Skip to content

feat(server): set FastMCP instructions= so MCP clients see multi-agent recipe#477

Merged
tsdata merged 1 commit intomainfrom
docs/mcp-instructions-multi-agent
Apr 25, 2026
Merged

feat(server): set FastMCP instructions= so MCP clients see multi-agent recipe#477
tsdata merged 1 commit intomainfrom
docs/mcp-instructions-multi-agent

Conversation

@memtomem
Copy link
Copy Markdown
Owner

Summary

memtomem's MCP server constructed FastMCP without an instructions=
argument:

mcp = FastMCP("memtomem", lifespan=app_lifespan)

The MCP spec's initialize response carries an instructions field
that clients auto-inject into every LLM session alongside the tool
list — but memtomem left it empty, so LLMs had only per-tool
docstrings to go on. When users asked for per-agent isolation, clients
were quietly defaulting to plain mem_add instead of routing through
mem_agent_share. Surfaced while walking the v0.1.28 multi-agent
test scenarios from memtomem-docs (same trail that produced #473
and #475).

This PR threads a workflow-recipe string through instructions= so
every client gets the same hint, paste-free.

What the recipe covers

  • Single-agent quickstartmem_add / mem_search, default
    namespace. The 90% case stays one line.
  • Multi-agent recipe in ordermem_agent_register
    mem_session_start(agent_id=...)mem_agent_search /
    mem_agent_sharemem_session_end.
  • Namespace conventionsdefault / agent-runtime:<id> /
    shared: with one-line descriptions.
  • Pitfalls — notably that mem_add without namespace= consults
    current_namespace, not the session's agent-runtime:* scope, so
    multi-agent writes must go through mem_agent_share. Caught while
    reviewing fix(sessions): mem_session_start derives namespace from agent_id #475.

Full string lives in packages/memtomem/src/memtomem/server/instructions.py
so it's grep-able and reusable.

Why this PR (vs. docs / per-tool docstring edits)

  • Per-tool docstrings are seen only when the LLM has already
    picked a tool — they don't help with the routing decision.
  • A separate USAGE.md snippet would require every user to paste
    it into CLAUDE.md / system prompt manually. The MCP instructions
    channel auto-injects.
  • Prior art — memtomem-stm already uses instructions= (visible
    in any session that has both servers connected). FastMCP supports
    the parameter natively; no SDK changes needed.

Test plan

Pin tests in packages/memtomem/tests/test_server_instructions.py
mirror test_server_version_reporting.py (#383):

  • Unit: mcp.instructions == INSTRUCTIONS and every workflow
    token (tool name or namespace prefix) appears in the constant.
    Renames force both halves to move in lockstep.
  • E2E: drives the initialize JSON-RPC call against a real
    subprocess, parses the response, and asserts the instructions
    field round-trips. Catches FastMCP regressions that drop or
    strip the parameter.
  • uv run pytest packages/memtomem/tests/test_server_instructions.py -v
    — 12 / 12 pass.
  • uv run pytest -m "not ollama" — 2457 / 2457 pass, 46
    deselected, no regressions.
  • uv run ruff check packages/memtomem/src packages/memtomem/tests
    and ruff format --check — clean.

Backward compat

  • No tool signatures change; only the server-level initialize
    response gains a non-empty instructions field.
  • Clients that ignore the field (older MCP libraries, custom clients)
    see no behavioral difference.

Follow-ups (out of scope)

  • Optional memtomem-docs/USAGE-multi-agent.md longer-form recipe if
    the 50-line instructions= proves too thin in practice. The pin
    test makes it safe to deepen the constant in place first.

🤖 Generated with Claude Code

…ecipe

Tool docstrings alone left LLMs guessing which memtomem tool to call
when users asked for per-agent isolation — clients silently fell back
to plain `mem_add` instead of `mem_agent_share`. The MCP spec's
`initialize` response carries an `instructions` field that clients
auto-inject into every LLM session alongside the tool list, but
memtomem's `FastMCP("memtomem", lifespan=app_lifespan)` constructor
call left it unset. Pass a workflow-recipe string instead.

Content covers: single-agent quickstart (`mem_add` / `mem_search`),
the multi-agent recipe in order (`mem_agent_register` →
`mem_session_start` → `mem_agent_search` / `mem_agent_share` →
`mem_session_end`), namespace conventions (`default` /
`agent-runtime:<id>` / `shared:`), and pitfalls — notably that
`mem_add` without `namespace=` consults `current_namespace` rather
than the active session's `agent-runtime:*` scope, so multi-agent
write paths must go through `mem_agent_share`.

Source of truth lives in `memtomem/server/instructions.py` so the
constant is grep-able and reusable. The existing `serverInfo.version`
patch in `server/__init__.py` (#383) is the closest prior art for
tweaking the initialize response.

Pin tests in `tests/test_server_instructions.py` mirror
`test_server_version_reporting.py`:

- Unit test asserts `mcp.instructions == INSTRUCTIONS` and that every
  workflow token an LLM has to recognize (tool name or namespace
  prefix) appears in the constant — renames must move both halves
  in lockstep.
- E2E test drives the `initialize` RPC against a real subprocess and
  asserts the `instructions` field round-trips, so a future FastMCP
  release that drops the parameter is still caught.

Complements PR #475: now that `mem_session_start` derives
`agent-runtime:<agent_id>`, the LLM also knows when to invoke it.

Co-Authored-By: Claude <[email protected]>
Copy link
Copy Markdown
Collaborator

@tsdata tsdata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — reviewed in /review. CI green, pin tests mirror #383 pattern, all referenced tools/conventions verified against source.

@tsdata tsdata merged commit 8c036ab into main Apr 25, 2026
7 checks passed
@tsdata tsdata deleted the docs/mcp-instructions-multi-agent branch April 25, 2026 14:25
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 25, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants