Documentation
¶
Overview ¶
Package mcprev is the reverse-direction MCP transcoder: wraps an MCP server (speaking JSON-RPC over stdio) and exposes it as a codefly Toolbox gRPC server.
Why: the broader MCP ecosystem already ships dozens of servers (Anthropic-published, community). Without this adapter, using one with codefly would require rewriting it as a native Toolbox plugin. With it, any MCP server is a codefly toolbox for free — the host gets the spawn / sandbox / policy / routing layer, the LLM caller sees a normal Toolbox.
Mirror of core/toolbox/mcp, which goes the other direction (Toolbox gRPC → MCP JSON-RPC, the existing path Mind uses).
Lifecycle: ReverseTranscoder owns the stdio pair you give it (typically the spawned MCP server's stdin/stdout pipes). Call Initialize once before any other RPC; the handshake also negotiates the protocol version and reads the server's advertised name+version into Identity().
Index ¶
Constants ¶
const JSONRPCVersion = "2.0"
JSONRPCVersion is the pinned JSON-RPC field value, per spec.
const MCPProtocolVersion = "2024-11-05"
MCPProtocolVersion is the MCP revision we advertise on initialize. Aligned with the forward transcoder for consistency.
const MaxMCPErrorBytes = 4 * 1024
MaxMCPErrorBytes caps the error string we surface from isError=true. Errors flow into a different field but still hit the LLM; cap them shorter (4 KiB) since legitimate error text is rarely long.
const MaxMCPTextBytes = 64 * 1024
MaxMCPTextBytes caps any single text content block from an MCP server. The transcoder is the LLM-trust boundary for foreign MCP content: a hostile or buggy server could otherwise dump arbitrary bytes into the model's context. 64 KiB is generous for tool output but blunts the "fill the context window" attack.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ReverseTranscoder ¶
ReverseTranscoder wraps an MCP server's stdio and serves the codefly Toolbox gRPC contract on top.
Construct via New, then call Initialize before exposing the server through agents.Serve. After Initialize, the transcoder reads server identity (name, version) and is ready to relay tools/list and tools/call.
Concurrency: the underlying JSON-RPC stream is a single request/response channel — the transcoder serializes calls via callMu so the LLM-side gRPC server can multiplex without racing the wire.
func New ¶
New constructs a ReverseTranscoder over the given stdio pair. The caller is responsible for spawning the MCP server process and passing its stdin/stdout. closer (optional) is invoked when the transcoder is torn down — typically the cmd.Wait + pipe close.
func (*ReverseTranscoder) Close ¶
func (r *ReverseTranscoder) Close() error
Close tears down the underlying stdio pipes / subprocess if a closer was supplied at construction. Idempotent — closer is guarded by callMu so concurrent Close from a shutdown signal + gRPC handler doesn't race.
func (*ReverseTranscoder) Identity ¶
func (r *ReverseTranscoder) Identity(_ context.Context, _ *toolboxv0.IdentityRequest) (*toolboxv0.IdentityResponse, error)
Identity returns the wrapped MCP server's identity. Name and version come from the server's initialize response; description is generic since MCP doesn't expose a server-level description field (only per-tool ones).
func (*ReverseTranscoder) Initialize ¶
func (r *ReverseTranscoder) Initialize(ctx context.Context) error
Initialize performs the MCP initialize handshake and caches the remote server's identity + tool list. Must be called before exposing the transcoder via agents.Serve. Re-running it after a server crash is safe — state is replaced, not appended.
func (*ReverseTranscoder) Tools ¶
func (r *ReverseTranscoder) Tools() []*registry.ToolDefinition
Tools returns the tool catalog cached at Initialize time. The embedded registry.Base then projects this into ListTools / ListToolSummaries / DescribeTool / CallTool — same shape any native codefly toolbox uses.