Documentation
¶
Index ¶
- Constants
- Variables
- func BoolArg(arguments map[string]any, key string) (bool, bool, error)
- func BuildToolErrorResult(message string) map[string]any
- func BuildToolMCPServer(gateway *ToolGatewayService, contexts *ToolSessionContextStore, ...) *sdkmcp.Server
- func BuildToolSuccessResult(structured any) map[string]any
- func ContentText(result map[string]any) string
- func ConvertGatewayCallResultToSDK(result map[string]any, resultTypeRequired bool) (*sdkmcp.CallToolResult, error)
- func ConvertGatewayToolsToSDK(items []ToolDescriptor) []*sdkmcp.Tool
- func EnsureStreamableAcceptHeader(req *http.Request)
- func FirstStringArg(arguments map[string]any, keys ...string) string
- func IntArg(arguments map[string]any, key string) (int, bool, error)
- func IsNotification(req JSONRPCRequest) bool
- func LimitToolResult(result map[string]any, label string, limit ToolOutputLimit) map[string]any
- func PayloadError(payload map[string]any) error
- func RawStringID(id string) json.RawMessage
- func ResultError(payload map[string]any) error
- func ServeToolMCPHTTP(w http.ResponseWriter, req *http.Request, log *slog.Logger, ...)
- func StringArg(arguments map[string]any, key string) string
- func StructuredContent(payload map[string]any) (map[string]any, error)
- func ToolGatewayMiddleware(gateway *ToolGatewayService, contexts *ToolSessionContextStore, ...) sdkmcp.Middleware
- type AuthorizeResult
- type Connection
- type ConnectionService
- func (s *ConnectionService) BatchDelete(ctx context.Context, botID string, ids []string) error
- func (s *ConnectionService) Create(ctx context.Context, botID string, req UpsertRequest) (Connection, error)
- func (s *ConnectionService) Delete(ctx context.Context, botID, id string) error
- func (s *ConnectionService) ExportByBot(ctx context.Context, botID string) (ExportResponse, error)
- func (s *ConnectionService) Get(ctx context.Context, botID, id string) (Connection, error)
- func (s *ConnectionService) Import(ctx context.Context, botID string, req ImportRequest) ([]Connection, error)
- func (s *ConnectionService) ListActiveByBot(ctx context.Context, botID string) ([]Connection, error)
- func (s *ConnectionService) ListByBot(ctx context.Context, botID string) ([]Connection, error)
- func (s *ConnectionService) Update(ctx context.Context, botID, id string, req UpsertRequest) (Connection, error)
- func (s *ConnectionService) UpdateProbeResult(ctx context.Context, botID, id, status string, tools []ToolDescriptor, ...) error
- type DiscoveryResult
- type ExportResponse
- type ImportRequest
- type JSONRPCError
- type JSONRPCRequest
- type JSONRPCResponse
- type ListResponse
- type MCPServerEntry
- type OAuthService
- func (s *OAuthService) Discover(ctx context.Context, serverURL string) (*DiscoveryResult, error)
- func (s *OAuthService) GetStatus(ctx context.Context, connectionID string) (*OAuthStatus, error)
- func (s *OAuthService) GetValidToken(ctx context.Context, connectionID string) (string, error)
- func (s *OAuthService) HandleCallback(ctx context.Context, state, code string) (string, error)
- func (s *OAuthService) RevokeToken(ctx context.Context, connectionID string) error
- func (s *OAuthService) SaveDiscovery(ctx context.Context, connectionID string, result *DiscoveryResult) error
- func (s *OAuthService) StartAuthorization(ctx context.Context, connectionID, clientID, clientSecret, callbackURL string) (*AuthorizeResult, error)
- func (s *OAuthService) WithQueries(queries dbstore.Queries) *OAuthService
- type OAuthStatus
- type ServerError
- type ToolCallPayload
- type ToolDescriptor
- type ToolGatewayOption
- type ToolGatewayService
- func (s *ToolGatewayService) CallTool(ctx context.Context, session ToolSessionContext, payload ToolCallPayload) (map[string]any, error)
- func (s *ToolGatewayService) ListTools(ctx context.Context, session ToolSessionContext) ([]ToolDescriptor, error)
- func (s *ToolGatewayService) LookupTool(ctx context.Context, session ToolSessionContext, toolName string) (ToolDescriptor, bool, error)
- type ToolOutputLimit
- type ToolRegistry
- type ToolSessionContext
- type ToolSessionContextStore
- type ToolSource
- type ToolSourceDiagnostics
- type ToolStreamEvent
- type UpsertRequest
Constants ¶
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" 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 ¶
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") )
var ErrToolNotFound = errors.New("tool not found")
ErrToolNotFound indicates the provider does not own the requested tool.
Functions ¶
func BuildToolErrorResult ¶
BuildToolErrorResult builds a standard MCP tool error result object.
func BuildToolMCPServer ¶
func BuildToolMCPServer(gateway *ToolGatewayService, contexts *ToolSessionContextStore, session ToolSessionContext) *sdkmcp.Server
func BuildToolSuccessResult ¶
BuildToolSuccessResult builds a standard MCP tool success result object.
func ContentText ¶
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 IsNotification ¶
func IsNotification(req JSONRPCRequest) bool
func LimitToolResult ¶
func PayloadError ¶
func RawStringID ¶
func RawStringID(id string) json.RawMessage
func ResultError ¶
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 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 ¶
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 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 ¶
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 (*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 ¶
GetValidToken returns a valid access token, refreshing if expired.
func (*OAuthService) HandleCallback ¶
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:
- User-provided client_id
- Previously stored client_id (from prior registration or user input)
- Dynamic Client Registration (RFC 7591) if registration_endpoint is available
- 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
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").