mcp

package module
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

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

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrNilServer = errors.New("mcp: server must not be nil")

	ErrNilSession = errors.New("mcp: session must not be nil")
)
View Source
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

func ReportProgress(ctx context.Context, progress float64, total *float64, message string) error

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

func RequestMetaFromContext(ctx context.Context) sdkmcp.Meta

RequestMetaFromContext returns a shallow copy of metadata stored by WithRequestMeta, or nil. Its signature matches RequestMetaFunc:

config := mcp.ToolDiscoveryConfig{RequestMeta: mcp.RequestMetaFromContext}

func WithRequestMeta

func WithRequestMeta(ctx context.Context, meta sdkmcp.Meta) context.Context

WithRequestMeta stores a defensive snapshot because request metadata may be read after the caller reuses or mutates its original map.

Types

type PublicToolNameFunc

type PublicToolNameFunc func(sourceName, remoteName string) string

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

type RequestMetaFunc func(ctx context.Context) sdkmcp.Meta

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.

Jump to

Keyboard shortcuts

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