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
- func Canonical(raw []byte) ([]byte, error)
- func CheckURL(raw string) error
- func DefinitionDigest(name, description string, input, output json.RawMessage) (string, error)
- func Digest(t *sdk.Tool) (string, error)
- func Failed(name string) string
- func Loopback(host string) bool
- func MergeLabels(configured, added []string) []string
- func NotRun(name string) string
- func NotTaken(tool, arg string) string
- func RequestMeta(call agentloop.Call, sendLabels bool) sdk.Meta
- func ResultLabels(meta map[string]any) ([]string, string)
- func SessionEnded(name string) string
- func Stopped(name string) string
- func ToResult(name string, cfg ToolConfig, output *jsonschema.Schema, r *sdk.CallToolResult) agentloop.Result
- type Client
- type DriftError
- type Listed
- type Server
- type ToolConfig
Constants ¶
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.
const ( Image = "image" Audio = "audio" ResourceLink = "resource_link" Resource = "resource" )
The kinds of non-text content a tool can be allowed to return.
const DefaultMaxMessageBytes = 1 << 20
DefaultMaxMessageBytes caps one message from the server when Server.MaxMessageBytes is zero.
const DefaultStartTimeout = 30 * time.Second
DefaultStartTimeout bounds a restart when Server.StartTimeout is zero.
Variables ¶
This section is empty.
Functions ¶
func Canonical ¶
Canonical is JSON with object keys sorted, no insignificant whitespace, no HTML escaping and numbers as written, as agentloop.InputDigest uses.
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 ¶
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 Loopback ¶
Loopback reports whether a host name is this machine: localhost or a loopback address.
func MergeLabels ¶
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 ¶
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 ¶
NotTaken is what the model is told of a call that gave an argument the operator fixed or hid.
func RequestMeta ¶
RequestMeta is the _meta sent with a call: the call id, and with sendLabels the session's labels, sorted and never null.
func ResultLabels ¶
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 ¶
SessionEnded is what the model is told of a call a remote server refused because it had ended the session.
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 ¶
Connect starts the server, lists its tools and checks them against the allowlist and the digests given.
func (*Client) Digests ¶
Digests returns the pinned digest of each allowed tool, by the name the agent knows it by (its alias).
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.
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.