mcp

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: AGPL-3.0 Imports: 31 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ToolHeaderAuthorization      = "Authorization" //nolint:gosec // G101: HTTP header name, not a credential.
	ToolHeaderBotID              = "X-Memoh-Bot-Id"
	ToolHeaderChatID             = "X-Memoh-Chat-Id"
	ToolHeaderRuntimeID          = "X-Memoh-Runtime-Id"
	ToolHeaderRuntimeToken       = "X-Memoh-Runtime-Token" //nolint:gosec // G101: HTTP header name, not a credential.
	ToolHeaderSessionID          = "X-Memoh-Session-Id"
	ToolHeaderRunID              = "X-Memoh-Run-Id"
	ToolHeaderSessionType        = "X-Memoh-Session-Type"
	ToolHeaderRouteID            = "X-Memoh-Route-Id"
	ToolHeaderChannelIdentityID  = "X-Memoh-Channel-Identity-Id"
	ToolHeaderSessionToken       = "X-Memoh-Session-Token" //nolint:gosec // G101: HTTP header name, not a credential.
	ToolHeaderCurrentPlatform    = "X-Memoh-Current-Platform"
	ToolHeaderReplyTarget        = "X-Memoh-Reply-Target"
	ToolHeaderConversationType   = "X-Memoh-Conversation-Type"
	ToolHeaderIsSubagent         = "X-Memoh-Is-Subagent"
	ToolHeaderSupportsImageInput = "X-Memoh-Supports-Image-Input"
	ToolHeaderSupportsFileInput  = "X-Memoh-Supports-File-Input"
)

Variables

View Source
var (
	// ErrNameRequired reports a connection request without a name.
	ErrNameRequired = errors.New("name is required")
	// ErrNameTaken reports that the bot already has a connection with the name.
	ErrNameTaken = errors.New("mcp connection name is already taken")
	// ErrEndpointInvalid reports a connection that gives neither a command nor
	// a URL, or both.
	ErrEndpointInvalid = errors.New("mcp endpoint is invalid")
	// ErrOAuthNotDiscovered reports that OAuth discovery has not been saved for
	// the connection, or saved without an authorization endpoint.
	ErrOAuthNotDiscovered = errors.New("oauth not discovered for this connection")
	// ErrClientIDRequired reports that no client_id is known and the
	// authorization server cannot register one.
	ErrClientIDRequired = errors.New("client_id is required")
	// ErrOAuthStateInvalid reports an authorization callback whose state is
	// unknown, expired or incomplete.
	ErrOAuthStateInvalid = errors.New("oauth state is invalid or expired")
	// ErrTokenExchange reports that the authorization server did not accept the
	// code exchange.
	ErrTokenExchange = errors.New("token exchange failed")
)
View Source
var ErrToolNotFound = errors.New("tool not found")

ErrToolNotFound indicates the provider does not own the requested tool.

Functions

func BoolArg

func BoolArg(arguments map[string]any, key string) (bool, bool, error)

func BuildToolErrorResult

func BuildToolErrorResult(message string) map[string]any

BuildToolErrorResult builds a standard MCP tool error result object.

func BuildToolMCPServer

func BuildToolMCPServer(gateway *ToolGatewayService, contexts *ToolSessionContextStore, session ToolSessionContext) *sdkmcp.Server

func BuildToolSuccessResult

func BuildToolSuccessResult(structured any) map[string]any

BuildToolSuccessResult builds a standard MCP tool success result object.

func ContentText

func ContentText(result map[string]any) string

func ConvertGatewayCallResultToSDK

func ConvertGatewayCallResultToSDK(result map[string]any, resultTypeRequired bool) (*sdkmcp.CallToolResult, error)

ConvertGatewayCallResultToSDK builds the SDK result from its wire form. The SDK sets resultType only inside its built-in tools/call handler, which the gateway middleware bypasses, and keeps the field unexported, so the wire form is the one place it can be supplied.

func ConvertGatewayToolsToSDK

func ConvertGatewayToolsToSDK(items []ToolDescriptor) []*sdkmcp.Tool

func EnsureStreamableAcceptHeader

func EnsureStreamableAcceptHeader(req *http.Request)

func FirstStringArg

func FirstStringArg(arguments map[string]any, keys ...string) string

func IntArg

func IntArg(arguments map[string]any, key string) (int, bool, error)

func IsNotification

func IsNotification(req JSONRPCRequest) bool

func LimitToolResult

func LimitToolResult(result map[string]any, label string, limit ToolOutputLimit) map[string]any

func PayloadError

func PayloadError(payload map[string]any) error

func RawStringID

func RawStringID(id string) json.RawMessage

func ResultError

func ResultError(payload map[string]any) error

func ServeToolMCPHTTP

func ServeToolMCPHTTP(w http.ResponseWriter, req *http.Request, log *slog.Logger, gateway *ToolGatewayService, contexts *ToolSessionContextStore, session ToolSessionContext)

ServeToolMCPHTTP serves a tool MCP request using the request-carried session context. Callers that own richer per-run context (the ACP session pool) overlay it onto the session before calling.

func StringArg

func StringArg(arguments map[string]any, key string) string

func StructuredContent

func StructuredContent(payload map[string]any) (map[string]any, error)

func ToolGatewayMiddleware

func ToolGatewayMiddleware(gateway *ToolGatewayService, contexts *ToolSessionContextStore, session ToolSessionContext) sdkmcp.Middleware

Types

type AuthorizeResult

type AuthorizeResult struct {
	AuthorizationURL string `json:"authorization_url"`
}

AuthorizeResult holds the authorization URL to redirect the user to.

type Connection

type Connection struct {
	ID            string           `json:"id"`
	BotID         string           `json:"bot_id"`
	Name          string           `json:"name"`
	Type          string           `json:"type"`
	Config        map[string]any   `json:"config"`
	Active        bool             `json:"is_active"`
	Status        string           `json:"status"`
	ToolsCache    []ToolDescriptor `json:"tools_cache"`
	LastProbedAt  *time.Time       `json:"last_probed_at,omitempty"`
	StatusMessage string           `json:"status_message"`
	AuthType      string           `json:"auth_type"`
	CreatedAt     time.Time        `json:"created_at"`
	UpdatedAt     time.Time        `json:"updated_at"`
}

Connection represents a stored MCP connection for a bot.

type ConnectionService

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

ConnectionService handles CRUD operations for MCP connections.

func NewConnectionService

func NewConnectionService(log *slog.Logger, queries dbstore.Queries) *ConnectionService

NewConnectionService creates a ConnectionService backed by sqlc queries.

func (*ConnectionService) BatchDelete

func (s *ConnectionService) BatchDelete(ctx context.Context, botID string, ids []string) error

BatchDelete removes multiple MCP connections by IDs. Invalid IDs are skipped; at least one must succeed for no error.

func (*ConnectionService) Create

func (s *ConnectionService) Create(ctx context.Context, botID string, req UpsertRequest) (Connection, error)

Create inserts a new MCP connection for a bot.

func (*ConnectionService) Delete

func (s *ConnectionService) Delete(ctx context.Context, botID, id string) error

Delete removes an MCP connection.

func (*ConnectionService) ExportByBot

func (s *ConnectionService) ExportByBot(ctx context.Context, botID string) (ExportResponse, error)

ExportByBot returns all connections for a bot in standard mcpServers format.

func (*ConnectionService) Get

func (s *ConnectionService) Get(ctx context.Context, botID, id string) (Connection, error)

Get returns a specific MCP connection for a bot.

func (*ConnectionService) Import

func (s *ConnectionService) Import(ctx context.Context, botID string, req ImportRequest) ([]Connection, error)

Import performs a declarative sync from a standard mcpServers dict. Existing connections (matched by name) get config updated but is_active preserved. New connections are created with is_active=true. Connections not in the input are left untouched.

func (*ConnectionService) ListActiveByBot

func (s *ConnectionService) ListActiveByBot(ctx context.Context, botID string) ([]Connection, error)

ListActiveByBot returns active MCP connections for a bot.

func (*ConnectionService) ListByBot

func (s *ConnectionService) ListByBot(ctx context.Context, botID string) ([]Connection, error)

ListByBot returns all MCP connections for a bot.

func (*ConnectionService) Update

func (s *ConnectionService) Update(ctx context.Context, botID, id string, req UpsertRequest) (Connection, error)

Update modifies an existing MCP connection.

func (*ConnectionService) UpdateProbeResult

func (s *ConnectionService) UpdateProbeResult(ctx context.Context, botID, id, status string, tools []ToolDescriptor, message string) error

UpdateProbeResult persists the result of a probe operation.

type DiscoveryResult

type DiscoveryResult struct {
	ResourceMetadataURL    string   `json:"resource_metadata_url"`
	AuthorizationServerURL string   `json:"authorization_server_url"`
	AuthorizationEndpoint  string   `json:"authorization_endpoint"`
	TokenEndpoint          string   `json:"token_endpoint"`
	RegistrationEndpoint   string   `json:"registration_endpoint,omitempty"`
	ScopesSupported        []string `json:"scopes_supported,omitempty"`
	ResourceURI            string   `json:"resource_uri"`
}

DiscoveryResult holds the result of an OAuth discovery flow.

type ExportResponse

type ExportResponse struct {
	MCPServers map[string]MCPServerEntry `json:"mcpServers"`
}

ExportResponse returns connections in standard mcpServers format.

type ImportRequest

type ImportRequest struct {
	MCPServers map[string]MCPServerEntry `json:"mcpServers"`
}

ImportRequest accepts a standard mcpServers dict for batch import.

type JSONRPCError

type JSONRPCError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

type JSONRPCRequest

type JSONRPCRequest struct {
	JSONRPC string          `json:"jsonrpc"`
	ID      json.RawMessage `json:"id"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params,omitempty"`
}

func NewToolCallRequest

func NewToolCallRequest(id string, toolName string, args map[string]any) (JSONRPCRequest, error)

type JSONRPCResponse

type JSONRPCResponse struct {
	JSONRPC string          `json:"jsonrpc"`
	ID      json.RawMessage `json:"id,omitempty"`
	Result  any             `json:"result,omitempty"`
	Error   *JSONRPCError   `json:"error,omitempty"`
}

func JSONRPCErrorResponse

func JSONRPCErrorResponse(id json.RawMessage, code int, message string) JSONRPCResponse

type ListResponse

type ListResponse struct {
	Items []Connection `json:"items"`
}

ListResponse wraps MCP connection list responses.

type MCPServerEntry

type MCPServerEntry struct {
	Command   string            `json:"command,omitempty"`
	Args      []string          `json:"args,omitempty"`
	Env       map[string]string `json:"env,omitempty"`
	Cwd       string            `json:"cwd,omitempty"`
	URL       string            `json:"url,omitempty"`
	Headers   map[string]string `json:"headers,omitempty"`
	Transport string            `json:"transport,omitempty"`
}

MCPServerEntry is one entry in the standard mcpServers dict.

type OAuthService

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

OAuthService manages OAuth flows for MCP connections.

func NewOAuthService

func NewOAuthService(log *slog.Logger, queries dbstore.Queries, callbackURL string) *OAuthService

func (*OAuthService) Discover

func (s *OAuthService) Discover(ctx context.Context, serverURL string) (*DiscoveryResult, error)

Discover performs the MCP OAuth discovery flow: 1. Send request to MCP server, expect 401 with WWW-Authenticate 2. Fetch Protected Resource Metadata 3. Fetch Authorization Server Metadata.

func (*OAuthService) GetStatus

func (s *OAuthService) GetStatus(ctx context.Context, connectionID string) (*OAuthStatus, error)

GetStatus returns the OAuth status for a connection.

func (*OAuthService) GetValidToken

func (s *OAuthService) GetValidToken(ctx context.Context, connectionID string) (string, error)

GetValidToken returns a valid access token, refreshing if expired.

func (*OAuthService) HandleCallback

func (s *OAuthService) HandleCallback(ctx context.Context, state, code string) (string, error)

HandleCallback exchanges the authorization code for tokens.

func (*OAuthService) RevokeToken

func (s *OAuthService) RevokeToken(ctx context.Context, connectionID string) error

RevokeToken clears stored tokens for a connection.

func (*OAuthService) SaveDiscovery

func (s *OAuthService) SaveDiscovery(ctx context.Context, connectionID string, result *DiscoveryResult) error

SaveDiscovery persists the discovery result for a connection.

func (*OAuthService) StartAuthorization

func (s *OAuthService) StartAuthorization(ctx context.Context, connectionID, clientID, clientSecret, callbackURL string) (*AuthorizeResult, error)

StartAuthorization generates PKCE parameters and returns the authorization URL. Client ID resolution follows MCP spec priority:

  1. User-provided client_id
  2. Previously stored client_id (from prior registration or user input)
  3. Dynamic Client Registration (RFC 7591) if registration_endpoint is available
  4. Error — user must provide a client_id

func (*OAuthService) WithQueries

func (s *OAuthService) WithQueries(queries dbstore.Queries) *OAuthService

WithQueries returns a shallow service copy bound to the supplied queries.

type OAuthStatus

type OAuthStatus struct {
	Configured  bool       `json:"configured"`
	HasToken    bool       `json:"has_token"`
	Expired     bool       `json:"expired"`
	Scopes      string     `json:"scopes,omitempty"`
	ExpiresAt   *time.Time `json:"expires_at,omitempty"`
	AuthServer  string     `json:"auth_server,omitempty"`
	CallbackURL string     `json:"callback_url"`
}

OAuthStatus describes the current OAuth state of a connection.

type ServerError added in v0.22.0

type ServerError struct {
	Name string
	Err  error
}

ServerError ties an import failure to the server entry that caused it.

func (*ServerError) Error added in v0.22.0

func (e *ServerError) Error() string

func (*ServerError) Unwrap added in v0.22.0

func (e *ServerError) Unwrap() error

type ToolCallPayload

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

ToolCallPayload is the MCP tools/call params payload.

func BuildToolCallPayloadFromRaw

func BuildToolCallPayloadFromRaw(params *sdkmcp.CallToolParamsRaw) (ToolCallPayload, error)

type ToolDescriptor

type ToolDescriptor struct {
	Name        string         `json:"name"`
	Description string         `json:"description,omitempty"`
	InputSchema map[string]any `json:"inputSchema"`
}

ToolDescriptor is the MCP tools/list item shape used by the gateway.

type ToolGatewayOption

type ToolGatewayOption func(*ToolGatewayService)

func WithToolOutputLimit

func WithToolOutputLimit(limit ToolOutputLimit) ToolGatewayOption

type ToolGatewayService

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

ToolGatewayService federates tools from gateway sources, including external MCP connections and selected native Memoh tools exposed to ACP runtimes.

func NewToolGatewayService

func NewToolGatewayService(log *slog.Logger, sources []ToolSource, opts ...ToolGatewayOption) *ToolGatewayService

func (*ToolGatewayService) CallTool

func (s *ToolGatewayService) CallTool(ctx context.Context, session ToolSessionContext, payload ToolCallPayload) (map[string]any, error)

func (*ToolGatewayService) ListTools

func (s *ToolGatewayService) ListTools(ctx context.Context, session ToolSessionContext) ([]ToolDescriptor, error)

func (*ToolGatewayService) LookupTool

func (s *ToolGatewayService) LookupTool(ctx context.Context, session ToolSessionContext, toolName string) (ToolDescriptor, bool, error)

type ToolOutputLimit

type ToolOutputLimit = contextlimit.ToolOutputLimit

type ToolRegistry

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

ToolRegistry stores provider ownership and descriptor metadata.

func NewToolRegistry

func NewToolRegistry() *ToolRegistry

func (*ToolRegistry) List

func (r *ToolRegistry) List() []ToolDescriptor

func (*ToolRegistry) Lookup

func (r *ToolRegistry) Lookup(name string) (ToolSource, ToolDescriptor, bool)

func (*ToolRegistry) Register

func (r *ToolRegistry) Register(source ToolSource, tool ToolDescriptor) error

type ToolSessionContext

type ToolSessionContext = toolcontext.Session

ToolSessionContext is the MCP gateway's compatibility name for the shared tool execution context. The canonical type is owned by internal/toolcontext.

func ToolSessionContextFromHTTP

func ToolSessionContextFromHTTP(req *http.Request, fallbackBotID string) ToolSessionContext

type ToolSessionContextStore

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

ToolSessionContextStore registers per-run tool event sinks so gateway HTTP tool calls can stream lifecycle events back to the owning prompt. Session context itself travels with each request (ACP runtimes overlay it from the live runtime handle), so the store holds no session state.

func NewToolSessionContextStore

func NewToolSessionContextStore() *ToolSessionContextStore

func (*ToolSessionContextStore) AppendToolEvent

func (s *ToolSessionContextStore) AppendToolEvent(session ToolSessionContext, event ToolStreamEvent) bool

func (*ToolSessionContextStore) RegisterToolEventSink

func (s *ToolSessionContextStore) RegisterToolEventSink(session ToolSessionContext, sink func(ToolStreamEvent)) func()

type ToolSource

type ToolSource interface {
	ListTools(ctx context.Context, session ToolSessionContext) ([]ToolDescriptor, error)
	CallTool(ctx context.Context, session ToolSessionContext, toolName string, arguments map[string]any) (map[string]any, error)
}

ToolSource represents a tool source surfaced through the MCP gateway. Implementations may wrap federated MCP connections or selected native Memoh ToolProviders.

type ToolSourceDiagnostics added in v0.22.0

type ToolSourceDiagnostics interface {
	ToolDiagnostics(ctx context.Context, session ToolSessionContext) []string
}

ToolSourceDiagnostics is implemented by sources that can explain, in text meant for the model, why some or all of their tools are missing from ListTools. The agent surfaces the lines in the system prompt so a degraded source is reported instead of silently looking empty.

type ToolStreamEvent

type ToolStreamEvent struct {
	Type       string `json:"type"`
	ToolCallID string `json:"tool_call_id,omitempty"`
	ToolName   string `json:"tool_name,omitempty"`
	Input      any    `json:"input,omitempty"`
	Result     any    `json:"result,omitempty"`
	Error      string `json:"error,omitempty"`
	// Approval request fields (Type "tool_approval_request").
	ApprovalID string `json:"approval_id,omitempty"`
	// Interactive request fields (Type "user_input_request"). Carrying the
	// pending interaction over the same channel as tool_call_start lets the UI
	// attach it to the existing tool call block instead of rendering a
	// separate synthetic message.
	UserInputID string         `json:"user_input_id,omitempty"`
	ShortID     int            `json:"short_id,omitempty"`
	Status      string         `json:"status,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`
}

ToolStreamEvent is the stream-safe subset of MCP tools/call lifecycle events that ACP HTTP MCP calls record for live UI replay and persistence.

func (ToolStreamEvent) ToAgentStreamEvent

func (e ToolStreamEvent) ToAgentStreamEvent() (event.StreamEvent, bool)

type UpsertRequest

type UpsertRequest struct {
	Name      string            `json:"name"`
	Command   string            `json:"command,omitempty"`
	Args      []string          `json:"args,omitempty"`
	Env       map[string]string `json:"env,omitempty"`
	Cwd       string            `json:"cwd,omitempty"`
	URL       string            `json:"url,omitempty"`
	Headers   map[string]string `json:"headers,omitempty"`
	Transport string            `json:"transport,omitempty"`
	Active    *bool             `json:"is_active,omitempty"`
	AuthType  string            `json:"auth_type,omitempty"`
}

UpsertRequest accepts standard mcpServers item format. Type is auto-inferred: command present -> stdio, url present -> http (default) or sse (if transport:"sse").

Directories

Path Synopsis
sources

Jump to

Keyboard shortcuts

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