Integrate: a new MCP server#

wenchang.mcp.build_server(...) returns a new mcp 2.x MCPServer that carries the memory prompt as its instructions, the seven memory tools, and the prompt resource wenchang://memory-prompt. You run it with server.run(...). Quickstart builds one end to end for Claude Code; this page covers every argument and both transports.

Compatibility: mcp 2.x MCPServer only. The mcp extra installs mcp>=2.2,<3, and the adapter targets mcp.server.mcpserver.MCPServer. FastMCP servers and mcp 1.x servers do not work: with mcp 1.x installed, importing wenchang.mcp raises ImportError, and register_memory_tools raises TypeError("server must be an MCPServer, not ...") for any other server type. For another framework, see Integrate without MCP.

Install with the extra: pip install "wenchang[mcp] @ git+https://github.com/msiebert/wenchang@v0.1.1".

Arguments#

Every argument is keyword-only. build_server checks them all before it creates the server, and raises TypeError or ValueError for a bad one.

Argument Required What it does
slots yes A PromptSlots. The server's instructions are build_memory_prompt(slots). See Customizing the prompts.
client yes A TransportClient, normally InProcessClient(MemoryStore(...)). Tool calls run concurrently on worker threads and share it. See Threads for what is safe to share.
resolver yes Your IdentityResolver. On this path it runs on every tool call. Its resolve must be a plain synchronous method; an async one raises TypeError at registration. See Identity.
policy yes A ScopePolicy: the roles that may write each scope.
credentials_from_context yes A plain (non-async) function that takes the MCP request Context and returns the raw credentials your resolver verifies. See Credentials.
source yes The surface name added to each written file's sources metadata. Non-empty.
product no Your product's name, put in the first line of each tool description. One non-empty line.
tool_prefix no Registers each tool as {tool_prefix}_{name}. 1 to 64 letters, digits, _ or -, starting and ending with a letter or digit.
on_call no A plain function called with a ToolCallRecord after every tool call. See Observing calls.
name no The server name. Default "wenchang".

The server's version is the installed wenchang version. Names on the tools has more on product, tool_prefix, and source.

Where the guidance goes#

Some clients, including Claude Desktop and claude.ai, ignore the server's instructions. The server therefore also puts the core rules where every client sees them:

instructions and the wenchang://memory-prompt resource are unchanged. wenchang.mcp.mcp_tool_descriptions(slots=None, product=None) returns the descriptions the server registers. Startup raises ValueError if one exceeds MAX_TOOL_DESCRIPTION_CHARS (2000), which only a very long purpose can cause. The core tool_descriptions() and MemoryTools.descriptions() are unchanged, since a non-MCP integrator owns its system prompt.

Two things help the agent find and use the tools. Keep purpose short and specific, because tool search matches on it. Give the connector a short, descriptive display name so the model recognizes when it applies.

Credentials#

Every tool call runs credentials_from_context(ctx), passes the result to your resolver, and binds that caller's own tools. ctx.headers holds the request headers on HTTP and is None on stdio. Return the raw value and leave verification to the resolver. If the function raises, the call fails with a permanent ResolverFailureError, and only the exception's type is logged, since its message may carry the credential.

Transports#

Observing calls#

on_call receives a wenchang.observer.ToolCallRecord after every tool call (wenchang.mcp re-exports it). On this path:

Calls MCP rejects while validating arguments never produce a record. An exception the observer raises is logged at ERROR and swallowed. The reference lists every field.

Next#