Files
kb/openspec/changes/archive/2026-04-04-kb-v3-mcp-server/specs/mcp-server/spec.md
T
2026-04-04 22:50:19 +01:00

10 KiB

MCP Server

Purpose

The MCP server provides a Model Context Protocol interface to the kb engine, exposing knowledge base operations as native MCP tools over Streamable HTTP transport. It runs as a separate Docker container alongside the engine, translating MCP tool calls into engine HTTP API calls.

Requirements

Requirement: MCP server transport and deployment

The MCP server SHALL expose tools via Streamable HTTP transport. It SHALL run as a Docker container, configured to connect to the kb engine's HTTP API. It SHALL read KB_ENGINE_URL and KB_API_KEY from environment variables to connect to the engine.

Scenario: MCP server starts and connects to engine

  • WHEN the MCP server container starts with KB_ENGINE_URL=http://engine:8000 and KB_API_KEY=secret
  • THEN it SHALL begin accepting MCP connections over Streamable HTTP and use the configured URL and API key for all engine API calls

Scenario: Engine unreachable at startup

  • WHEN the MCP server starts but cannot reach the engine at KB_ENGINE_URL
  • THEN it SHALL start and accept connections, but tool calls SHALL return errors indicating the engine is unreachable

Scenario: Docker Compose deployment

  • WHEN the MCP server is deployed via Docker Compose alongside the engine
  • THEN it SHALL connect to the engine via the Docker network using the service name (e.g. http://engine:8000)

Requirement: MCP server authentication

The MCP server SHALL require Bearer token authentication from calling agents via the KB_MCP_API_KEY environment variable. This is independent of the engine's KB_API_KEY.

Scenario: Valid MCP API key

  • WHEN KB_MCP_API_KEY is set and a calling agent provides a matching Bearer token
  • THEN the MCP server SHALL process the request normally

Scenario: Missing MCP API key when required

  • WHEN KB_MCP_API_KEY is set and a calling agent connects without a Bearer token
  • THEN the MCP server SHALL reject the connection with an authentication error

Scenario: Invalid MCP API key

  • WHEN KB_MCP_API_KEY is set and a calling agent provides a non-matching Bearer token
  • THEN the MCP server SHALL reject the connection with an authentication error

Scenario: MCP auth disabled

  • WHEN KB_MCP_API_KEY is not set
  • THEN the MCP server SHALL accept all connections without authentication

Requirement: Search tool

The MCP server SHALL expose a kb_search tool that queries the knowledge base via the engine's search API.

  • WHEN an agent calls kb_search with {"query": "pension revaluation", "top": 5}
  • THEN the MCP server SHALL POST to the engine's /api/v1/search endpoint and return the results with chunk text, scores, document metadata, and tags

Scenario: Search with collection filter

  • WHEN an agent calls kb_search with {"query": "email preferences", "collection": "memory"}
  • THEN the MCP server SHALL add collection:memory to the tags filter and POST to the engine's search endpoint

Scenario: Search with tags and collection

  • WHEN an agent calls kb_search with {"query": "feedback", "tags": ["email"], "collection": "memory"}
  • THEN the MCP server SHALL combine the explicit tags with collection:memory in the tag filter

Scenario: Search results strip collection tags

  • WHEN the engine returns search results containing tags ["collection:memory", "feedback", "email"]
  • THEN the MCP server SHALL strip collection:* tags from the tags array and add a separate collection field, returning {"collection": "memory", "tags": ["feedback", "email"], ...}

Scenario: Search with mode override

  • WHEN an agent calls kb_search with {"query": "error log", "fts_only": true}
  • THEN the MCP server SHALL pass fts_only: true to the engine search endpoint

Requirement: Add note tool

The MCP server SHALL expose a kb_addnote tool that submits a text note to the engine for ingestion.

Scenario: Add a note with default collection

  • WHEN an agent calls kb_addnote with {"text": "User prefers concise responses"}
  • THEN the MCP server SHALL submit the note to the engine's POST /api/v1/jobs endpoint with the tag collection:documents and return the job ID

Scenario: Add a note to a specific collection

  • WHEN an agent calls kb_addnote with {"text": "User prefers concise responses", "collection": "memory", "tags": ["feedback"]}
  • THEN the MCP server SHALL submit the note with tags ["collection:memory", "feedback"] to the engine

Scenario: Add a note to a collection replaces existing collection tag

  • WHEN an agent calls kb_addnote with {"text": "some note", "collection": "memory"} and the note is ingested
  • THEN the resulting document SHALL have exactly one collection:* tag: collection:memory

Requirement: Chunked file upload tools

The MCP server SHALL expose a three-step chunked file upload pattern for transferring files from remote agents to the engine.

Scenario: Start an upload

  • WHEN an agent calls kb_upload_start with {"filename": "report.pdf", "total_size": 5242880, "tags": ["insurance"], "collection": "documents"}
  • THEN the MCP server SHALL create a staging entry, generate a UUID upload_id, and return {"upload_id": "<uuid>"}

Scenario: Upload a chunk

  • WHEN an agent calls kb_upload_chunk with {"upload_id": "<uuid>", "data": "<base64-encoded-data>", "chunk_index": 0}
  • THEN the MCP server SHALL decode the base64 data and write it to the staging area for the given upload

Scenario: Upload multiple chunks in sequence

  • WHEN an agent calls kb_upload_chunk multiple times with sequential chunk_index values for the same upload_id
  • THEN the MCP server SHALL store each chunk and track the sequence

Scenario: Finish an upload

  • WHEN an agent calls kb_upload_finish with {"upload_id": "<uuid>"}
  • THEN the MCP server SHALL reassemble the chunks in order, forward the complete file as a multipart upload to the engine's POST /api/v1/jobs endpoint with the tags from kb_upload_start (including collection:<name>), and return the job ID

Scenario: Upload with invalid upload_id

  • WHEN an agent calls kb_upload_chunk or kb_upload_finish with an upload_id that does not exist
  • THEN the MCP server SHALL return an error indicating the upload ID is not found

Scenario: Abandoned upload cleanup

  • WHEN an agent starts an upload but does not call kb_upload_finish within 10 minutes
  • THEN the MCP server SHALL clean up the staged chunks and remove the upload tracking entry

Scenario: MCP server restart during upload

  • WHEN the MCP server container restarts while an upload is in progress
  • THEN the in-progress upload SHALL be lost and the agent SHALL need to restart from kb_upload_start

Requirement: Update note tool

The MCP server SHALL expose a kb_update_note tool that updates an existing note in place via the engine's note mutation endpoint.

Scenario: Update an existing note

  • WHEN an agent calls kb_update_note with {"document_id": 42, "text": "Updated preference: user prefers bullet points"}
  • THEN the MCP server SHALL send PATCH /api/v1/notes/42 to the engine and return the updated document

Scenario: Update a non-existent document

  • WHEN an agent calls kb_update_note with a document_id that does not exist
  • THEN the MCP server SHALL return an error indicating the document was not found

Scenario: Update a non-note document

  • WHEN an agent calls kb_update_note with a document_id that refers to a PDF
  • THEN the MCP server SHALL return an error indicating that only notes can be updated

Requirement: Get document tool

The MCP server SHALL expose a kb_get tool that retrieves document details from the engine.

Scenario: Get by document ID

  • WHEN an agent calls kb_get with {"document_id": 42}
  • THEN the MCP server SHALL fetch GET /api/v1/documents/42 and return the document details with chunks

Scenario: Get by source path

  • WHEN an agent calls kb_get with {"source_path": "memory/feedback_testing.md"}
  • THEN the MCP server SHALL query the engine's documents endpoint filtered by source path and return matching documents

Scenario: Get results strip collection tags

  • WHEN the engine returns document details with tags including collection:memory
  • THEN the MCP server SHALL strip collection:* from tags and present a separate collection field

Requirement: Status tool

The MCP server SHALL expose a kb_status tool that returns engine health and statistics.

Scenario: Get engine status

  • WHEN an agent calls kb_status with no parameters
  • THEN the MCP server SHALL fetch GET /api/v1/status and return engine version, model info, device info, document counts, and queue state

Requirement: Jobs tool

The MCP server SHALL expose a kb_jobs tool that returns ingestion job status.

Scenario: List recent jobs

  • WHEN an agent calls kb_jobs with no parameters
  • THEN the MCP server SHALL fetch GET /api/v1/jobs and return the list of recent jobs

Scenario: Filter jobs by status

  • WHEN an agent calls kb_jobs with {"status": "failed"}
  • THEN the MCP server SHALL fetch GET /api/v1/jobs?status=failed and return matching jobs

Requirement: Collection management via tags

The MCP server SHALL manage collections using tag conventions. The MCP server SHALL enforce exclusive collection membership — a document SHALL belong to exactly one collection.

Scenario: Default collection on addnote

  • WHEN an agent calls kb_addnote without specifying a collection
  • THEN the MCP server SHALL apply the tag collection:documents

Scenario: Explicit collection on addnote

  • WHEN an agent calls kb_addnote with {"collection": "memory"}
  • THEN the MCP server SHALL apply the tag collection:memory

Scenario: Exclusive collection enforcement

  • WHEN a document already has the tag collection:documents and an operation changes its collection to memory
  • THEN the MCP server SHALL first remove collection:documents via the engine's tag API, then add collection:memory

Scenario: Collection field in search results

  • WHEN search results include documents with collection:* tags
  • THEN the MCP server SHALL present the collection as a top-level collection field and exclude collection:* from the tags array