Help us shape the future of Go! Take the 2026 Go Developer Survey

mcp

package
v0.0.0-...-6272484 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package mcp gives an agent the tools of one MCP server as agentloop.Tool values. The server is a child process spoken to over stdio, or a remote one spoken to over streamable HTTP (see http.go).

The caller's configuration is the authority. It names the tools the agent may have (an allowlist) and gives each its labels. A tool the server lists that is not on the allowlist is ignored, and an allowlisted tool the server lacks is an error. The server's tool annotations are never used.

Each allowed tool's definition (name, description, input and output schema) is pinned by its SHA-256 (Digest) when the client connects. A definition that differs from the digest the caller gave, or on Reconnect from the one pinned, is an error.

The client declares no capabilities and handles no requests from the server: no sampling, elicitation or roots. A result that asks for input fails the call, and a request from the server breaks the connection until Reconnect.

A result is text. Image, audio, resource_link and embedded resource content fail the call unless the tool allows the kind, and even then the model sees only a placeholder, except for the text of an embedded text resource. A tool with an outputSchema shows the model only its structuredContent, validated against that schema and serialised again. Whenever a result cannot be used the model is told only "The tool <name> failed.", and the reason goes to Result.Log.

The server process gets exactly the argv, environment and directory it is configured with, and runs in a process group of its own that is killed when the client closes.

A tool's FixedArgs and HiddenArgs narrow what the model may send: both are taken out of the schema the model is shown, a call that names either is refused before the server sees it, and the fixed values are added to every call.

Index

Constants

View Source
const (
	// LabelsKey holds the session's labels on a request (when the server
	// is sent them) and the labels a result adds on a response.
	LabelsKey = "com.kirahowe.agentloop/labels"
	// CallIDKey holds agentloop's id for the call on a request.
	CallIDKey = "com.kirahowe.agentloop/call-id"
)

The _meta keys agentloop uses, under its own reverse-DNS prefix.

View Source
const (
	Image        = "image"
	Audio        = "audio"
	ResourceLink = "resource_link"
	Resource     = "resource"
)

The kinds of non-text content a tool can be allowed to return.

View Source
const DefaultMaxMessageBytes = 1 << 20

DefaultMaxMessageBytes caps one message from the server when Server.MaxMessageBytes is zero.

View Source
const DefaultStartTimeout = 30 * time.Second

DefaultStartTimeout bounds a restart when Server.StartTimeout is zero.

Variables

This section is empty.

Functions

func Canonical

func Canonical(raw []byte) ([]byte, error)

Canonical is JSON with object keys sorted, no insignificant whitespace, no HTML escaping and numbers as written, as agentloop.InputDigest uses.

func CheckURL

func CheckURL(raw string) error

CheckURL says why a remote server's URL cannot be used, or nil.

func DefinitionDigest

func DefinitionDigest(name, description string, input, output json.RawMessage) (string, error)

DefinitionDigest is Digest from the parts. An empty output means the tool has no outputSchema.

func Digest

func Digest(t *sdk.Tool) (string, error)

Digest is the SHA-256, in hex, of a tool's definition: its name, description, inputSchema and outputSchema as canonical JSON. The annotations are left out: they decide nothing, and the SDK would have to encode them again, so the digest would follow the SDK's version.

func Failed

func Failed(name string) string

Failed is all the model is told of a call whose result cannot be used.

func Loopback

func Loopback(host string) bool

Loopback reports whether a host name is this machine: localhost or a loopback address.

func MergeLabels

func MergeLabels(configured, added []string) []string

MergeLabels is the configured labels with those a result adds: sorted, no repeats, nil when there are none. A result can only add.

func NotRun

func NotRun(name string) string

NotRun is what the model is told of a call that was never sent, because the server stopped or broke the protocol earlier.

func NotTaken

func NotTaken(tool, arg string) string

NotTaken is what the model is told of a call that gave an argument the operator fixed or hid.

func RequestMeta

func RequestMeta(call agentloop.Call, sendLabels bool) sdk.Meta

RequestMeta is the _meta sent with a call: the call id, and with sendLabels the session's labels, sorted and never null.

func ResultLabels

func ResultLabels(meta map[string]any) ([]string, string)

ResultLabels reads the labels a result adds from its _meta. No key is no labels. Anything but an array of valid labels is why the call fails.

func SessionEnded

func SessionEnded(name string) string

SessionEnded is what the model is told of a call a remote server refused because it had ended the session.

func Stopped

func Stopped(name string) string

Stopped is what the model is told when the server died during a call.

func ToResult

func ToResult(name string, cfg ToolConfig, output *jsonschema.Schema, r *sdk.CallToolResult) agentloop.Result

ToResult turns a tools/call result into what the agent records. It is pure. output is the tool's compiled outputSchema, or nil.

Types

type Client

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

A Client is a connection to one server and the tools it gives.

func Connect

func Connect(ctx context.Context, srv Server) (*Client, error)

Connect starts the server, lists its tools and checks them against the allowlist and the digests given.

func (*Client) Close

func (c *Client) Close() error

Close stops the server and everything in its process group.

func (*Client) Digests

func (c *Client) Digests() map[string]string

Digests returns the pinned digest of each allowed tool, by the name the agent knows it by (its alias).

func (*Client) Reconnect

func (c *Client) Reconnect(ctx context.Context) error

Reconnect stops the server, if it is running, and starts it again. Every allowed tool must have the definition pinned when the client first connected; to accept a changed one, Connect again with its new digest. Nothing reconnects on its own.

func (*Client) Tools

func (c *Client) Tools() []agentloop.Tool

Tools returns the allowed tools, by name.

type DriftError

type DriftError struct {
	Server, Tool, Pinned, Got string
}

A DriftError says an allowed tool's definition is not the pinned one.

func (*DriftError) Error

func (e *DriftError) Error() string

type Listed

type Listed struct {
	Name         string               `json:"name"`
	Title        string               `json:"title,omitempty"`
	Description  string               `json:"description"`
	Annotations  *sdk.ToolAnnotations `json:"annotations,omitempty"`
	InputSchema  json.RawMessage      `json:"input_schema"`
	OutputSchema json.RawMessage      `json:"output_schema,omitempty"`
	Digest       string               `json:"digest"`
}

A Listed tool is one a server lists, with its digest, for an operator choosing which tools to allow.

func List

func List(ctx context.Context, srv Server) ([]Listed, error)

List connects to a server, lists every tool it has, by name, and closes. srv.Tools is not used. A tool whose schema cannot be read fails the listing, as it would fail Connect.

type Server

type Server struct {
	// Name is the operator's name for the server, used in errors.
	Name string
	// Argv is the program and its arguments, for a server run over stdio.
	Argv []string
	// URL is a remote server's endpoint, spoken to over streamable HTTP,
	// in place of Argv. It must pass CheckURL.
	URL string
	// Token gives the bearer token sent to a remote server, or is nil to
	// send none. renew is set after the server refused the token it gave
	// (a 401), so it may get a new one.
	Token func(ctx context.Context, renew bool) (string, error)
	// HTTPTransport carries a remote server's requests. Nil means one
	// like Go's default, with no proxy.
	HTTPTransport http.RoundTripper
	// Env is the whole environment, as K=V, of a stdio server. Nil means
	// empty: nothing is inherited.
	Env []string
	// Dir is the working directory. Empty means the current one.
	Dir string
	// Stderr receives what the server writes to stderr, for the
	// operator. Nil discards it.
	Stderr io.Writer
	// SendLabels sends the session's labels in each call's _meta. Off,
	// the server does not learn them. The call id is always sent.
	SendLabels bool
	// Restart starts a server that has died, or whose connection was
	// lost, again for the next call, which must find every definition as
	// pinned. Off, only Reconnect starts it again. A server that broke the
	// protocol, or whose restart found a changed definition, is never
	// restarted on its own.
	Restart bool
	// StartTimeout bounds a restart. Zero means DefaultStartTimeout.
	StartTimeout time.Duration
	// Tools is the allowlist: each tool the agent may call, by the name
	// the server gives it.
	Tools map[string]ToolConfig
	// MaxMessageBytes caps one JSON-RPC message from the server. Zero
	// means DefaultMaxMessageBytes.
	MaxMessageBytes int
}

A Server is one MCP server and the tools an agent may use from it.

type ToolConfig

type ToolConfig struct {
	// Alias is the name the agent, the model and the policy know the tool
	// by. Empty means the server's name for it.
	Alias string
	// Labels are carried by every result of the tool.
	Labels []string
	// Digest pins the tool's definition. Empty accepts whatever the
	// server lists, and Client.Digests says what that was.
	Digest string
	// AllowContent lists the non-text content kinds a result may carry
	// (Image, Audio, ResourceLink, Resource). The model sees a
	// placeholder for each, never the content, except that an embedded
	// resource holding text (not a blob) is shown as that text.
	AllowContent []string
	// FixedArgs are arguments set for every call, by name, as JSON. The
	// model is not shown them and a call that gives one is refused.
	FixedArgs map[string]json.RawMessage
	// HiddenArgs are arguments the model is not shown, and a call that
	// gives one is refused. A required argument cannot be hidden.
	HiddenArgs []string
}

A ToolConfig is one allowed tool.

Jump to

Keyboard shortcuts

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