MCP servers, over streamable HTTP
A server is a row with a URL; its tools are discovered by a button and cached, then offered beside the built-in ones. Written by hand rather than taken from the reference SDK, because that SDK's transport does its own connecting -- and the one thing that must not be bypassed is check_url on every hop. Owning the transport is the point; the framing beside it is the small part. Sessions are per call: initialize, initialized, the call, a best-effort DELETE. Caching one wants an owner, a TTL, eviction, a lock and a shutdown hook, and the server may expire it under all of that anyway -- ToolContext is a session-free snapshot precisely so nothing in a tool holds live state. A server's names and descriptions reach the model as instructions and are bounded before they do; what it returns is escaped preformatted text, never markdown. Tools are namespaced per server, so two servers exposing "search" do not collide and neither shadows a built-in. Also: a round's calls now run together under a semaphore, results indexed so each tool turn stays paired with its call, and generation.status names what is running -- a remote tool is latency-bound, and a silent pause is what a hang looks like. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
"""An MCP client: remote servers over streamable HTTP.
|
||||
|
||||
Three parts. `protocol` is the wire format and nothing else -- it knows no
|
||||
database and no HTTP. `client` owns the transport, which is where the SSRF guard
|
||||
lives and the reason none of this comes from the reference SDK. `registry` is
|
||||
where a row becomes a tool the chat loop can be offered.
|
||||
|
||||
Local stdio servers are deliberately absent. Spawning a subprocess is the
|
||||
agentic-execution feature, which wants a confirmation model before it does
|
||||
anything; a URL is a different act with a different blast radius.
|
||||
"""
|
||||
|
||||
from lembas.services.mcp.client import McpSpec, call_tool, list_tools, spec_from
|
||||
from lembas.services.mcp.protocol import McpError
|
||||
from lembas.services.mcp.registry import offer_name, refresh, tool_defs
|
||||
|
||||
__all__ = [
|
||||
"McpError",
|
||||
"McpSpec",
|
||||
"call_tool",
|
||||
"list_tools",
|
||||
"offer_name",
|
||||
"refresh",
|
||||
"spec_from",
|
||||
"tool_defs",
|
||||
]
|
||||
Reference in New Issue
Block a user