Documentation
¶
Overview ¶
Package mcp provides Scope helpers around the Model Context Protocol (https://modelcontextprotocol.io/).
Use the official Go SDK package (github.com/modelcontextprotocol/go-sdk/mcp) for protocol clients, servers, sessions, and transports. The Scope package keeps the small adapters needed around those SDK primitives: context metadata, reverse-capability helpers, tool.Tool wrapping, tool registration and prompt conversion.
Naming ¶
The package shares its name with the official Go SDK (github.com/modelcontextprotocol/go-sdk/mcp). Consumers will normally import it as:
import (
scopemcp "github.com/Tangerg/scope/mcp"
sdkmcp "github.com/modelcontextprotocol/go-sdk/mcp"
)
Inside this package the SDK is imported under the alias sdkmcp.
Index ¶
- Variables
- func AnnotatedReadOnlyConcurrencyPolicy(_, _ string, annotations sdkmcp.ToolAnnotations, _ toolcontract.Invocation) (key string, concurrent bool)
- func DiscoverTools(ctx context.Context, sources []ToolSource, config ToolDiscoveryConfig) ([]toolcontract.Tool, error)
- func Elicit(ctx context.Context, params sdkmcp.ElicitParams) (*sdkmcp.ElicitResult, error)
- func PromptMessagesToChat(messages []*sdkmcp.PromptMessage) ([]chat.Message, error)
- func Register(server *sdkmcp.Server, tools ...toolcontract.Tool) error
- func ReportProgress(ctx context.Context, progress float64, total *float64, message string) error
- func RequestMetaFromContext(ctx context.Context) sdkmcp.Meta
- func WithRequestMeta(ctx context.Context, meta sdkmcp.Meta) context.Context
- type PublicToolNameFunc
- type RequestMetaFunc
- type ToolCallError
- type ToolConcurrencyPolicy
- type ToolDiscoveryConfig
- type ToolSource
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrNilServer = errors.New("mcp: server must not be nil") ErrNilSession = errors.New("mcp: session must not be nil") )
var ErrNoServerSession = errors.New("mcp: no active MCP server session on context")
ErrNoServerSession reports a reverse call made outside an MCP tool invocation.
Functions ¶
func AnnotatedReadOnlyConcurrencyPolicy ¶
func AnnotatedReadOnlyConcurrencyPolicy(_, _ string, annotations sdkmcp.ToolAnnotations, _ toolcontract.Invocation) (key string, concurrent bool)
AnnotatedReadOnlyConcurrencyPolicy opts explicitly read-only MCP tools into conflict-free concurrent execution. Missing, false, or contradictory annotations remain exclusive.
This is only scheduling advice: it neither authorizes a call nor bypasses a caller's approval policy. MCP annotations are untrusted hints, so callers should use this policy only for servers whose descriptors they are willing to trust for execution ordering.
func DiscoverTools ¶
func DiscoverTools(ctx context.Context, sources []ToolSource, config ToolDiscoveryConfig) ([]toolcontract.Tool, error)
DiscoverTools reads each live session's current catalog and projects every remote descriptor into a Scope tool. It does not cache or own the sessions.
Example ¶
package main
import (
"context"
"fmt"
"github.com/Tangerg/scope/mcp"
)
func main() {
tools, err := mcp.DiscoverTools(context.Background(), nil, mcp.ToolDiscoveryConfig{})
if err != nil {
panic(err)
}
fmt.Println(len(tools))
}
Output: 0
func Elicit ¶
func Elicit(ctx context.Context, params sdkmcp.ElicitParams) (*sdkmcp.ElicitResult, error)
Elicit asks the connected client to surface a structured prompt to the end user and returns their response. Useful when a tool needs runtime clarification it could not have asked for at schema-design time (auth confirmation, ambiguous filename, ...).
Returns ErrNoServerSession when called outside an MCP dispatch. Underlying RPC errors propagate as-is.
Example — structured response:
res, err := mcp.Elicit(ctx, sdkmcp.ElicitParams{
Message: "Choose a deployment target",
RequestedSchema: map[string]any{
"type": "object",
"properties": map[string]any{
"env": map[string]any{
"type": "string",
"enum": []string{"staging", "prod"},
},
},
"required": []string{"env"},
},
})
if err != nil { return "", err }
if res.Action != "accept" { return "user canceled", nil }
env, _ := res.Content["env"].(string)
func PromptMessagesToChat ¶
func PromptMessagesToChat(messages []*sdkmcp.PromptMessage) ([]chat.Message, error)
PromptMessagesToChat converts MCP prompt messages into Core chat messages. Text, image, audio, resource-link, and embedded-resource content retain their semantic shape; malformed or unsupported content returns an error instead of disappearing from the prompt.
func Register ¶
func Register(server *sdkmcp.Server, tools ...toolcontract.Tool) error
Register installs every [tool.Tool] in tools onto server using the low-level [(*sdkmcp.Server).AddTool] API.
Registration is all-or-nothing: definitions are snapshotted, duplicate names within the batch are rejected, and every tool is built before any is added. A bad entry mid-list therefore never leaves the server half-registered, and handlers use the same identity the server advertised even when a Tool implementation is mutable.
The generic sdkmcp.AddTool[In, Out] form is deliberately avoided: tools already supply a hand-authored JSON schema, and the generic API would otherwise reflect over a Go In type and overwrite it.
func ReportProgress ¶
ReportProgress sends a progress notification back to the client. progress should increase monotonically; total is optional and may be left nil when the work size is unknown. message is a free-form human-readable status string.
The originating client must have included a progressToken in its tools/call request — otherwise this helper returns nil without sending a notification (the spec mandates that servers only emit progress when explicitly opted in). Errors propagate from the underlying *sdkmcp.ServerSession.NotifyProgress.
Example:
func (t *longTool) Call(ctx context.Context, invocation tool.Invocation) (chat.ToolOutput, error) {
for i := range 100 {
// ... work ...
_ = mcp.ReportProgress(ctx, float64(i+1), new(100.0),
fmt.Sprintf("processed %d/100", i+1))
}
return "done", nil
}
func RequestMetaFromContext ¶
RequestMetaFromContext returns a shallow copy of metadata stored by WithRequestMeta, or nil. Its signature matches RequestMetaFunc:
config := mcp.ToolDiscoveryConfig{RequestMeta: mcp.RequestMetaFromContext}
Types ¶
type PublicToolNameFunc ¶
PublicToolNameFunc maps a remote tool identity to the name a model sees. Remote servers choose names independently, so two sources can collide or emit characters providers reject; projecting the name here keeps that negotiation out of the tool contract and lets a host resolve collisions its own way.
type RequestMetaFunc ¶
RequestMetaFunc resolves per-call MCP metadata from the context rather than from a fixed value, so a caller can forward request-scoped identity such as a trace or tenant without rebuilding the tool for every call.
type ToolCallError ¶
type ToolCallError struct {
// RemoteName is the original MCP tool name as the server advertised
// it (not the prefixed name reported into the registry).
RemoteName string
// Message is the human-readable failure text reported by the tool,
// or a fallback when the tool returned IsError=true with no text.
Message string
}
ToolCallError is returned by tools produced by DiscoverTools when a remote MCP tool reports IsError=true. Use errors.AsType to distinguish a tool-side failure from transport, protocol, or argument-decoding errors:
out, err := tool.Call(ctx, args)
if tcErr, ok := errors.AsType[*mcp.ToolCallError](err); ok {
// remote tool itself failed; surface tcErr.Message
} else if err != nil {
// transport / argument failure; surface the infrastructure error
}
func (*ToolCallError) Error ¶
func (t *ToolCallError) Error() string
type ToolConcurrencyPolicy ¶
type ToolConcurrencyPolicy func( sourceName, remoteName string, annotations sdkmcp.ToolAnnotations, invocation toolcontract.Invocation, ) (key string, concurrent bool)
ToolConcurrencyPolicy decides whether one remote tool call may overlap other calls from the same model response. A false result keeps the call exclusive; a true result with an empty key declares no known conflict, while equal non-empty keys serialize.
The callback receives the source and remote tool names, an isolated copy of the remote annotations, and a schema-validated invocation. It must be deterministic, side-effect-free, and safe for concurrent use because a durable resume may plan queued calls again and callers may inspect the capability from multiple goroutines.
type ToolDiscoveryConfig ¶
type ToolDiscoveryConfig struct {
// PublicName maps each remote tool identity to its public name. Nil
// uses the package default, "<sourceName>_<remoteName>" sanitized to the
// function-name charset accepted by model providers.
PublicName PublicToolNameFunc
// RequestMeta is applied to every tool produced. Nil forwards no metadata on
// tool calls.
RequestMeta RequestMetaFunc
// ConcurrencyPolicy opts remote tools into a caller-owned scheduling policy. Nil
// keeps every MCP call exclusive because protocol descriptors do not provide
// a trustworthy resource-conflict contract. Callers retain ownership of
// execution and result ordering. [AnnotatedReadOnlyConcurrencyPolicy] is the
// conservative ready-made policy for trusted descriptors that declare
// readOnlyHint=true.
ConcurrencyPolicy ToolConcurrencyPolicy
}
ToolDiscoveryConfig controls the boundary projection performed by DiscoverTools.
type ToolSource ¶
type ToolSource struct {
// Name identifies the upstream server in tool prefixes and error
// messages. Empty is allowed but discouraged when more than one
// source is in play.
Name string
// Session is a live, initialized client session. The wrapper does not own
// the session; callers are responsible for closing it.
Session *sdkmcp.ClientSession
}
ToolSource binds an initialized MCP client session to a logical name used to deconflict tools across multiple servers.