Documentation
¶
Overview ¶
Package mcp connects burrow agents to Model Context Protocol servers, as pi's MCP extension does. The protocol and transports come from github.com/modelcontextprotocol/go-sdk; this package keeps one ServerConnection per server (connected on first use, reconnected when a call finds it gone), registers the servers' tools on an agent session through an Extension, and keeps OAuth credentials in a baseAgent.AuthStore.
Wiring an agent session to remote servers for one user:
handler, err := mcp.NewOAuthHandler(&mcp.OAuthOptions{
Store: store, OwnerID: userID, Server: "docs", ServerURL: serverURL,
HTTPClient: guarded, RedirectURL: "https://app.example/mcp/callback",
})
ext, err := mcp.NewExtension(mcp.ExtensionOptions{
Servers: []mcp.ServerConnectionOptions{{
Name: "docs", OAuth: handler,
CreateTransport: mcp.HTTPTransport(serverURL, &mcp.HTTPTransportOptions{HTTPClient: guarded}),
}},
Tools: session, // a *baseAgent.AgentSession
})
ext.Start()
defer ext.Close(ctx)
// Before each prompt:
ext.WaitForStartup(ctx)
ext.ReconnectSignedIn(ctx)
Local servers use StdioTransport, whose errors end with what the server last wrote to stderr.
A server whose user must sign in shows StateNeedsAuth in its status, and its tools return an error result whose ToolDetails has SignInRequired set. A local app such as a TUI signs in with Extension.SignIn, which uses a loopback callback and a pasted redirect URL as fallback. A web app sends the user to OAuthHandler.StartSignIn's URL; its callback finds the sign-in with FindPendingSignIn, for the owner of the app's own session, and passes the query to OAuthHandler.CompleteSignIn. ReconnectSignedIn then picks up the new tokens. Apps that host Client ID Metadata Documents set OAuthOptions.ClientMetadataDocument, for example with HostedClientMetadataDocument, instead of registering clients.
Close waits for a token refresh in progress, so rotated tokens are saved before the process exits.
Index ¶
- Constants
- Variables
- func CallbackID(serverURL string) (string, error)
- func ConvertResult(server, tool string, result *sdk.CallToolResult, opts *ConvertResultOptions) agent.AgentToolResult[any]
- func CreateResourceToolDefinitions(servers func() []ResourceServer) []agent.AgentTool[any, any]
- func CreateToolDefinition(opts ToolDefinitionOptions) agent.AgentTool[any, any]
- func CreateToolName(server, tool string, isTaken func(name string) bool) string
- func SignInMcpServer(ctx context.Context, handler *OAuthHandler, opts SignInOptions) error
- type ClientMetadataDocument
- type ClientMetadataDocumentFunc
- type ConvertResultOptions
- type Extension
- func (e *Extension) Close(ctx context.Context) error
- func (e *Extension) Connection(name string) *ServerConnection
- func (e *Extension) Connections() []*ServerConnection
- func (e *Extension) Logout(ctx context.Context, name string) error
- func (e *Extension) Reconnect(ctx context.Context, name string) error
- func (e *Extension) ReconnectSignedIn(ctx context.Context) error
- func (e *Extension) SignIn(ctx context.Context, name string, opts SignInOptions) error
- func (e *Extension) Start()
- func (e *Extension) WaitForStartup(ctx context.Context) bool
- type ExtensionOptions
- type HTTPTransportOptions
- type OAuthCallback
- type OAuthCallbackPage
- type OAuthCallbackServer
- type OAuthCallbackServerOptions
- type OAuthError
- type OAuthHandler
- func (h *OAuthHandler) Authorize(ctx context.Context, req *http.Request, resp *http.Response) error
- func (h *OAuthHandler) CompleteSignIn(ctx context.Context, query url.Values) error
- func (h *OAuthHandler) HTTPClient(base *http.Client) *http.Client
- func (h *OAuthHandler) SignOut(ctx context.Context) error
- func (h *OAuthHandler) SignedIn(ctx context.Context) (bool, error)
- func (h *OAuthHandler) StartSignIn(ctx context.Context) (string, error)
- func (h *OAuthHandler) TokenSource(ctx context.Context) (oauth2.TokenSource, error)
- func (h *OAuthHandler) Wait(ctx context.Context) error
- type OAuthOptions
- type PendingSignIn
- type RequestOptions
- type ResourceServer
- type ServerConnection
- func (c *ServerConnection) AllResourceTemplates(ctx context.Context, opts *RequestOptions) ([]*sdk.ResourceTemplate, error)
- func (c *ServerConnection) AllResources(ctx context.Context, opts *RequestOptions) ([]*sdk.Resource, error)
- func (c *ServerConnection) CallTool(ctx context.Context, name string, args map[string]any, opts *RequestOptions) (*sdk.CallToolResult, error)
- func (c *ServerConnection) Close(ctx context.Context) error
- func (c *ServerConnection) GetClient(ctx context.Context) (*sdk.ClientSession, error)
- func (c *ServerConnection) HasResources() bool
- func (c *ServerConnection) Instructions() string
- func (c *ServerConnection) Name() string
- func (c *ServerConnection) OAuth() *OAuthHandler
- func (c *ServerConnection) ReadResource(ctx context.Context, uri string, opts *RequestOptions) (*sdk.ReadResourceResult, error)
- func (c *ServerConnection) Reconnect(ctx context.Context) error
- func (c *ServerConnection) ResourceTemplatesPage(ctx context.Context, cursor string, opts *RequestOptions) (*sdk.ListResourceTemplatesResult, error)
- func (c *ServerConnection) ResourcesPage(ctx context.Context, cursor string, opts *RequestOptions) (*sdk.ListResourcesResult, error)
- func (c *ServerConnection) SignOut(ctx context.Context) error
- func (c *ServerConnection) Status() ServerStatus
- func (c *ServerConnection) Timeout() time.Duration
- func (c *ServerConnection) Tools() []*sdk.Tool
- type ServerConnectionOptions
- type ServerState
- type ServerStatus
- type SignInOptions
- type SignInPrompt
- type ToolCaller
- type ToolDefinitionOptions
- type ToolDetails
- type ToolRegistry
- type TransportFactory
Constants ¶
const ( ListResourcesTool = "list_mcp_resources" ListResourceTemplatesTool = "list_mcp_resource_templates" ReadResourceTool = "read_mcp_resource" )
Names of the resource tools. Codex and opencode use the same tools, so models trained on them use these unchanged.
const DefaultStartupWait = 10 * time.Second
DefaultStartupWait is how long WaitForStartup waits for servers still connecting when ExtensionOptions.StartupWait is zero.
const DefaultTimeout = 60 * time.Second
DefaultTimeout bounds connecting and each request when ServerConnectionOptions.Timeout is zero.
const OAuthNamespace = "mcp"
OAuthNamespace is the AuthStore namespace of MCP OAuth state.
const OutputMaxBytes = 20 * 1024
OutputMaxBytes is the size of model-facing text beyond which a result is cut in the middle.
Variables ¶
var ErrNoPendingSignIn = errors.New("mcp: no sign-in is waiting for this response; sign in again")
ErrNoPendingSignIn is returned when no started sign-in matches an authorization response's state.
var ErrSignInCancelled = errors.New("sign-in cancelled")
ErrSignInCancelled is returned by SignInMcpServer when the user or ctx cancels the sign-in.
var ErrSignInRequired = errors.New("sign-in required")
ErrSignInRequired is returned, wrapped, when only a new sign-in gives access to a server: nothing is stored, the refresh token is gone or was rejected, or the server asks for more scope. Connect and CallTool errors wrap it, so check them with errors.Is and offer StartSignIn.
Functions ¶
func CallbackID ¶
CallbackID is 12 characters identifying an MCP server URL in callback paths, computed like Codex does: the first 9 bytes of the SHA-256 of the URL without its fragment, in unpadded base64url.
func ConvertResult ¶
func ConvertResult(server, tool string, result *sdk.CallToolResult, opts *ConvertResultOptions) agent.AgentToolResult[any]
ConvertResult converts a tool result to model-facing content, within OutputMaxBytes. A result without content blocks becomes its structured content as JSON. An error result keeps its content and is marked IsError, getting a generic message when it has no text. opts may be nil.
func CreateResourceToolDefinitions ¶
func CreateResourceToolDefinitions(servers func() []ResourceServer) []agent.AgentTool[any, any]
CreateResourceToolDefinitions returns list_mcp_resources, list_mcp_resource_templates and read_mcp_resource. They take a server argument; servers returns the servers they reach, at call time. Listings are JSON, as in Codex. MCP App resources (ui:// URIs and profile=mcp-app HTML) are left out, since they are user interfaces for hosts that render them.
func CreateToolDefinition ¶
func CreateToolDefinition(opts ToolDefinitionOptions) agent.AgentTool[any, any]
CreateToolDefinition adapts one MCP tool to an agent tool. Progress notifications become tool updates. A call that fails because the user must sign in returns an error result with ToolDetails.SignInRequired set.
func CreateToolName ¶
CreateToolName is mcp__<server>__<tool>, sanitized and shortened with a hash suffix when too long. Like Codex, everything but [A-Za-z0-9_] becomes _. isTaken reports names used by a different MCP tool: sanitizing can map two tools to one name (a-b and a_b), which then get the hash suffix. isTaken may be nil.
func SignInMcpServer ¶
func SignInMcpServer(ctx context.Context, handler *OAuthHandler, opts SignInOptions) error
SignInMcpServer signs the user in to handler's server from a local app, such as a TUI: it uses the stored refresh token when possible, and otherwise runs the browser authorization code flow against a loopback callback. The tokens are stored like CompleteSignIn stores them. Cancelling ctx stops the sign-in with ErrSignInCancelled; requests to the authorization server are also time-limited.
Types ¶
type ClientMetadataDocument ¶
ClientMetadataDocument is a Client ID Metadata Document: an https URL the client uses as its client_id, and a redirect URI the document lists.
type ClientMetadataDocumentFunc ¶
type ClientMetadataDocumentFunc func(serverURL, redirectURL string, metadata *oauthex.AuthServerMeta) (*ClientMetadataDocument, error)
ClientMetadataDocumentFunc chooses the Client ID Metadata Document to sign in to serverURL with, given the redirect URI of the sign-in and the authorization server's metadata. It is called at every sign-in, and the result is stored with the tokens.
func HostedClientMetadataDocument ¶
func HostedClientMetadataDocument(baseURL string) ClientMetadataDocumentFunc
HostedClientMetadataDocument chooses documents served under baseURL, as pi chooses its own and Codex its. When the authorization server sends the iss parameter in authorization responses (RFC 9207), the document is baseURL/client.json and the redirect URI the one given. Otherwise the document and redirect URI are specific to the MCP server, so a response cannot be mixed up with one from another authorization server (RFC 9700 section 4.4.2.2): baseURL/<id>/client.json with the redirect path followed by /<id>, where id is CallbackID of the server URL. The app serves those documents and receives the authorization response on those paths too.
type ConvertResultOptions ¶
type ConvertResultOptions struct {
// ReadableResources reports that read_mcp_resource can read the server's
// resources, which resource links then name.
ReadableResources bool
}
ConvertResultOptions configures ConvertResult.
type Extension ¶
type Extension struct {
// contains filtered or unexported fields
}
Extension connects an agent session to MCP servers, as pi's MCP extension does. Each server's tools are registered when it connects and again when they change. Names stay stable for the session, since its history calls tools by name. Tools a server no longer offers are deactivated, and activated again if it offers them again. The resource tools are registered once a server offers resources.
Wire it into a session:
ext, err := mcp.NewExtension(mcp.ExtensionOptions{Servers: servers, Tools: session})
ext.Start()
defer ext.Close(ctx)
// Before each prompt:
ext.WaitForStartup(ctx)
ext.ReconnectSignedIn(ctx)
session.Prompt(ctx, text, nil)
func NewExtension ¶
func NewExtension(opts ExtensionOptions) (*Extension, error)
NewExtension creates the servers' connections. Call Start to connect them.
func (*Extension) Close ¶
Close closes every connection. See ServerConnection.Close.
func (*Extension) Connection ¶
func (e *Extension) Connection(name string) *ServerConnection
Connection is the connection of the server named name, or nil.
func (*Extension) Connections ¶
func (e *Extension) Connections() []*ServerConnection
Connections are the servers' connections, in the order configured.
func (*Extension) Logout ¶
Logout deletes the stored credentials of the server named name and disconnects it.
func (*Extension) ReconnectSignedIn ¶
ReconnectSignedIn reconnects the servers that need a sign-in when their credentials were stored since, for example by CompleteSignIn in another request or process. Call it before each prompt or turn.
func (*Extension) SignIn ¶
SignIn signs the user in to the server named name with SignInMcpServer, then reconnects. Closing the extension cancels it.
func (*Extension) Start ¶
func (e *Extension) Start()
Start connects every server in the background. Failures show in each connection's Status. Calling it again does nothing.
func (*Extension) WaitForStartup ¶
WaitForStartup lets the first prompt wait for the servers Start is still connecting, so their tools are declared in its first request, but not indefinitely: a slow or hanging server must not hold up the prompt. Its tools become available once it connects. Later calls return at once. It reports whether every server finished connecting.
type ExtensionOptions ¶
type ExtensionOptions struct {
// Servers are the servers to connect, with distinct names. The
// extension sets their OnTools; their OnChange is called after the
// extension's.
Servers []ServerConnectionOptions
// Tools receives the servers' tools and the resource tools. Required.
Tools ToolRegistry
// StartupWait is how long WaitForStartup waits for servers still
// connecting. Zero means DefaultStartupWait.
StartupWait time.Duration
}
ExtensionOptions configures an Extension.
type HTTPTransportOptions ¶
type HTTPTransportOptions struct {
// HTTPClient sends the requests. Nil means a default client. Apps that
// let users add servers should pass a client that refuses private
// addresses.
HTTPClient *http.Client
// Headers are sent with each request to the endpoint's origin, for
// example an API key for a server without OAuth. Headers the transport
// sets itself take precedence, among them the OAuth access token once the
// user has signed in, as in pi.
Headers map[string]string
}
HTTPTransportOptions configures HTTPTransport.
type OAuthCallback ¶
OAuthCallback is an authorization response.
type OAuthCallbackPage ¶
OAuthCallbackPage is the outcome shown on the browser page after the redirect.
type OAuthCallbackServer ¶
type OAuthCallbackServer struct {
// contains filtered or unexported fields
}
OAuthCallbackServer receives authorization responses on a loopback address, for apps such as a TUI where the browser runs on the user's machine.
func ListenOAuthCallback ¶
func ListenOAuthCallback(opts OAuthCallbackServerOptions) (*OAuthCallbackServer, error)
ListenOAuthCallback starts a callback server. Close it when done.
func (*OAuthCallbackServer) Close ¶
func (s *OAuthCallbackServer) Close() error
Close fails the waits in progress and stops the server.
func (*OAuthCallbackServer) RedirectURL ¶
func (s *OAuthCallbackServer) RedirectURL() string
RedirectURL is the URL of Path on the port the server listens on.
func (*OAuthCallbackServer) WaitForCallback ¶
func (s *OAuthCallbackServer) WaitForCallback(state, path string) (func(ctx context.Context) (*OAuthCallback, error), error)
WaitForCallback expects the authorization response with state, and returns a function that waits for it. Call it before sending the user to the authorization URL, since a response nobody expects is refused. With a path, the server receives responses on it too, and a response on another path fails, so a server-specific redirect URI can tell authorization servers apart (RFC 9700 section 4.4.2.2).
type OAuthCallbackServerOptions ¶
type OAuthCallbackServerOptions struct {
// Host is the address to listen on. Empty means 127.0.0.1.
Host string
// RedirectHost is the host name in the redirect URL, for example
// localhost for a client registered with it while listening on
// 127.0.0.1. Empty means Host.
RedirectHost string
// Port is the port to listen on. Zero means a free port.
Port int
// Path receives the callback. Empty means /callback.
Path string
// ExtraPaths receive the callback too, for example the server-specific
// path of a redirect URI.
ExtraPaths []string
// Timeout bounds each wait. Zero means 5 minutes.
Timeout time.Duration
// RenderPage renders the browser page as HTML. Nil means a plain-text
// message.
RenderPage func(OAuthCallbackPage) string
}
OAuthCallbackServerOptions configures ListenOAuthCallback.
type OAuthError ¶
OAuthError is an error response of an authorization server's token endpoint (RFC 6749 section 5.2).
func (*OAuthError) Error ¶
func (e *OAuthError) Error() string
type OAuthHandler ¶
type OAuthHandler struct {
// contains filtered or unexported fields
}
OAuthHandler authorizes requests to one MCP server for one owner. Set it as the OAuthHandler of an sdk.StreamableClientTransport, with OAuthHandler.HTTPClient as its HTTPClient, as HTTPTransport does.
Connections never start a browser flow on their own. They send the stored access token, refresh it when it is about to expire or after a 401, and otherwise fail with ErrSignInRequired. The app then signs the user in with StartSignIn and CompleteSignIn, which may run in different processes.
Many servers rotate refresh tokens, so two refreshes with the same refresh token lose the grant. Refreshes hold the store's lock from reading the tokens to saving new ones, in every process, and tokens that changed meanwhile are used without refreshing.
func NewOAuthHandler ¶
func NewOAuthHandler(opts *OAuthOptions) (*OAuthHandler, error)
NewOAuthHandler returns a handler for opts.Server and opts.OwnerID.
func (*OAuthHandler) Authorize ¶
Authorize handles a 401 or 403 from the server. It refreshes the rejected token, or returns ErrSignInRequired when only a new sign-in helps. It implements auth.OAuthHandler.
func (*OAuthHandler) CompleteSignIn ¶
CompleteSignIn finishes the sign-in StartSignIn began, given the query of the authorization server's redirect to RedirectURL. It checks the state and issuer, exchanges the code for tokens, and stores them.
func (*OAuthHandler) HTTPClient ¶
func (h *OAuthHandler) HTTPClient(base *http.Client) *http.Client
HTTPClient returns base, nil meaning a default client, with a transport that reports ErrSignInRequired when the server rejects the tokens Authorize just refreshed. Use it as the HTTPClient of the sdk.StreamableClientTransport the handler authorizes; HTTPTransport does. The SDK retries a request once after Authorize and reports a second 401 as a plain error that breaks the connection, so without it a server that rejects every token makes each connect refresh again and fail instead of asking the user to sign in.
func (*OAuthHandler) SignOut ¶
func (h *OAuthHandler) SignOut(ctx context.Context) error
SignOut deletes everything stored for the server, including the client registration.
func (*OAuthHandler) SignedIn ¶
func (h *OAuthHandler) SignedIn(ctx context.Context) (bool, error)
SignedIn reports whether tokens are stored for the server. They may still be rejected.
func (*OAuthHandler) StartSignIn ¶
func (h *OAuthHandler) StartSignIn(ctx context.Context) (string, error)
StartSignIn begins signing in. It discovers the authorization server, registers a client if needed, stores the pending request, and returns the URL to send the user to. The authorization server redirects the user to RedirectURL; pass that request's query to CompleteSignIn, in any process. Starting again replaces the pending request.
func (*OAuthHandler) TokenSource ¶
func (h *OAuthHandler) TokenSource(ctx context.Context) (oauth2.TokenSource, error)
TokenSource returns the stored access token, refreshed first when it is about to expire, or nil when there is none. It implements auth.OAuthHandler.
func (*OAuthHandler) Wait ¶
func (h *OAuthHandler) Wait(ctx context.Context) error
Wait returns once no store update of this handler is running, or with ctx's error when ctx is done first. Call it before the process exits: a refresh or code exchange the server already answered may have rotated the refresh token, and exiting before the new tokens are saved loses the grant. Updates keep running when the request that started them is cancelled, so they can still be in progress after every request returned.
type OAuthOptions ¶
type OAuthOptions struct {
// Store keeps the state of each owner's sign-in: client registration,
// tokens and the pending authorization request. Required.
Store baseAgent.AuthStore
// OwnerID is the user or tenant the credentials belong to.
OwnerID string
// Server names the server. With ServerURL it keys the stored state, so
// servers sharing a URL keep separate accounts. Required.
Server string
// ServerURL is the MCP endpoint. Required.
ServerURL string
// HTTPClient sends discovery, registration and token requests. Apps that
// let users add servers should pass a client that refuses private
// addresses, and use it for the transport too. Nil means a default client.
HTTPClient *http.Client
// RequestTimeout bounds each request to the authorization server. Zero
// means 15 seconds.
RequestTimeout time.Duration
// RedirectURL receives the authorization response; pass its query to
// CompleteSignIn. It may be specific to the server, so the callback
// knows which handler to complete. Required to sign in.
RedirectURL string
// ClientID and ClientSecret identify a client registered with the
// authorization server beforehand. Without ClientID, sign-in registers
// one dynamically (RFC 7591) and stores it.
ClientID string
ClientSecret string
// ClientName is the client_name of dynamic registration. Empty means
// "burrow".
ClientName string
// ClientMetadataDocument, when set and ClientID is empty, identifies the
// client with a Client ID Metadata Document instead of registering it
// dynamically. See [HostedClientMetadataDocument].
ClientMetadataDocument ClientMetadataDocumentFunc
// Scope lists scopes, separated by spaces, to request in addition to the
// ones the server asks for.
Scope string
// AuthServerMetadataURL is an authorization server metadata document
// (RFC 8414 or OpenID Connect discovery) to use instead of discovery
// through the server, for servers that advertise a wrong authorization
// server or none. The document is trusted as configured, so its issuer is
// not checked. It must use HTTPS, except on loopback hosts.
AuthServerMetadataURL string
// Now returns the current time. Nil means time.Now.
Now func() time.Time
}
OAuthOptions configures an OAuthHandler.
type PendingSignIn ¶
PendingSignIn identifies the server of a started sign-in.
func FindPendingSignIn ¶
func FindPendingSignIn(ctx context.Context, store baseAgent.AuthStore, ownerID, state string) (*PendingSignIn, error)
FindPendingSignIn finds ownerID's started sign-in that the authorization response with state belongs to, for apps with one redirect URL for every server. Construct the result's OAuthHandler and pass the response to its CompleteSignIn. It returns ErrNoPendingSignIn when none matches.
ownerID must come from the app's own authenticated session, never from the response. A lookup across owners would let an attacker send a victim the authorization URL of the attacker's sign-in: the victim's grant would then complete it, storing the victim's tokens under the attacker's account (login CSRF, RFC 9700 section 4.7).
type RequestOptions ¶
type RequestOptions struct {
// Timeout bounds the request, restarting at each progress notification
// when OnProgress is set. Zero leaves it bounded only by its context.
Timeout time.Duration
// OnProgress receives the server's progress notifications for the
// request. Nil means the request does not ask for progress.
OnProgress func(*sdk.ProgressNotificationParams)
}
RequestOptions are the options of one request to a server.
type ResourceServer ¶
type ResourceServer interface {
Name() string
Timeout() time.Duration
ResourcesPage(ctx context.Context, cursor string, opts *RequestOptions) (*sdk.ListResourcesResult, error)
ResourceTemplatesPage(ctx context.Context, cursor string, opts *RequestOptions) (*sdk.ListResourceTemplatesResult, error)
AllResources(ctx context.Context, opts *RequestOptions) ([]*sdk.Resource, error)
AllResourceTemplates(ctx context.Context, opts *RequestOptions) ([]*sdk.ResourceTemplate, error)
ReadResource(ctx context.Context, uri string, opts *RequestOptions) (*sdk.ReadResourceResult, error)
}
ResourceServer is a connected server that offers resources. ServerConnection implements it.
type ServerConnection ¶
type ServerConnection struct {
// contains filtered or unexported fields
}
ServerConnection is one configured server. It connects on first use and reconnects lazily when a call finds the connection gone. Callbacks run without its lock held, so they may call its methods.
func NewServerConnection ¶
func NewServerConnection(opts ServerConnectionOptions) (*ServerConnection, error)
NewServerConnection returns a connection that has not connected yet. Call GetClient to connect.
func (*ServerConnection) AllResourceTemplates ¶
func (c *ServerConnection) AllResourceTemplates(ctx context.Context, opts *RequestOptions) ([]*sdk.ResourceTemplate, error)
AllResourceTemplates lists every page of resource templates.
func (*ServerConnection) AllResources ¶
func (c *ServerConnection) AllResources(ctx context.Context, opts *RequestOptions) ([]*sdk.Resource, error)
AllResources lists every page of resources.
func (*ServerConnection) CallTool ¶
func (c *ServerConnection) CallTool(ctx context.Context, name string, args map[string]any, opts *RequestOptions) (*sdk.CallToolResult, error)
CallTool calls the server's tool name. It is not retried after a transient error, since the tool may have run.
func (*ServerConnection) Close ¶
func (c *ServerConnection) Close(ctx context.Context) error
Close closes the connection and returns once no transport of this server is open, including one that was still connecting, and no refresh of its tokens is saving. A refresh the server already answered may have rotated the refresh token; exiting before the new tokens are saved would lose the grant. It returns early with ctx's error.
func (*ServerConnection) GetClient ¶
func (c *ServerConnection) GetClient(ctx context.Context) (*sdk.ClientSession, error)
GetClient returns the connected session, connecting first if needed. Concurrent callers share one connect. Cancelling ctx stops waiting, not the connect.
func (*ServerConnection) HasResources ¶
func (c *ServerConnection) HasResources() bool
HasResources reports whether the server offers resources, which the resource tools list and read on demand. They are not listed at connect: listing every resource can take long (a large drive, say).
func (*ServerConnection) Instructions ¶
func (c *ServerConnection) Instructions() string
Instructions are the server's instructions from initialize, describing its tools as a group.
func (*ServerConnection) OAuth ¶
func (c *ServerConnection) OAuth() *OAuthHandler
OAuth is the handler that authorizes requests, or nil.
func (*ServerConnection) ReadResource ¶
func (c *ServerConnection) ReadResource(ctx context.Context, uri string, opts *RequestOptions) (*sdk.ReadResourceResult, error)
ReadResource reads the resource at uri.
func (*ServerConnection) Reconnect ¶
func (c *ServerConnection) Reconnect(ctx context.Context) error
Reconnect connects again with fresh credentials, for example after signing in.
func (*ServerConnection) ResourceTemplatesPage ¶
func (c *ServerConnection) ResourceTemplatesPage(ctx context.Context, cursor string, opts *RequestOptions) (*sdk.ListResourceTemplatesResult, error)
ResourceTemplatesPage lists one page of resource templates, starting at cursor. Servers that do not implement resources/templates/list have none.
func (*ServerConnection) ResourcesPage ¶
func (c *ServerConnection) ResourcesPage(ctx context.Context, cursor string, opts *RequestOptions) (*sdk.ListResourcesResult, error)
ResourcesPage lists one page of resources, starting at cursor.
func (*ServerConnection) SignOut ¶
func (c *ServerConnection) SignOut(ctx context.Context) error
SignOut disconnects after the stored credentials were removed.
func (*ServerConnection) Status ¶
func (c *ServerConnection) Status() ServerStatus
Status is the connection's state and why it is in it.
func (*ServerConnection) Timeout ¶
func (c *ServerConnection) Timeout() time.Duration
Timeout bounds connecting and each request.
func (*ServerConnection) Tools ¶
func (c *ServerConnection) Tools() []*sdk.Tool
Tools are the tools the server offered when last listed.
type ServerConnectionOptions ¶
type ServerConnectionOptions struct {
// Name names the server in tool names, labels and messages. Required.
Name string
// CreateTransport returns the transport of each connection attempt.
// Required.
CreateTransport TransportFactory
// OAuth authorizes requests to a server that signs users in with OAuth.
// It is passed to CreateTransport.
OAuth *OAuthHandler
// Timeout bounds connecting and each request; for tool calls, the time
// between progress notifications. Zero means DefaultTimeout.
Timeout time.Duration
// Client identifies the client to the server. Nil means burrow.
Client *sdk.Implementation
// OnTools is called when the server's tools were listed: after each
// connect and when the server reports that they changed.
OnTools func(*ServerConnection)
// OnChange is called when the status or the tools change.
OnChange func(*ServerConnection)
}
ServerConnectionOptions configures a ServerConnection.
type ServerState ¶
type ServerState string
ServerState is the state of a ServerConnection.
const ( StateConnecting ServerState = "connecting" StateConnected ServerState = "connected" // StateDisconnected means the connection dropped, for example because // the stdio server exited. The next call reconnects. StateDisconnected ServerState = "disconnected" // StateNeedsAuth means the user must sign in; see [ErrSignInRequired]. StateNeedsAuth ServerState = "needs-auth" StateFailed ServerState = "failed" StateClosed ServerState = "closed" )
type ServerStatus ¶
type ServerStatus struct {
State ServerState
// Error says why the server failed or disconnected, or that refreshing
// its tools failed.
Error string
}
ServerStatus is the state of a ServerConnection and why it is in it.
type SignInOptions ¶
type SignInOptions struct {
// Prompt shows the authorization URL and asks for the redirect URL.
// Required.
Prompt SignInPrompt
// CallbackURL is the loopback redirect URI. Empty means
// http://127.0.0.1/callback. One with a port is sent exactly as
// written, since servers compare it as a string; localhost is served on
// 127.0.0.1.
CallbackURL string
// CallbackPort is the port of a CallbackURL without one. Zero means the
// port of the stored client's redirect URI, so it stays valid, else a
// free port.
CallbackPort int
// RenderPage renders the browser page after the redirect as HTML. Nil
// means a plain-text message.
RenderPage func(OAuthCallbackPage) string
}
SignInOptions configures SignInMcpServer.
type SignInPrompt ¶
type SignInPrompt interface {
// ShowAuthorizationURL shows the authorization URL to the user and opens
// it in a browser.
ShowAuthorizationURL(url string)
// PromptForRedirectURL asks for the redirect URL from the browser
// address bar, for when the browser cannot reach the loopback callback
// (for example over SSH). ctx is cancelled once the callback arrives or
// the sign-in is cancelled. An empty answer cancels the sign-in. A
// prompt that cannot ask waits for ctx and returns its error.
PromptForRedirectURL(ctx context.Context) (string, error)
}
SignInPrompt asks the user to authorize in a browser.
type ToolCaller ¶
type ToolCaller interface {
CallTool(ctx context.Context, name string, args map[string]any, opts *RequestOptions) (*sdk.CallToolResult, error)
}
ToolCaller calls tools of one server. ServerConnection implements it.
type ToolDefinitionOptions ¶
type ToolDefinitionOptions struct {
// Server names the server in labels and messages.
Server string
Tool *sdk.Tool
// Name is the agent tool name, from [CreateToolName].
Name string
// Timeout bounds each call, restarting at each progress notification.
// Zero leaves calls bounded only by their context.
Timeout time.Duration
// GetClient returns the caller at execution time, so a tool outlives the
// connection it was listed on.
GetClient func(ctx context.Context) (ToolCaller, error)
// ReadableResources reports whether read_mcp_resource can read the
// server's resources, which resource links then name. Nil means it
// cannot.
ReadableResources func() bool
}
ToolDefinitionOptions configures CreateToolDefinition.
type ToolDetails ¶
type ToolDetails struct {
Server string `json:"server"`
Tool string `json:"tool"`
// StructuredContent is the result's structured content, if any. It is
// never truncated.
StructuredContent any `json:"structuredContent,omitempty"`
// SignInRequired reports that the call failed because the user must sign
// in to Server (see [ErrSignInRequired]); the result is an error result
// saying so. Apps check it in tool events to offer sign-in. Details
// restored from a session store are decoded JSON, not ToolDetails.
SignInRequired bool `json:"signInRequired,omitempty"`
}
ToolDetails are the details of every MCP tool result and update.
type ToolRegistry ¶
type ToolRegistry interface {
// RegisterTool adds a tool, active, or replaces the tool of that name,
// keeping whether it is active.
RegisterTool(tool agent.AgentTool[any, any]) error
GetActiveToolNames() ([]string, error)
// SetActiveToolsByName activates the named tools and deactivates the
// rest, ignoring unknown names.
SetActiveToolsByName(names []string) error
}
ToolRegistry is where an Extension registers tools. baseAgent.AgentSession implements it: a tool registered during a prompt is declared from the prompt's next turn.
type TransportFactory ¶
type TransportFactory func(oauth *OAuthHandler) (sdk.Transport, error)
TransportFactory returns a new transport for each connection attempt. When oauth is not nil, the transport must authorize its requests with it, and send them with its HTTPClient.
func HTTPTransport ¶
func HTTPTransport(endpoint string, opts *HTTPTransportOptions) TransportFactory
HTTPTransport connects to a streamable HTTP endpoint. Nil opts means the default client and no headers.
func StdioTransport ¶
func StdioTransport(command func() *exec.Cmd) TransportFactory
StdioTransport runs a stdio server. command returns the process to start for each connection attempt; set its Dir and Env there. The end of what the server writes to stderr is added to the error when it fails to connect or exits. A Stderr the command sets still receives all of it.