Files
chemenu/instructions/mcp-read-server.md
T
torben 2c4c2b1c7c
CI / verify (push) Failing after 57s
Release / release (push) Successful in 37s
stack: TOC-Pflicht fuer Referenzdateien ueber 100 Zeilen (docs toc); session-setup.md/gates.md nennen die tatsaechliche Budget-Ausnahmeliste (schliesst #73, #76)
Files changed:
- AGENTS.md
- CHANGES.md
- VERSION
- instructions/CONTRACT.md
- instructions/capture-session.md
- instructions/claude-code-model-selection.md
- instructions/dev/issue-tracking.md
- instructions/dev/testing-conventions.md
- instructions/dev/version-parts.md
- instructions/evolve-subtypes.md
- instructions/gates.md
- instructions/german-terminology.md
- instructions/ingest-large-tree.md
- instructions/kb-profiles.md
- instructions/link-taxonomy.md
- instructions/mcp-read-server.md
- instructions/migrate-corpus.md
- instructions/migrations/3.0.0-authoring-conventions.md
- instructions/migrations/4.0.0-link-taxonomy.md
- instructions/private-instance.md
- instructions/session-setup.md
- instructions/setup-instance.md
- kb/CONTRACT.md
- kb/CONVENTIONS.md
- kb/concepts/COLLECTION.md
- raw/CONTRACT.md
- tools/CONTRACT.md
- tools/chemenu/commands/docs_verify.py
- tools/chemenu/commands/instructions_cmd.py
- tools/chemenu/tests/test_docs_verify.py
- tools/chemenu/tests/test_instructions_cmd.py
- tools/chemenu/tests/test_toc.py
- tools/chemenu/toc.py
- types/type-spec.md
2026-09-09 20:38:42 +02:00

5.5 KiB

type, name, description
type name description
types/instruction.md mcp-read-server Run and keep current the MCP read server that serves this wiki to a second consumer

Running the MCP read server

Chemenu has a second consumer. search, types, describe_type, lint and status are served over MCP to callers that are not this terminal - the CLI and the server are two adapters over one core (chemenu.api.Corpus), not a CLI with a network interface bolted on.

This document is about operating it: how to start it, what has to be true of the checkout it serves, and how that checkout stays current. What it exposes and why is in tools/CONTRACT.md and in the module's own docstring (tools/chemenu/mcp/server.py).

Deployment is deliberately not here. Which cluster, which ingress host, where the credential lives - that is private infrastructure and this is a public repository. What is here is everything an operator needs that is true of the software rather than of one installation.

Contents

When to run

  • Standing something up for a consumer that is not a terminal on this machine.
  • Diagnosing an answer that looks stale, or one that disagrees with the CLI.
  • Before pointing a new consumer at an existing server.

Steps

  1. Install the server's dependency. It is deliberately not in requirements.txt: an instance that only uses the CLI should not be made to install pydantic, starlette, uvicorn and cryptography to do it.

    tools/.venv/bin/pip install -r tools/requirements-mcp.txt
    
  2. Decide which checkout it serves. The root resolves by precedence - an explicit --root, then $CHEMENU_ROOT, then the checkout the package lives in. A deployment points at its corpus with one variable and no code:

    export CHEMENU_ROOT=/srv/chemenu
    
  3. Take tracing out of the served tree. The server refuses to start otherwise, and the refusal is the point: telemetry defaults to on and writes under reports/telemetry/ inside the repo, which step 5's sync is entitled to wipe. Either is fine:

    export WIKI_TRACE=0                      # off
    export WIKI_TRACE_DIR=/var/log/chemenu   # or elsewhere, outside the corpus
    
  4. Start it on the transport that matches what is in front of it.

    tools/.venv/bin/python -m chemenu.mcp                                # stdio
    tools/.venv/bin/python -m chemenu.mcp --transport streamable-http    # deployed
    

    stdio is for developing and testing without a network - one process per consumer, started locally. streamable-http is what a deployed instance speaks, and the only one the authentication middleware can sit in front of, because that middleware is an HTTP reverse proxy. sse is reachable through the SDK and deliberately not offered: it is the superseded remote transport, and building on it now only moves the migration later.

  5. Keep the checkout current by polling, and keep it clean.

    git -C "$CHEMENU_ROOT" fetch --quiet origin && \
      git -C "$CHEMENU_ROOT" reset --hard --quiet origin/main
    

    Every few minutes, from a timer beside the server. Polling rather than a webhook on purpose: it needs no inbound endpoint and no signature checking, which is a smaller surface than the thing it would optimize. A webhook is a later optimization, not a starting point.

    reset --hard is load-bearing, not a convenience. The corpus cache reuses a parse while the commit is unchanged and refuses to cache a dirty tree at all, so a checkout that has drifted answers correctly but reparses on every request - and every answer it gives is stamped "commit": null, because a dirty tree corresponds to no revision.

Decision points

  • An answer looks stale? Read commit in the response. If it names an old revision, the sync is not running. If it is null, the served tree has uncommitted changes - something is writing into the corpus that should not be.
  • The server disagrees with wikitool on the same query? That is a defect, not a configuration difference: the two go through the same functions and a golden test holds their output together (tools/chemenu/tests/test_mcp_server.py). Check first that both are pointed at the same root - CHEMENU_ROOT is easy to set for one and not the other.
  • Asked to expose a write tool? There is none, and the way to add one is not a flag. The server imports nothing under chemenu.commands, so new, touch, xref, cite, publish and migrate are unreachable from it rather than filtered out of a list. Submitting documents from outside is a different design, with a quarantine in it - not a tool added here.
  • Asked to rate-limit inside the server? Rate limiting belongs in the middleware in front of the process, next to authentication. Not the Iteration Budget Gate: that exists to stop an agent session from iterating unnoticed over the wiki's state, which is why retrieval is exempt from it, and using it as a rate limiter would dilute it into one.

Scope

Not for setting up an instance (setup-instance.md) or a fresh clone (bootstrap.md). Not for the authentication or rate-limiting middleware, which is infrastructure configuration rather than part of this repository. Not a write path: see the decision point above.