Skip to content

refactor(mcp-binding): every bound route is an alias of one @preload function, mcp.tool - #52

Merged
acn-ericlaw merged 2 commits into
mainfrom
refactor/mcp-binding-preload
Nov 14, 2026
Merged

acn-ericlaw merged 2 commits into
mainfrom
refactor/mcp-binding-preload

Conversation

@acn-ericlaw

Copy link
Copy Markdown
Collaborator

What

The MCP binding's routes were served by a closure that a factory (_handler) made per allowlisted tool and registered at
boot. They are now aliases of one function, mcp_tool, declared with @preload(route="mcp.tool", instances=10, private=True)
like any composable function: mcp.tool itself is private and bound to no tool (a call to it is a 404), and the boot
registers each allowlisted tool's route as an alias of it with the server's instances - default_registry.register(route, mcp_tool, ...), the pack's counterpart of the engines' Platform.register. A call learns the route it was addressed to
from its execution context, get_trace().route, the pack's counterpart of the engines' read-only my_route header, and
that route names the server and the remote tool. The route contract, the servers file and the shared vector file are
unchanged. The tests now call the routes through PostOffice local RPC, the path behind the HTTP host, and pin the shape
(every bound route's handler is mcp_tool, public, with the server's instances; mcp.tool private). README and CHANGELOG
describe it. ruff clean, basedpyright 0 errors, 46 binding tests and the suite's 397 passed; driven live through the
public Mermaid Chart MCP server: the bound route 200 with the server's structured content, mcp.tool 403 on the wire, a
non-map body 400, an unknown route 404.

Why

Eric asked which function serves diagram.render.mcp and found a closure where the composable style has a declared
function; this aligns the binding with llm.chat and mcp.health without changing ADR-0033's shape (one route per
allowlisted remote tool, certified on the graph's catalog). A generic client with one route addressed by server and tool
was considered and set aside: the ADR rejects it as alternative (c), and its certifiable form would need a headers map on
the catalog row in both engines.

🤖 Generated with Claude Code
Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com

acn-ericlaw and others added 2 commits November 14, 2026 18:47
…function, mcp.tool

The function serving the binding's routes was a closure made by a factory and registered
per tool. It is now mcp_tool, declared with @preload like any composable function, private
and bound to no tool; the boot registers each allowlisted tool's route as an alias of it
with the server's instances, and a call reads the route it was addressed to from its
execution context (get_trace().route, the pack's counterpart of the engines' my_route).
The tests call the routes through PostOffice local RPC, the path behind the HTTP host; the
shape was also driven live through the public Mermaid Chart MCP server.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@acn-ericlaw
acn-ericlaw merged commit 25c2fc6 into main Nov 14, 2026
5 checks passed
acn-ericlaw added a commit that referenced this pull request Nov 14, 2026
…e as landed

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant