mcp

package module
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Jul 3, 2026 License: MIT Imports: 24 Imported by: 7

README

MCP Server Library for Go

A Go library for building Model Context Protocol (MCP) servers with a clean, fluent API.

Features

  • HTTP & Stdio Transports: Serve the same tools over HTTP or newline-delimited JSON-RPC on stdin/stdout, and consume remote servers over either
  • Simple API: Fluent interface for defining tools and parameters
  • Type Safety: Strongly typed parameter access with automatic conversion
  • Rich Responses: Support for text, image, audio, resource, and structured content
  • TOON Support: Compact, human-readable JSON encoding for LLM prompts
  • Thread Safe: Concurrent request handling with mutex protection
  • Remote Servers: Connect to and proxy remote MCP servers with authentication
  • Remote Search: Delegate tool_search to remote servers to discover hidden tools
  • Parallel Tool Calls: Execute multiple tools concurrently and collect all results in one call
  • Searchable Tools: Reduce context window usage with on-demand tool discovery
  • Dynamic Tool Providers: Load tools from external sources (databases, scripts, APIs)
  • Per-User Remote Servers: Request-scoped RemoteProvider for federating remote MCP servers with per-user auth, filtering, and caching
  • Provider Composition: Combine providers with MultiProvider using clear miss/error semantics
  • MCP Compliant: Full support for protocol versions 2024-11-05 through 2025-11-25

Installation

go get github.com/paularlott/mcp

Quick Start

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"

    "github.com/paularlott/mcp"
)

func main() {
    // Create server
    server := mcp.NewServer("my-server", "1.0.0")

    // Register a tool
    server.RegisterTool(
        mcp.NewTool("greet", "Greet someone",
            mcp.String("name", "Name to greet", mcp.Required()),
            mcp.String("greeting", "Custom greeting"),
        ),
        func(ctx context.Context, req *mcp.ToolRequest) (*mcp.ToolResponse, error) {
            name, _ := req.String("name")
            greeting := req.StringOr("greeting", "Hello")
            return mcp.NewToolResponseText(fmt.Sprintf("%s, %s!", greeting, name)), nil
        },
    )

    // Start server
    http.HandleFunc("/mcp", server.HandleRequest)
    log.Fatal(http.ListenAndServe(":8000", nil))
}

Transports

The same server and its tools can be served over two transports.

HTTP

Mount the server as an http.Handler (as in Quick Start above):

http.HandleFunc("/mcp", server.HandleRequest)
Stdio

Serve the MCP protocol over stdin/stdout (newline-delimited JSON-RPC 2.0) — the transport a host launches as a subprocess. ServeStdio blocks until stdin reaches EOF; keep stdout for protocol frames only and send logs to stderr:

server := mcp.NewServer("my-server", "1.0.0")
// ... RegisterTool(...) as usual ...
if err := server.ServeStdio(context.Background()); err != nil {
    log.Fatal(err)
}

Use ServeStream(ctx, in, out) to serve over any pair of streams (for example an in-process pipe) rather than the process's own stdio.

A client connects to a stdio server by launching it as a subprocess:

client, err := mcp.NewStdioClient("my-server-binary", []string{"--flag"}, "")
if err != nil {
    log.Fatal(err)
}
defer client.Close()

tools, _ := client.ListTools(ctx)
resp, _ := client.CallTool(ctx, "greet", map[string]any{"name": "Ada"})

NewStdioClient accepts options such as WithClientStderr, WithClientEnv, and WithClientDir. To talk to a server over streams you already hold, use NewStreamClient(in, out, namespace). The stdio transport is built on the paularlott/jsonrpc package. The client API (ListTools, CallTool, namespacing, filtering) is identical across HTTP and stdio.

CallToolsParallel and ExecuteDiscoveredToolsParallel send every call as a single JSON-RPC batch over the stdio transport (one round-trip instead of one per call), falling back to concurrent individual calls over HTTP. Either way, results are always returned in call order.

Documentation

For comprehensive guides, patterns, and API documentation, see the docs/ directory:

Get Started
  • Tool Providers - Dynamic tool loading, per-request providers, visibility control, and show-all mode
  • Tool Discovery - Searchable tools and context window optimization
How-To Guides

Tool Discovery Mode

The server supports two modes for tool visibility, selectable via HTTP header:

Header-Based Mode Selection

Clients can request show-all mode (useful for MCP server chaining):

POST /mcp HTTP/1.1
Content-Type: application/json
X-MCP-Show-All: true

{"jsonrpc":"2.0","id":1,"method":"initialize",...}

Or via query parameter: /mcp?show_all=true

Normal Mode (default): Native tools visible in tools/list. If discoverable tools exist, tool_search and execute_tool are also available.

Show-All Mode: ALL tools visible in tools/list including discoverable ones. This is useful when chaining MCP servers together.

Discoverable Tools

Tools can be marked as discoverable, meaning they won't appear in the normal tools/list but can be found via tool_search:

// Discoverable tool using the fluent builder
server.RegisterTool(
    mcp.NewTool("specialized_tool", "A specialized tool").Discoverable("keyword1", "keyword2"),
    handler,
)

With session management enabled, the mode is stored in the session token. See Tool Discovery Guide for details.

Examples

See the examples/ directory for complete, runnable examples:

Testing

Run tests to ensure everything works:

go test ./...

View specific test categories:

# Provider tests
go test -run TestAddRemoveProviders -v

# Dynamic tool state transitions
go test -run TestDynamicToolState -v

# Full test suite
go test -v

Documentation

Index

Constants

View Source
const (
	MCPProtocolVersionLatest = "2025-11-25"
	MCPProtocolVersionMin    = "2024-11-05"

	// DefaultSessionTTL is the default session lifetime for JWT session management
	DefaultSessionTTL = 30 * time.Minute

	// DefaultOAuthRefreshTimeout is the default timeout for OAuth token refresh operations
	DefaultOAuthRefreshTimeout = 30 * time.Second
)
View Source
const (
	// ErrorCodeParseError indicates invalid JSON was received by the server.
	// Use when the request body cannot be parsed as JSON.
	ErrorCodeParseError = -32700

	// ErrorCodeInvalidRequest indicates the JSON sent is not a valid Request object.
	// Use when required fields are missing or have wrong types.
	ErrorCodeInvalidRequest = -32600

	// ErrorCodeMethodNotFound indicates the method does not exist or is not available.
	// Used internally when an unknown MCP method is called.
	ErrorCodeMethodNotFound = -32601

	// ErrorCodeInvalidParams indicates invalid method parameters.
	// Use this in tool handlers when required parameters are missing or invalid.
	// Prefer using NewToolErrorInvalidParams() helper.
	ErrorCodeInvalidParams = -32602

	// ErrorCodeInternalError indicates an internal JSON-RPC error.
	// Use this in tool handlers for unexpected server-side errors.
	// Prefer using NewToolErrorInternal() helper.
	ErrorCodeInternalError = -32603

	// ErrorCodeImplementationErrorStart is the start of the implementation-defined
	// server error range (-32000 to -32099). Use codes in this range for
	// application-specific errors. Create with NewToolError().
	ErrorCodeImplementationErrorStart = -32000

	// ErrorCodeImplementationErrorEnd is the end of the implementation-defined
	// server error range.
	ErrorCodeImplementationErrorEnd = -32099
)

MCP JSON-RPC Error Codes These are standard JSON-RPC 2.0 error codes used by the MCP protocol. See: https://www.jsonrpc.org/specification#error_object

View Source
const (
	ToolSearchName  = "tool_search"
	ExecuteToolName = "execute_tool"
)

Discovery tool names

View Source
const DefaultRemoteToolCacheMaxEntries = 1024

DefaultRemoteToolCacheMaxEntries bounds the number of distinct cache keys a RemoteProvider keeps tool lists for. It exists so a CacheKey that embeds a per-user/per-tenant identifier cannot grow the cache without limit. Override with WithMaxCacheEntries.

View Source
const DefaultRemoteToolCacheTTL = 60 * time.Second

DefaultRemoteToolCacheTTL is the default lifetime for cached remote tool lists when a RemoteProviderConfig does not specify CacheTTL.

View Source
const ShowAllHeader = "X-MCP-Show-All"

ShowAllHeader is the HTTP header used to show all tools regardless of visibility

View Source
const ShowAllQueryParam = "show_all"

ShowAllQueryParam is the query parameter used to show all tools (fallback)

Variables

View Source
var (
	ErrUnknownTool      = errors.New("unknown tool")
	ErrUnknownParameter = errors.New("parameter not found")
	ErrToolFiltered     = errors.New("tool is filtered out")
)
View Source
var DefaultNamespaceSeparator = "__"

DefaultNamespaceSeparator is the default separator used for namespacing tool names. Uses "__" by default for broad client compatibility (some clients such as AntiGravity and PhpStorm reject tool names containing dots even though the MCP spec allows them).

Functions

func GenerateSigningKey added in v0.6.6

func GenerateSigningKey() ([]byte, error)

GenerateSigningKey creates a cryptographically secure random signing key

func GetShowAllFromRequest added in v0.10.0

func GetShowAllFromRequest(r *http.Request) bool

GetShowAllFromRequest extracts the show-all flag from an HTTP request. It first checks the X-MCP-Show-All header, then falls back to the show_all query parameter. Returns true if either is set to "true" (case-insensitive).

func GetShowAllTools added in v0.10.0

func GetShowAllTools(ctx context.Context) bool

GetShowAllTools returns true if show-all mode is enabled in the context.

func NewToolError

func NewToolError(code int, message string, data any) error

NewToolError creates a custom MCP error with a specific code. Use codes in the range -32000 to -32099 for application-specific errors. The data parameter can include additional error details and will be serialized to JSON.

Example:

return nil, mcp.NewToolError(-32001, "Rate limit exceeded", map[string]any{
    "retry_after": 60,
    "limit": 100,
})

func NewToolErrorInternal

func NewToolErrorInternal(message string) error

NewToolErrorInternal creates an error for internal server errors. Use this for unexpected failures like database errors, network issues, etc. This returns ErrorCodeInternalError (-32603).

func NewToolErrorInvalidParams

func NewToolErrorInvalidParams(message string) error

NewToolErrorInvalidParams creates an error for invalid or missing parameters. Use this when a required parameter is missing, has the wrong type, or fails validation. This returns ErrorCodeInvalidParams (-32602).

func RegisterOAuthClient added in v0.13.0

func RegisterOAuthClient(ctx context.Context, registrationEndpoint, clientName, redirectURI string) (string, error)

RegisterOAuthClient performs RFC 7591 dynamic client registration. Returns the issued client_id.

func WithShowAllFromRequest added in v0.10.0

func WithShowAllFromRequest(ctx context.Context, r *http.Request, providers ...ToolProvider) context.Context

WithShowAllFromRequest returns a context with show-all mode set based on the HTTP request. This is a convenience function that combines GetShowAllFromRequest and WithShowAllTools. Also attaches any provided tool providers.

func WithShowAllTools added in v0.10.0

func WithShowAllTools(ctx context.Context) context.Context

WithShowAllTools returns a context that shows all tools in tools/list, regardless of their Visibility setting. This is useful for MCP server chaining where the consuming server needs to see all available tools. Can be enabled via X-MCP-Show-All header or ?show_all=true query param.

func WithToolProviders added in v0.9.0

func WithToolProviders(ctx context.Context, providers ...ToolProvider) context.Context

WithToolProviders returns a context with the given tool providers attached. Multiple providers can be attached and all will be queried for tools. Tools from providers are filtered by their Visibility field:

  • ToolVisibilityNative: appears in tools/list
  • ToolVisibilityDiscoverable: only searchable via tool_search

Use WithShowAllTools to make all tools appear in tools/list regardless of visibility.

A per-request memo is also installed so providers can cache expensive, request-scoped work (such as resolving a user's remote servers) across the multiple times the server queries providers while handling one request.

Types

type Args added in v0.15.0

type Args map[string]any

Args is a map of tool arguments. It can be used directly as a map[string]any or built fluently via the Arg method.

// Direct map
client.CallTool(ctx, "tool", map[string]any{"city": "London"})

// Fluent builder
client.CallTool(ctx, "tool", mcp.Args{}.Arg("city", "London").Arg("units", "metric"))

func (Args) Arg added in v0.15.0

func (a Args) Arg(key string, value any) Args

Arg adds a key/value pair and returns the Args for chaining.

type AuthProvider

type AuthProvider interface {
	GetAuthHeader() (string, error)
	Refresh() error
}

AuthProvider is the interface for MCP client authentication.

type AuthResolver added in v0.19.0

type AuthResolver func(ctx context.Context) (AuthProvider, error)

AuthResolver lazily resolves the auth provider for a remote server for the current request. It is only called when the provider actually needs to talk to the server (listing or calling a tool), so per-user token lookups are not performed for servers that are never touched.

type BearerTokenAuth

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

BearerTokenAuth implements simple static bearer token authentication.

func NewBearerTokenAuth

func NewBearerTokenAuth(token string) *BearerTokenAuth

func (*BearerTokenAuth) GetAuthHeader

func (b *BearerTokenAuth) GetAuthHeader() (string, error)

func (*BearerTokenAuth) Refresh

func (b *BearerTokenAuth) Refresh() error

type Client

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

Client represents an MCP client for connecting to remote servers

func NewClient

func NewClient(baseURL string, auth AuthProvider, namespace string) *Client

NewClient creates a new MCP client using the shared HTTP pool. The namespace will be added to all tool names (e.g., namespace "scriptling" makes tool "search" available as "scriptling.search"). Use an empty namespace for no namespacing.

The namespace should be a simple identifier (letters, numbers, hyphens, underscores). Whitespace is trimmed automatically.

func NewClientWithPool added in v0.9.5

func NewClientWithPool(baseURL string, auth AuthProvider, namespace string, httpPool pool.HTTPPool) *Client

NewClientWithPool creates a new MCP client with a custom HTTP pool. If httpPool is nil, the default secure pool is used. This is useful when you need to use a pool with custom settings (e.g., InsecureSkipVerify for internal services).

Example:

// Create an insecure pool for internal services with self-signed certs
insecurePool := pool.NewPool(&pool.PoolConfig{InsecureSkipVerify: true})
client := mcp.NewClientWithPool("https://internal.service", auth, "ns", insecurePool)

func NewStdioClient added in v0.20.0

func NewStdioClient(command string, args []string, namespace string, opts ...StdioClientOption) (*Client, error)

NewStdioClient launches command (with args) as an MCP server speaking newline-delimited JSON-RPC over its stdin/stdout, and returns a client connected to it. Call Close to shut the child process down.

The namespace behaves as for NewClient: when non-empty it is prefixed to tool names (e.g. namespace "fs" exposes tool "read" as "fs__read").

func NewStreamClient added in v0.20.0

func NewStreamClient(in io.Reader, out io.Writer, namespace string) *Client

NewStreamClient returns an MCP client that speaks newline-delimited JSON-RPC over the given streams: it writes requests to out and reads responses from in. Use it to connect to a server exposed via Server.ServeStream (for example over an in-process pipe), or any transport you manage yourself. Close stops the client's reader.

func (*Client) CallTool

func (c *Client) CallTool(ctx context.Context, name string, args map[string]any) (*ToolResponse, error)

CallTool executes a tool on the remote server. If the client has a namespace, the tool name should include it (e.g., "scriptling.search"). The namespace will be stripped before calling the underlying tool. If a tool filter is set and the tool is filtered out, returns ErrToolFiltered.

func (*Client) CallToolsParallel added in v0.15.0

func (c *Client) CallToolsParallel(ctx context.Context, calls []ToolCall) []ParallelToolResult

CallToolsParallel executes multiple tools concurrently and returns results in the same order as the input. Over a transport with native batch support (currently the stdio transport, backed by jsonrpc.Client.CallBatch), all calls are sent as a single wire-level batch instead of one round-trip each; otherwise they run as concurrent individual calls.

func (*Client) Close added in v0.20.0

func (c *Client) Close() error

Close releases resources held by the client's transport. For the default HTTP transport it is a no-op; for a stdio subprocess transport it shuts the child process down.

func (*Client) ExecuteDiscoveredTool added in v0.8.0

func (c *Client) ExecuteDiscoveredTool(ctx context.Context, name string, arguments map[string]any) (*ToolResponse, error)

ExecuteDiscoveredTool executes a tool by name using the execute_tool MCP tool. This is the always-safe way to call tools returned by ToolSearch. Tools may also be callable directly via CallTool when they were exposed in tools/list.

func (*Client) ExecuteDiscoveredToolsParallel added in v0.15.0

func (c *Client) ExecuteDiscoveredToolsParallel(ctx context.Context, calls []ToolCall) []ParallelToolResult

ExecuteDiscoveredToolsParallel executes multiple discovered tools concurrently and returns results in the same order as the input. It has the same batch-transport behaviour as CallToolsParallel.

func (*Client) GetToolFilter added in v0.9.9

func (c *Client) GetToolFilter() ToolFilterFunc

GetToolFilter returns the current tool filter, or nil if none is set.

func (*Client) Initialize

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

Initialize performs the MCP handshake with the remote server

func (*Client) ListTools

func (c *Client) ListTools(ctx context.Context) ([]MCPTool, error)

ListTools retrieves tools from the remote server

func (*Client) Namespace added in v0.8.0

func (c *Client) Namespace() string

Namespace returns the namespace for this client's tools.

func (*Client) RefreshToolCache

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

RefreshToolCache explicitly refreshes the tool cache

func (*Client) ToolSearch added in v0.8.0

func (c *Client) ToolSearch(ctx context.Context, query string, maxResults int) ([]map[string]any, error)

ToolSearch performs a tool search using the tool_search MCP tool. This is useful when the server has many tools registered via a discovery registry. The query searches tool names, descriptions, and keywords.

func (*Client) WithToolFilter added in v0.9.9

func (c *Client) WithToolFilter(filter ToolFilterFunc) *Client

WithToolFilter sets a filter function for this client. The filter receives the original tool name (without namespace prefix). When set, ListTools will only return tools where filter returns true, and CallTool will reject calls to filtered-out tools. Pass nil to clear the filter. Returns the client for chaining. Note: Setting a filter clears the tool cache to ensure consistency.

type JWTSessionManager added in v0.6.6

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

JWTSessionManager provides stateless session management using JWT tokens This is the RECOMMENDED approach for production clusters as it: - Requires no external storage (Redis, Database) - Scales horizontally without coordination - Works across all server instances - Has zero infrastructure dependencies

Trade-off: Sessions cannot be revoked before expiry (acceptable for most use cases)

func NewJWTSessionManager added in v0.6.6

func NewJWTSessionManager(signingKey []byte, ttl time.Duration) *JWTSessionManager

NewJWTSessionManager creates a new JWT-based session manager signingKey should be a cryptographically secure random key (at least 32 bytes recommended) ttl is the session lifetime (e.g., 30 * time.Minute)

func NewJWTSessionManagerWithAutoKey added in v0.9.1

func NewJWTSessionManagerWithAutoKey(ttl time.Duration) (*JWTSessionManager, error)

NewJWTSessionManagerWithAutoKey creates a JWT session manager with an auto-generated signing key. This is convenient for development or single-instance deployments.

For production clusters with multiple instances, use NewJWTSessionManager with a persisted key to ensure all instances can validate each other's sessions.

func (*JWTSessionManager) CleanupExpiredSessions added in v0.6.6

func (m *JWTSessionManager) CleanupExpiredSessions(ctx context.Context, maxIdleTime time.Duration) error

CleanupExpiredSessions is a no-op for JWT sessions (tokens expire automatically)

func (*JWTSessionManager) CreateSession added in v0.6.6

func (m *JWTSessionManager) CreateSession(ctx context.Context, protocolVersion string, showAll bool) (string, error)

CreateSession generates a new JWT session token

func (*JWTSessionManager) DeleteSession added in v0.6.6

func (m *JWTSessionManager) DeleteSession(ctx context.Context, sessionID string) error

DeleteSession is a no-op for JWT sessions (cannot revoke before expiry)

func (*JWTSessionManager) GetProtocolVersion added in v0.6.6

func (m *JWTSessionManager) GetProtocolVersion(ctx context.Context, sessionID string) (string, error)

GetProtocolVersion extracts the protocol version from a JWT session token

func (*JWTSessionManager) GetShowAll added in v0.10.0

func (m *JWTSessionManager) GetShowAll(ctx context.Context, sessionID string) (bool, error)

GetShowAll extracts the show-all flag from a JWT session token

func (*JWTSessionManager) ValidateSession added in v0.6.6

func (m *JWTSessionManager) ValidateSession(ctx context.Context, sessionID string) (bool, error)

ValidateSession validates a JWT session token

type MCPError

type MCPError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
}

type MCPRequest

type MCPRequest struct {
	JSONRPC string `json:"jsonrpc"`
	ID      any    `json:"id"`
	Method  string `json:"method"`
	Params  any    `json:"params,omitempty"`
}

MCP Protocol types

type MCPResponse

type MCPResponse struct {
	JSONRPC string    `json:"jsonrpc"`
	ID      any       `json:"id,omitempty"`
	Result  any       `json:"result,omitempty"`
	Error   *MCPError `json:"error,omitempty"`
}

type MCPTool

type MCPTool struct {
	Name         string         `json:"name"`
	Description  string         `json:"description"`
	InputSchema  any            `json:"inputSchema"`
	OutputSchema any            `json:"outputSchema,omitempty"`
	Keywords     []string       `json:"-"` // For discovery search, not serialized to clients
	Visibility   ToolVisibility `json:"-"` // Native or Discoverable
}

type MultiProvider added in v0.19.0

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

MultiProvider combines multiple ToolProviders into a single ToolProvider.

Composition semantics:

  • GetTools aggregates the tools from every provider in order. To stay transparent with the server's own list path (listToolsFromProviders), a provider whose GetTools returns an error is skipped rather than failing the whole set, so one broken provider never hides the others' tools. GetTools therefore does not surface provider errors. Duplicate tool names are NOT de-duplicated here; the server's list/search logic already de-duplicates by name.

  • ExecuteTool dispatches to each provider in order using the "skip on miss, abort on real error, first success wins" contract: 1. A provider that does not handle the tool signals a miss by returning (nil, nil) or (nil, ErrUnknownTool). The next provider is tried. 2. A provider that returns any other error aborts dispatch and that error is returned to the caller. 3. The first provider that returns a non-nil result wins. If no provider handles the tool, ExecuteTool returns (nil, nil), which the server treats as ErrUnknownTool.

MultiProvider is safe for concurrent use if its underlying providers are.

func NewMultiProvider added in v0.19.0

func NewMultiProvider(providers ...ToolProvider) *MultiProvider

NewMultiProvider combines the given providers into a single ToolProvider. Nil providers are skipped. If no non-nil providers are supplied, nil is returned so callers can attach the result with WithToolProviders without a guard (attaching a nil provider is a no-op-safe pattern callers should still check for).

func (*MultiProvider) ExecuteTool added in v0.19.0

func (p *MultiProvider) ExecuteTool(ctx context.Context, name string, params map[string]any) (*ToolResponse, error)

ExecuteTool dispatches the call to the first provider that handles the tool. See the MultiProvider type docs for the full skip/abort/first-success contract.

func (*MultiProvider) GetTools added in v0.19.0

func (p *MultiProvider) GetTools(ctx context.Context) ([]MCPTool, error)

GetTools returns the aggregated tools from all providers in order. A provider whose GetTools returns an error is skipped (matching the server's list path), so GetTools itself never returns an error.

type OAuth2Auth

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

OAuth2Auth implements OAuth2 authentication backed by an oauth2.TokenSource. Supports both client credentials (machine-to-machine) and refresh token (user-delegated, e.g. PKCE) flows.

func NewOAuth2Auth

func NewOAuth2Auth(clientID, clientSecret, tokenURL string, scopes []string) *OAuth2Auth

NewOAuth2Auth creates an OAuth2 provider using the client credentials flow.

func NewOAuth2RefreshTokenAuth added in v0.13.0

func NewOAuth2RefreshTokenAuth(tokenURL, clientID, accessToken, refreshToken string) *OAuth2Auth

NewOAuth2RefreshTokenAuth creates an OAuth2 provider from an existing access + refresh token pair (e.g. obtained via browser-based PKCE flow). clientID is the dynamically registered client ID. accessToken may be empty.

func (*OAuth2Auth) GetAuthHeader

func (o *OAuth2Auth) GetAuthHeader() (string, error)

func (*OAuth2Auth) Refresh

func (o *OAuth2Auth) Refresh() error

type OAuthMeta added in v0.13.0

type OAuthMeta struct {
	AuthorizationEndpoint string `json:"authorization_endpoint"`
	TokenEndpoint         string `json:"token_endpoint"`
	RegistrationEndpoint  string `json:"registration_endpoint"`
}

OAuthMeta holds the OAuth2 server metadata discovered via RFC 8414.

func DiscoverOAuthMeta added in v0.13.0

func DiscoverOAuthMeta(ctx context.Context, serverURL string) (*OAuthMeta, error)

DiscoverOAuthMeta fetches OAuth2 server metadata from the MCP server URL by probing RFC 8414 and OIDC well-known endpoints.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option interface for parameter options

func Required

func Required() Option

type ParallelToolResult added in v0.15.0

type ParallelToolResult struct {
	Name     string
	Response *ToolResponse
	Err      error
}

ParallelToolResult holds the result of a single tool call from a parallel execution.

type Parameter

type Parameter interface {
	// contains filtered or unexported methods
}

Parameter interface for all parameter types

func Boolean

func Boolean(name, description string, options ...Option) Parameter

Boolean creates a boolean parameter

func BooleanArray added in v0.9.0

func BooleanArray(name, description string, options ...Option) Parameter

BooleanArray creates a boolean array parameter

func Integer added in v0.16.0

func Integer(name, description string, options ...Option) Parameter

Integer creates an integer parameter (whole numbers only). Emitted as JSON Schema {"type": "integer"}.

func IntegerArray added in v0.16.0

func IntegerArray(name, description string, options ...Option) Parameter

IntegerArray creates an integer array parameter (whole numbers only). Emitted as JSON Schema {"type": "array", "items": {"type": "integer"}}.

func Number

func Number(name, description string, options ...Option) Parameter

Number creates a number parameter (integer or float). Emitted as JSON Schema {"type": "number"}.

func NumberArray

func NumberArray(name, description string, options ...Option) Parameter

NumberArray creates a number array parameter (integers or floats). Emitted as JSON Schema {"type": "array", "items": {"type": "number"}}.

func Object

func Object(name, description string, propertiesAndOptions ...any) Parameter

Object creates an object parameter with properties

func ObjectArray

func ObjectArray(name, description string, propertiesAndOptions ...any) Parameter

ObjectArray creates an array of objects parameter

func Output

func Output(parameters ...Parameter) Parameter

func String

func String(name, description string, options ...Option) Parameter

String creates a string parameter

func StringArray

func StringArray(name, description string, options ...Option) Parameter

StringArray creates a string array parameter

type ProviderFuncs added in v0.19.0

type ProviderFuncs struct {
	GetToolsFunc    func(ctx context.Context) ([]MCPTool, error)
	ExecuteToolFunc func(ctx context.Context, name string, params map[string]any) (*ToolResponse, error)
}

ProviderFuncs adapts plain functions to the ToolProvider interface, so a provider can be defined inline without a dedicated type.

p := &mcp.ProviderFuncs{
    GetToolsFunc: func(ctx context.Context) ([]mcp.MCPTool, error) { ... },
    ExecuteToolFunc: func(ctx context.Context, name string, params map[string]any) (*mcp.ToolResponse, error) { ... },
}

A nil GetToolsFunc yields no tools; a nil ExecuteToolFunc reports the tool as not handled (returns nil, ErrUnknownTool).

func (*ProviderFuncs) ExecuteTool added in v0.19.0

func (p *ProviderFuncs) ExecuteTool(ctx context.Context, name string, params map[string]any) (*ToolResponse, error)

ExecuteTool calls ExecuteToolFunc, or reports the tool as not handled if it is unset.

func (*ProviderFuncs) GetTools added in v0.19.0

func (p *ProviderFuncs) GetTools(ctx context.Context) ([]MCPTool, error)

GetTools calls GetToolsFunc, or returns nil if it is unset.

type RemoteProvider added in v0.19.0

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

RemoteProvider is a request-scoped ToolProvider that exposes tools from one or more remote MCP servers. It is intended to be created once and reused for the lifetime of the process: it resolves the per-request server set from the context, so a single instance safely serves many users without leaking tools between them. Reusing one instance also lets its tool-list cache persist across requests.

provider := mcp.NewRemoteProvider(func(ctx context.Context) ([]mcp.RemoteProviderConfig, error) {
    user := userFromContext(ctx)
    return loadServersForUser(user), nil
})
// per request:
ctx := mcp.WithToolProviders(r.Context(), provider)
server.HandleRequest(w, r.WithContext(ctx))

func NewRemoteProvider added in v0.19.0

func NewRemoteProvider(resolve RemoteProviderResolver, opts ...RemoteProviderOption) *RemoteProvider

NewRemoteProvider creates a remote tool provider driven by the given resolver. Create it once and reuse it across requests.

func (*RemoteProvider) ExecuteTool added in v0.19.0

func (p *RemoteProvider) ExecuteTool(ctx context.Context, name string, params map[string]any) (*ToolResponse, error)

ExecuteTool dispatches a namespaced tool call to the owning remote server. Returns ErrUnknownTool when the tool is not a namespaced tool belonging to one of this request's servers, so other providers can handle it.

func (*RemoteProvider) GetTools added in v0.19.0

func (p *RemoteProvider) GetTools(ctx context.Context) ([]MCPTool, error)

GetTools returns the tools for all of the current request's remote servers, applying each server's visibility, keywords and tool filter. Servers that fail to respond are skipped so one bad remote does not break the whole list.

func (*RemoteProvider) InvalidateAllCache added in v0.19.0

func (p *RemoteProvider) InvalidateAllCache()

InvalidateAllCache clears every cached remote tool list.

func (*RemoteProvider) InvalidateCache added in v0.19.0

func (p *RemoteProvider) InvalidateCache(cacheKey string)

InvalidateCache removes the cached tool list for a single server. The key must match the server's CacheKey (or, when CacheKey is unset, Name + "\x00" + URL). Call this when a server's configuration or tool set changes.

type RemoteProviderConfig added in v0.19.0

type RemoteProviderConfig struct {
	// Name is the namespace applied to the server's tool names (e.g. a Name of
	// "github" exposes the remote tool "list_repos" as "github__list_repos").
	// It must be unique within a single resolver result.
	Name string

	// URL is the remote MCP server endpoint.
	URL string

	// Auth is a static auth provider for the server. Ignored when AuthFunc is set.
	// May be nil for unauthenticated servers.
	Auth AuthProvider

	// AuthFunc lazily resolves auth for the current request. Takes precedence
	// over Auth. Use this for per-user credentials (e.g. OAuth tokens looked up
	// from a store) so the lookup only happens when the server is used.
	AuthFunc AuthResolver

	// Visibility controls whether the server's tools appear in tools/list
	// (ToolVisibilityNative) or are only reachable via tool_search
	// (ToolVisibilityDiscoverable).
	Visibility ToolVisibility

	// ToolFilter optionally restricts which tools are exposed. It receives the
	// original (un-namespaced) tool name and returns true to include it. Applied
	// on both the list and call paths. Nil means expose all tools.
	ToolFilter ToolFilterFunc

	// CacheTTL is how long this server's tool list is cached. Zero uses
	// DefaultRemoteToolCacheTTL. Negative disables caching.
	CacheTTL time.Duration

	// CacheKey overrides the cache key for this server's tool list. Defaults to
	// Name + "\x00" + URL. Set this to include a user/tenant identifier when tool
	// catalogs differ per user and must not be shared.
	//
	// The cache is bounded: it holds at most a fixed number of entries (see
	// WithMaxCacheEntries / DefaultRemoteToolCacheMaxEntries) and evicts the
	// least-recently-used entry when full, so a per-user CacheKey cannot grow
	// memory without limit. For very large user populations you may still want a
	// shorter CacheTTL or a larger max so active users are not evicted too soon.
	CacheKey string

	// HTTPPool optionally provides a custom HTTP pool (e.g. for self-signed
	// internal services). Nil uses the default secure pool.
	HTTPPool pool.HTTPPool

	// Keywords are extra search keywords attached to this server's tools. The
	// server namespace and "remote" are always included.
	Keywords []string
}

RemoteProviderConfig describes a single remote MCP server that a RemoteProvider should expose for the current request. The consumer owns "which servers does this user have and how do they authenticate"; the library owns fetching, caching, namespacing, visibility, filtering and dispatch.

type RemoteProviderOption added in v0.19.0

type RemoteProviderOption func(*remoteProviderOptions)

RemoteProviderOption configures a RemoteProvider.

func WithMaxCacheEntries added in v0.19.0

func WithMaxCacheEntries(n int) RemoteProviderOption

WithMaxCacheEntries bounds how many distinct cache keys the provider keeps tool lists for. Once exceeded, the least-recently-used entry is evicted. This keeps memory bounded even when CacheKey embeds a per-user/per-tenant id. A value <= 0 uses DefaultRemoteToolCacheMaxEntries.

type RemoteProviderResolver added in v0.19.0

type RemoteProviderResolver func(ctx context.Context) ([]RemoteProviderConfig, error)

RemoteProviderResolver returns the set of remote servers available for the current request. It is called on every list/search/execute that reaches the provider, so it should read request-scoped information (user, tenant) from the context. Returning an error fails the operation; returning an empty slice simply exposes no remote tools.

type RemoteServerEntry added in v0.12.11

type RemoteServerEntry struct {
	Client       *Client
	Visibility   ToolVisibility
	RemoteSearch bool // Delegate tool_search to this remote server
}

RemoteServerEntry pairs a client with the visibility to use when registering.

type RemoteServerOption added in v0.17.0

type RemoteServerOption func(*remoteServerOptions)

RemoteServerOption configures options when registering a remote server.

func WithRemoteSearch added in v0.17.0

func WithRemoteSearch() RemoteServerOption

WithRemoteSearch enables delegating tool_search to this remote server. Results from the remote are prefixed with the server's namespace.

type ResourceContent

type ResourceContent struct {
	URI      string `json:"uri"`
	MimeType string `json:"mimeType,omitempty"`
	Text     string `json:"text,omitempty"`
	Blob     string `json:"blob,omitempty"` // base64 encoded
}

type ResourceResponse

type ResourceResponse struct {
	Contents []ResourceContent `json:"contents"`
}

func NewResourceResponseBlob

func NewResourceResponseBlob(uri string, data []byte, mimeType string) *ResourceResponse

func NewResourceResponseText

func NewResourceResponseText(uri, text, mimeType string) *ResourceResponse

type SearchResult added in v0.9.0

type SearchResult struct {
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Score       float64  `json:"score"`
	InputSchema any      `json:"inputSchema,omitempty"`
	Keywords    []string `json:"keywords,omitempty"`
}

SearchResult represents a tool found via search

type Server

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

Server represents an MCP server instance.

Design Philosophy

The Server struct is the central hub for MCP protocol handling. It intentionally combines several related concerns to provide a cohesive API:

  • Core Identity: name, version, and instructions for protocol negotiation
  • Tool Management: local tools with thread-safe registration and caching
  • Federation: remote MCP server integration with namespacing
  • Sessions: pluggable session management for stateful deployments
  • Discovery: optional tool registry for large tool sets

This design prioritizes ease of use over strict separation of concerns. A typical server setup requires only a few lines:

server := mcp.NewServer("myapp", "1.0.0")
server.RegisterTool(myTool, myHandler)
http.HandleFunc("/mcp", server.HandleRequest)

For advanced use cases, the server delegates to specialized components:

  • SessionManager interface for custom session storage
  • Client for remote server federation

Thread Safety: All methods are safe for concurrent use. The server uses RWMutex for read-heavy operations (ListTools, CallTool) with minimal lock contention.

Lifecycle: configure the server (SetInstructions, SetSessionManager, RegisterTool/RegisterTools, RegisterRemoteServer/ReplaceRemoteServers) before you start serving with HandleRequest. Each individual method is safe to call concurrently, but mutating registration while requests are in flight is discouraged: a tools/list or tools/call running concurrently with a RegisterTool may observe the tool set either before or after the change. For per-request or per-user tools, prefer ToolProvider with WithToolProviders rather than mutating the shared server.

func NewServer

func NewServer(name, version string) *Server

NewServer creates a new MCP server instance.

func (*Server) CallTool

func (s *Server) CallTool(ctx context.Context, name string, args map[string]any) (*ToolResponse, error)

CallTool executes a tool directly with namespace support (direct API) It checks discovery tools first, then local tools, then remote tools, then providers from context.

func (*Server) CleanupExpiredSessions added in v0.6.6

func (s *Server) CleanupExpiredSessions(maxIdleTime time.Duration) error

CleanupExpiredSessions removes sessions that haven't been used in the specified duration Only works if a session manager is configured

func (*Server) HandleRequest

func (s *Server) HandleRequest(w http.ResponseWriter, r *http.Request)

HandleRequest handles MCP protocol requests

func (*Server) ListTools deprecated

func (s *Server) ListTools() []MCPTool

ListTools returns the server's native tools plus discovery tools when discoverable tools are registered.

Deprecated: Use ListToolsWithContext instead. ListTools cannot see request-scoped ToolProviders, so it omits any per-user or per-request tools attached via WithToolProviders. It is retained as a thin wrapper for backwards compatibility and may be removed in a future version.

func (*Server) ListToolsWithContext added in v0.9.0

func (s *Server) ListToolsWithContext(ctx context.Context) []MCPTool

ListToolsWithContext returns tools based on the context mode. Normal mode: returns native tools + native provider tools (+ discovery tools if any discoverable tools exist) Show-all mode: returns ALL tools regardless of visibility The context is used to retrieve request-scoped tool providers.

func (*Server) RefreshTools

func (s *Server) RefreshTools(ctx context.Context) error

RefreshTools manually refreshes the tool cache and lookup from all remote servers. This method is safe for concurrent use - it releases the lock during network calls to avoid blocking other operations, then atomically swaps in the new data. The context can be used to cancel the operation if needed.

func (*Server) RegisterRemoteServer

func (s *Server) RegisterRemoteServer(client *Client, opts ...RemoteServerOption) error

RegisterRemoteServer registers a remote MCP server with native visibility. Remote server tools appear in tools/list and are directly callable.

func (*Server) RegisterRemoteServerDiscoverable added in v0.10.0

func (s *Server) RegisterRemoteServerDiscoverable(client *Client, opts ...RemoteServerOption) error

RegisterRemoteServerDiscoverable registers a remote MCP server with discoverable visibility. Remote server tools do NOT appear in tools/list but are searchable via tool_search.

func (*Server) RegisterTool

func (s *Server) RegisterTool(tool *ToolBuilder, handler ToolHandler, keywords ...string)

RegisterTool registers a tool with the server. The tool's visibility is determined by whether Discoverable() was called on the ToolBuilder:

  • Native tools (default): appear in tools/list and are directly callable
  • Discoverable tools (via .Discoverable(keywords...)): only available via tool_search and execute_tool

Optional keywords parameter is merged with keywords set via Discoverable() for search relevance. Keywords are used in show-all mode and for discoverable tool search.

func (*Server) RegisterTools added in v0.8.0

func (s *Server) RegisterTools(tools ...*ToolRegistration)

RegisterTools registers multiple tools with the server in a single batch. This is more efficient than calling RegisterTool multiple times as it only sorts the cache once at the end. Each tool's visibility is determined by whether Discoverable() was called on its ToolBuilder.

func (*Server) ReplaceRemoteServers added in v0.12.11

func (s *Server) ReplaceRemoteServers(servers []RemoteServerEntry) error

ReplaceRemoteServers atomically replaces all registered remote servers with the provided list. Each entry is a (*Client, ToolVisibility) pair. Use ToolVisibilityNative for tools that should appear in tools/list, or ToolVisibilityDiscoverable for tools only findable via tool_search. All previously registered remote servers and their cached tools are removed first.

func (*Server) ServeStdio added in v0.20.0

func (s *Server) ServeStdio(ctx context.Context, opts ...StdioOption) error

ServeStdio serves the MCP protocol over newline-delimited JSON-RPC 2.0 on os.Stdin/os.Stdout. It is the entry point for an MCP stdio server (the transport a host launches as a subprocess). It blocks until stdin reaches EOF.

Anything written to stdout must be protocol frames only, so send logs to stderr.

func (*Server) ServeStream added in v0.20.0

func (s *Server) ServeStream(ctx context.Context, in io.Reader, out io.Writer, opts ...StdioOption) error

ServeStream serves the MCP protocol over an arbitrary pair of newline-delimited JSON-RPC 2.0 streams. Use it for in-process pipes or any transport that is not the process's own stdio; ServeStdio wraps it for the common case.

func (*Server) SetInstructions

func (s *Server) SetInstructions(instructions string)

SetInstructions sets the server instructions that are returned during protocol initialization. Instructions provide guidance to the LLM about how to use the server's capabilities.

func (*Server) SetSessionManager added in v0.6.6

func (s *Server) SetSessionManager(manager SessionManager)

SetSessionManager sets a custom session manager for the server. For JWT-based sessions, use NewJWTSessionManager or NewJWTSessionManagerWithAutoKey.

Example:

sm, _ := mcp.NewJWTSessionManagerWithAutoKey(30 * time.Minute)
server.SetSessionManager(sm)

Use a custom SessionManager when you need:

  • Session revocation (logout functionality, security incidents)
  • Session listing (admin dashboards, audit trails)
  • Custom session metadata

func (*Server) UnregisterRemoteServer added in v0.12.11

func (s *Server) UnregisterRemoteServer(client *Client)

UnregisterRemoteServer removes a previously registered remote server and all its cached tools.

func (*Server) UnregisterTool added in v0.17.1

func (s *Server) UnregisterTool(name string) bool

UnregisterTool removes a tool by name from the server. Returns true if the tool was found and removed, false otherwise. This is safe to call concurrently.

type SessionManager added in v0.6.6

type SessionManager interface {
	// CreateSession creates a new session and returns its ID
	// showAll specifies whether this session shows all tools regardless of visibility
	CreateSession(ctx context.Context, protocolVersion string, showAll bool) (sessionID string, err error)

	// ValidateSession checks if a session exists and is valid
	// Returns true if valid, updates lastUsed timestamp if applicable
	ValidateSession(ctx context.Context, sessionID string) (valid bool, err error)

	// GetProtocolVersion returns the negotiated protocol version for a session
	GetProtocolVersion(ctx context.Context, sessionID string) (version string, err error)

	// GetShowAll returns whether show-all mode is enabled for a session
	// Returns false if not set or session is invalid
	GetShowAll(ctx context.Context, sessionID string) (bool, error)

	// DeleteSession removes a session
	DeleteSession(ctx context.Context, sessionID string) error

	// CleanupExpiredSessions removes sessions older than maxIdleTime
	CleanupExpiredSessions(ctx context.Context, maxIdleTime time.Duration) error
}

SessionManager defines the interface for session storage and validation Implement this interface to create custom session stores (Redis, Database, etc.)

type StdioClientOption added in v0.20.0

type StdioClientOption func(*stdioClientConfig)

StdioClientOption configures a subprocess-backed stdio client.

func WithClientDir added in v0.20.0

func WithClientDir(dir string) StdioClientOption

WithClientDir sets the working directory for the child server process.

func WithClientEnv added in v0.20.0

func WithClientEnv(env []string) StdioClientOption

WithClientEnv sets the environment for the child server process.

func WithClientOnExit added in v0.20.0

func WithClientOnExit(fn func(error)) StdioClientOption

WithClientOnExit registers a callback invoked exactly once when the spawned server process exits — whether it crashes mid-session or is shut down by Client.Close. It is invoked asynchronously from a reaper goroutine, so it fires even if Close is never called; it must not block.

Without this, a caller has no way to learn that its child server has died other than subsequent calls failing. This is passed through to jsonrpc.WithOnExit.

func WithClientStderr added in v0.20.0

func WithClientStderr(w io.Writer) StdioClientOption

WithClientStderr routes the child server's standard error to w (default: inherited from the parent). Pass io.Discard to silence it.

type StdioOption added in v0.20.0

type StdioOption func(*stdioConfig)

StdioOption configures a stdio MCP server run.

func WithStdioShowAllTools added in v0.20.0

func WithStdioShowAllTools() StdioOption

WithStdioShowAllTools makes the stdio server expose every tool (including discoverable ones) on tools/list, bypassing the discovery meta-tools. It is the stdio equivalent of the HTTP show-all header/query flag.

type ToolBuilder

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

ToolBuilder provides fluent API for building tools

func NewTool

func NewTool(name, description string, parameters ...Parameter) *ToolBuilder

NewTool creates a new tool with the declarative API

func (*ToolBuilder) BuildOutputSchema

func (t *ToolBuilder) BuildOutputSchema() map[string]any

BuildOutputSchema returns the JSON Schema for the tool's structured output. Returns nil if no output schema was defined with Output(). This is used internally and for tools that return structured content.

func (*ToolBuilder) BuildSchema

func (t *ToolBuilder) BuildSchema() map[string]any

BuildSchema returns the JSON Schema for the tool's input parameters. This is used internally for tool registration and search functionality, but can also be used for documentation or schema validation purposes.

func (*ToolBuilder) Description added in v0.6.0

func (t *ToolBuilder) Description() string

Description returns the tool's description with newlines normalized to spaces and multiple whitespace collapsed to single spaces

func (*ToolBuilder) Discoverable added in v0.10.0

func (t *ToolBuilder) Discoverable(keywords ...string) *ToolBuilder

Discoverable marks the tool as discoverable via tool_search. Discoverable tools do NOT appear in tools/list but can be found through search. Keywords improve search relevance - include terms users might search for. When any discoverable tools exist, tool_search and execute_tool are automatically added to tools/list.

func (*ToolBuilder) IsDiscoverable added in v0.10.0

func (t *ToolBuilder) IsDiscoverable() bool

IsDiscoverable returns true if the tool is marked as discoverable.

func (*ToolBuilder) Keywords added in v0.10.0

func (t *ToolBuilder) Keywords() []string

Keywords returns the keywords set for this tool.

func (*ToolBuilder) Name added in v0.6.0

func (t *ToolBuilder) Name() string

Name returns the tool's name

func (*ToolBuilder) ToMCPTool added in v0.9.8

func (t *ToolBuilder) ToMCPTool() MCPTool

ToMCPTool converts the ToolBuilder to an MCPTool struct. This is useful for tool providers that use the fluent API to build tools but need to return MCPTool structs from their GetTools method. Use .Discoverable(keywords...) before calling this to set keywords and mark as discoverable.

type ToolCall added in v0.15.0

type ToolCall struct {
	Name      string
	Arguments map[string]any
}

ToolCall represents a single tool invocation for use with parallel calls.

type ToolCallParams

type ToolCallParams struct {
	Name      string         `json:"name"`
	Arguments map[string]any `json:"arguments,omitempty"`
}

type ToolContent

type ToolContent struct {
	Type     string           `json:"type"`
	Text     string           `json:"text,omitempty"`
	Data     string           `json:"data,omitempty"`
	MimeType string           `json:"mimeType,omitempty"`
	Resource *ResourceContent `json:"resource,omitempty"`
}

type ToolError

type ToolError struct {
	Code    int
	Message string
	Data    any
}

ToolError represents an MCP protocol error that can be returned from tool handlers. When returned from a ToolHandler, the error code and message are sent to the client in the JSON-RPC error response.

Returning one in a tool handler or provider:

func myHandler(ctx context.Context, req *mcp.ToolRequest) (*mcp.ToolResponse, error) {
    name, err := req.String("name")
    if err != nil {
        return nil, mcp.NewToolErrorInvalidParams("name parameter is required")
    }
    // ... process request
}

Detecting one as a caller (middleware, tests, custom transports) — use errors.As, which also unwraps wrapped errors, to recover the code/message/data:

resp, err := server.CallTool(ctx, name, args)
var toolErr *mcp.ToolError
if errors.As(err, &toolErr) {
    log.Printf("tool error %d: %s (data=%v)", toolErr.Code, toolErr.Message, toolErr.Data)
}

func (*ToolError) Error

func (e *ToolError) Error() string

type ToolFilterFunc added in v0.9.9

type ToolFilterFunc func(toolName string) bool

ToolFilterFunc is a function that determines if a tool should be included. It receives the original tool name (without namespace prefix). Return true to include the tool, false to exclude it.

type ToolHandler

type ToolHandler func(ctx context.Context, req *ToolRequest) (*ToolResponse, error)

ToolHandler represents a function that handles tool calls. It receives the request context and a ToolRequest with typed argument accessors.

type ToolProvider added in v0.9.0

type ToolProvider interface {
	// GetTools returns all tools available from this provider.
	// The context contains tenant/user information for filtering.
	// Each tool's Visibility field determines whether it appears in tools/list
	// or only via tool_search. Keywords should be populated for discoverable tools.
	GetTools(ctx context.Context) ([]MCPTool, error)

	// ExecuteTool executes a tool by name and returns its response.
	//
	// Miss contract: if this provider does not handle the named tool, return
	// (nil, nil). This is the canonical "not handled" signal and lets the
	// server (or a MultiProvider) try the next provider. Returning
	// (nil, ErrUnknownTool) is also accepted for the same purpose and behaves
	// identically. Any other non-nil error aborts dispatch and is returned to
	// the caller, so only use it for genuine failures, not for misses.
	//
	// Build the response with the NewToolResponse* constructors. If you have a
	// loose value (a string or any JSON-encodable type) rather than an
	// already-built response, wrap it with NewToolResponseAuto.
	ExecuteTool(ctx context.Context, name string, params map[string]any) (*ToolResponse, error)
}

ToolProvider is the interface that providers implement to expose tools. Tools returned by providers should set their Visibility field:

  • ToolVisibilityNative: Tool appears in tools/list
  • ToolVisibilityDiscoverable: Tool only available via tool_search

func GetToolProviders added in v0.9.0

func GetToolProviders(ctx context.Context) []ToolProvider

GetToolProviders returns the tool providers from the context. Returns nil if no providers are attached.

type ToolRegistration added in v0.8.0

type ToolRegistration struct {
	Tool    *ToolBuilder
	Handler ToolHandler
}

ToolRegistration pairs a tool builder with its handler for batch registration.

func NewToolRegistration added in v0.8.0

func NewToolRegistration(tool *ToolBuilder, handler ToolHandler) *ToolRegistration

NewToolRegistration creates a tool registration for use with RegisterTools.

type ToolRequest

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

ToolRequest provides typed access to tool arguments. Use the accessor methods (String, Int, Bool, etc.) to retrieve parameters with automatic type conversion and validation.

func NewToolRequest added in v0.6.0

func NewToolRequest(args map[string]any) *ToolRequest

NewToolRequest creates a new ToolRequest with the given arguments. This is typically called by the server when dispatching tool calls.

func (*ToolRequest) Args added in v0.6.3

func (r *ToolRequest) Args() map[string]any

Args returns all arguments as a map

func (*ToolRequest) Bool

func (r *ToolRequest) Bool(name string) (bool, error)

Bool returns a boolean parameter by name. Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) BoolOr

func (r *ToolRequest) BoolOr(name string, defaultValue bool) bool

BoolOr returns a boolean parameter or defaultValue if not present or invalid.

func (*ToolRequest) BoolSlice added in v0.9.0

func (r *ToolRequest) BoolSlice(name string) ([]bool, error)

BoolSlice returns a boolean array parameter by name. Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) BoolSliceOr added in v0.9.0

func (r *ToolRequest) BoolSliceOr(name string, defaultValue []bool) []bool

BoolSliceOr returns a boolean array parameter or defaultValue if not present or invalid.

func (*ToolRequest) Float

func (r *ToolRequest) Float(name string) (float64, error)

Float returns a float64 parameter by name. Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) FloatOr

func (r *ToolRequest) FloatOr(name string, defaultValue float64) float64

FloatOr returns a float64 parameter or defaultValue if not present or invalid.

func (*ToolRequest) FloatSlice

func (r *ToolRequest) FloatSlice(name string) ([]float64, error)

FloatSlice returns a float64 array parameter by name. Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) FloatSliceOr

func (r *ToolRequest) FloatSliceOr(name string, defaultValue []float64) []float64

FloatSliceOr returns a float64 array parameter or defaultValue if not present or invalid.

func (*ToolRequest) GetObjectBoolProperty deprecated

func (r *ToolRequest) GetObjectBoolProperty(objectName, propertyName string) (bool, error)

GetObjectBoolProperty extracts a bool property from an object parameter.

Deprecated: use ObjectBool (or ObjectBoolOr for a default).

func (*ToolRequest) GetObjectIntProperty deprecated

func (r *ToolRequest) GetObjectIntProperty(objectName, propertyName string) (int, error)

GetObjectIntProperty extracts an int property from an object parameter.

Deprecated: use ObjectInt (or ObjectIntOr for a default).

func (*ToolRequest) GetObjectProperty deprecated

func (r *ToolRequest) GetObjectProperty(objectName, propertyName string) (any, error)

GetObjectProperty extracts a property from an object parameter.

Deprecated: use ObjectProperty.

func (*ToolRequest) GetObjectStringProperty deprecated

func (r *ToolRequest) GetObjectStringProperty(objectName, propertyName string) (string, error)

GetObjectStringProperty extracts a string property from an object parameter.

Deprecated: use ObjectString (or ObjectStringOr for a default).

func (*ToolRequest) Int

func (r *ToolRequest) Int(name string) (int, error)

Int returns an integer parameter by name. Handles both int and float64 types (JSON numbers are parsed as float64). Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) IntOr

func (r *ToolRequest) IntOr(name string, defaultValue int) int

IntOr returns an integer parameter or defaultValue if not present or invalid.

func (*ToolRequest) IntSlice

func (r *ToolRequest) IntSlice(name string) ([]int, error)

IntSlice returns an integer array parameter by name. Handles both int and float64 array elements (JSON numbers are parsed as float64). Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) IntSliceOr

func (r *ToolRequest) IntSliceOr(name string, defaultValue []int) []int

IntSliceOr returns an integer array parameter or defaultValue if not present or invalid.

func (*ToolRequest) Object

func (r *ToolRequest) Object(name string) (map[string]any, error)

Object returns a parameter as a map[string]any (generic object). Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) ObjectBool added in v0.19.0

func (r *ToolRequest) ObjectBool(objectName, propertyName string) (bool, error)

ObjectBool extracts a bool property from an object parameter.

func (*ToolRequest) ObjectBoolOr added in v0.19.0

func (r *ToolRequest) ObjectBoolOr(objectName, propertyName string, defaultValue bool) bool

ObjectBoolOr extracts a bool property from an object parameter, returning defaultValue when the object or property is missing or not a boolean.

func (*ToolRequest) ObjectInt added in v0.19.0

func (r *ToolRequest) ObjectInt(objectName, propertyName string) (int, error)

ObjectInt extracts an int property from an object parameter.

func (*ToolRequest) ObjectIntOr added in v0.19.0

func (r *ToolRequest) ObjectIntOr(objectName, propertyName string, defaultValue int) int

ObjectIntOr extracts an int property from an object parameter, returning defaultValue when the object or property is missing or not a number.

func (*ToolRequest) ObjectOr

func (r *ToolRequest) ObjectOr(name string, defaultValue map[string]any) map[string]any

ObjectOr returns a parameter as an object or the default value

func (*ToolRequest) ObjectProperty added in v0.19.0

func (r *ToolRequest) ObjectProperty(objectName, propertyName string) (any, error)

GetObjectProperty extracts a property from an object parameter ObjectProperty extracts a property from an object parameter.

func (*ToolRequest) ObjectSlice

func (r *ToolRequest) ObjectSlice(name string) ([]map[string]any, error)

ObjectSlice returns a parameter as a slice of objects

func (*ToolRequest) ObjectSliceOr

func (r *ToolRequest) ObjectSliceOr(name string, defaultValue []map[string]any) []map[string]any

ObjectSliceOr returns a parameter as a slice of objects or the default value

func (*ToolRequest) ObjectString added in v0.19.0

func (r *ToolRequest) ObjectString(objectName, propertyName string) (string, error)

ObjectString extracts a string property from an object parameter.

func (*ToolRequest) ObjectStringOr added in v0.19.0

func (r *ToolRequest) ObjectStringOr(objectName, propertyName, defaultValue string) string

ObjectStringOr extracts a string property from an object parameter, returning defaultValue when the object or property is missing or not a string.

func (*ToolRequest) String

func (r *ToolRequest) String(name string) (string, error)

String returns a string parameter by name. Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) StringOr

func (r *ToolRequest) StringOr(name, defaultValue string) string

StringOr returns a string parameter or defaultValue if not present or invalid.

func (*ToolRequest) StringSlice

func (r *ToolRequest) StringSlice(name string) ([]string, error)

StringSlice returns a string array parameter by name. Returns ErrUnknownParameter if the parameter doesn't exist.

func (*ToolRequest) StringSliceOr

func (r *ToolRequest) StringSliceOr(name string, defaultValue []string) []string

StringSliceOr returns a string array parameter or defaultValue if not present or invalid.

type ToolResponse

type ToolResponse struct {
	Content           []ToolContent `json:"content"`
	StructuredContent any           `json:"structuredContent,omitempty"`
}

ToolResponse represents the response from a tool

func NewToolResponseAudio

func NewToolResponseAudio(data []byte, mimeType string) *ToolResponse

func NewToolResponseAuto added in v0.19.0

func NewToolResponseAuto(value any) *ToolResponse

NewToolResponseAuto builds a ToolResponse from a loose value, applying the same conversion the server uses internally:

  • a *ToolResponse is returned unchanged,
  • a string becomes a text response,
  • anything else is JSON-encoded.

Use it in ToolProvider.ExecuteTool when you have a dynamic value (e.g. the output of a script or a remote call) rather than an already-built response. Prefer the specific NewToolResponse* constructors when you know the type.

func NewToolResponseImage

func NewToolResponseImage(data []byte, mimeType string) *ToolResponse

func NewToolResponseJSON

func NewToolResponseJSON(data any) *ToolResponse

func NewToolResponseMulti

func NewToolResponseMulti(responses ...*ToolResponse) *ToolResponse

func NewToolResponseResource

func NewToolResponseResource(uri, text, mimeType string) *ToolResponse
func NewToolResponseResourceLink(uri, text string) *ToolResponse

func NewToolResponseStructured

func NewToolResponseStructured(data any) *ToolResponse

func NewToolResponseTOON added in v0.7.0

func NewToolResponseTOON(data any) *ToolResponse

func NewToolResponseText

func NewToolResponseText(text string) *ToolResponse

type ToolResult

type ToolResult struct {
	Content           []ToolContent `json:"content,omitempty"`
	StructuredContent any           `json:"structuredContent,omitempty"`
	IsError           bool          `json:"isError,omitempty"`
}

type ToolVisibility added in v0.6.12

type ToolVisibility int

ToolVisibility defines how a tool is exposed to clients. This controls whether tools appear in tools/list or only via tool_search.

const (
	// ToolVisibilityNative means the tool appears in tools/list and is directly callable.
	// This is the standard MCP behavior - tools are visible and can be called by name.
	ToolVisibilityNative ToolVisibility = iota

	// ToolVisibilityDiscoverable means the tool is only available via tool_search and execute_tool.
	// The tool does NOT appear in tools/list but can be discovered and executed through
	// the tool_search and execute_tool meta-tools. This is useful for:
	// - Large tool sets where listing all tools would overwhelm the LLM
	// - Dynamic tools that should be discovered by keyword search
	// - Tools that should only be used when specifically relevant
	ToolVisibilityDiscoverable
)

func (ToolVisibility) String added in v0.9.0

func (v ToolVisibility) String() string

String returns a human-readable name for the visibility level.

Directories

Path Synopsis
ai
examples
client command
object-example command
openai command
per-user-tools command
Package main demonstrates per-user tool access using ToolProvider.
Package main demonstrates per-user tool access using ToolProvider.
remote-server command
server command
session-server command
stdio-client command
Command stdio-client launches an MCP stdio server as a subprocess and talks to it over the child's stdin/stdout.
Command stdio-client launches an MCP stdio server as a subprocess and talks to it over the child's stdin/stdout.
stdio-server command
Command stdio-server is an MCP server that speaks the protocol over stdin/stdout (newline-delimited JSON-RPC 2.0).
Command stdio-server is an MCP server that speaks the protocol over stdin/stdout (newline-delimited JSON-RPC 2.0).
tool-discovery command
unified-server command
Package toon implements the TOON (Token-Oriented Object Notation) format.
Package toon implements the TOON (Token-Oriented Object Notation) format.

Jump to

Keyboard shortcuts

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