mcp

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package mcp serves a set of the agent's tools to a Model Context Protocol client over a JSON-RPC 2.0 stdio transport, so an external program (another agent's harness, an editor, any MCP client) can call the agent's tools without being handed the host directly.

The point of the server is where a called tool runs: every tools/call is routed through the same dispatch waist as a native loop, so the caller's effects are admitted against the run's capability grant, gated by the containment level its trust requires, subject to the safety brakes, and recorded on the event spine. Presence in tools/list makes a tool reachable, never automatically permitted: authority is decided at the waist at call time, exactly as it is for the agent's own loop. A client that is denied sees an ordinary error tool result and can adapt, while the denial lands on the spine as a rejected action.

The server is a pure protocol and routing layer. It holds no grant and no brake of its own: the governance bindings ride on the context passed to Serve (the caller binds the run's grant with capability.Into and the run id with brakes.Into, the same way the mission executor does before it dispatches), and the server propagates that context into every Govern call. So a host that wants a read-only session binds a narrow grant; a host that wants a kill-switch binds the brakes; the server needs no knowledge of either.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Info

type Info struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

Info identifies a party in the initialize handshake: the server's name and version reported to the client, and the shape the client reports back.

type Option

type Option func(*Server)

Option configures a Server at construction.

func WithGoal

func WithGoal(id string) Option

WithGoal sets the goal id every governed tool call runs under, so the actions a client drives are threaded onto the same goal as the run that hosts the server. Empty means the calls belong to no specific goal.

func WithInfo

func WithInfo(i Info) Option

WithInfo sets the server identity reported in the initialize handshake. A zero Info reports a default name and an empty version.

func WithScope

func WithScope(s state.Scope) Option

WithScope sets the scope every governed tool call is attributed to on the spine, so a session's actions are located on the instance/project/workspace axis like any native action. The zero scope is the global scope.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server exposes a fixed set of mission.Tools to one MCP client connection and governs every call through a dispatch waist. Construct it with NewServer and run it with Serve. It is safe to reuse across sequential connections, but a single Serve call drives one connection.

func NewServer

func NewServer(d *dispatch.Dispatcher, tools []mission.Tool, opts ...Option) *Server

NewServer builds a server that serves tools through d. Tools are keyed by name; a later tool with a duplicate name replaces an earlier one, and tools/list reports each name once in first-registration order. A nil dispatcher is replaced with a zero-config one (allow-all, discard sink), so the server is usable standalone, though a real host passes a governed dispatcher.

func (*Server) HTTPHandler

func (s *Server) HTTPHandler(base context.Context, token string) http.Handler

HTTPHandler adapts the server to the Model Context Protocol streamable-HTTP transport, so a client that connects to a URL rather than spawning a subprocess (an in-process loopback bridge is the motivating case) drives the same governed tools over one HTTP endpoint. Each POST carries one JSON-RPC message and gets its reply as a single application/json body; the tools here answer synchronously, so the handler never needs to open a server-sent-event stream.

base is the governed context the handler dispatches under: the caller binds the run's capability grant with capability.Into and the run id with brakes.Into before constructing the handler, exactly as for the stdio Serve path, and every request is served on a context derived from base so a run-level halt or shutdown cancels an in-flight call. token, when non-empty, is a bearer token the client must present, so a loopback port a co-tenant could also reach is not open to it.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, r io.Reader, w io.Writer) error

Serve reads newline-delimited JSON-RPC messages from r, dispatches each, and writes replies to w, until r reaches EOF or ctx is cancelled. It returns nil on a clean client disconnect (EOF) or context cancellation, and a wrapped error only on an unrecoverable transport failure. Governance bindings on ctx (the run's grant and brakes) are propagated into every tool call; a caller that wants a governed session binds them before calling Serve.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL