Documentation
¶
Overview ¶
Package mcp gives memcode an MCP (Model Context Protocol) client: it discovers the servers configured across scopes (local / project / user), connects to them (stdio, streamable HTTP, or SSE), lists their tools, and exposes a single Call entrypoint. This is the same mechanism Claude Code uses to gain third-party tools — and it follows Claude Code's documented model: project-scoped servers live in a checked-in .mcp.json and require explicit approval before use (see approvals.go), while servers you add yourself (local / user scope, in ~/.memcode/mcp.json) are trusted.
The protocol itself is spoken by the official SDK (github.com/modelcontextprotocol/go-sdk); this package handles config, scopes, approval, lifecycle, namespacing, and result flattening. The permission gate on each CALL lives in the runtime package (runtime/mcp.go).
Index ¶
- func AddServer(root string, scope Scope, name string, sc ServerConfig) error
- func ApprovalsPath(root string) string
- func ConfigHash(cfg ServerConfig) string
- func LocalServers(root string) map[string]ServerConfig
- func ProjectFile(root string) string
- func ProjectServers(root string) map[string]ServerConfig
- func RememberCalls(root, name string, cfg ServerConfig, rawTool string) error
- func RemoveServer(root string, scope Scope, name string) (bool, error)
- func ResetApprovals(root string) error
- func SaveApproval(root, name string, cfg ServerConfig, d Decision) error
- func ToolName(server, raw string) string
- func UserServers() map[string]ServerConfig
- func UserStoreFile() string
- type Approvals
- type Decision
- type Manager
- func (m *Manager) Add(ctx context.Context, servers map[string]ServerConfig, opts Options)
- func (m *Manager) Call(ctx context.Context, name string, args map[string]any) (string, bool, error)
- func (m *Manager) Close()
- func (m *Manager) Errors() []error
- func (m *Manager) GetPrompt(ctx context.Context, name string, args map[string]string) (string, error)
- func (m *Manager) Has(name string) bool
- func (m *Manager) Lookup(name string) (Tool, bool)
- func (m *Manager) Prompts() []Prompt
- func (m *Manager) ReadResource(ctx context.Context, uri string) (string, error)
- func (m *Manager) Resources() []Resource
- func (m *Manager) Tools() []Tool
- type Options
- type Prompt
- type PromptArg
- type Resource
- type Scope
- type ScopedServer
- type ServerConfig
- type Tool
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddServer ¶
func AddServer(root string, scope Scope, name string, sc ServerConfig) error
AddServer writes a server into the given scope's store (raw, unexpanded — secrets stay as ${VAR} references). Overwrites an existing entry of the same name in that scope.
func ApprovalsPath ¶
ApprovalsPath is where a project's MCP approval choices live: user-level state under the home directory (like UserStoreFile), keyed by a hash of the canonical project root so each project gets its own file. NEVER inside the repo — see the package header. Returns "" when no home directory can be determined.
func ConfigHash ¶
func ConfigHash(cfg ServerConfig) string
ConfigHash is a stable digest of a server's RAW config (as read from its store, before ${VAR} expansion — see Resolve), so any edit to its .mcp.json entry invalidates a prior approval (re-prompting), while environment changes (which don't alter the committed config) do not — and resolved secrets never feed the hash.
func LocalServers ¶
func LocalServers(root string) map[string]ServerConfig
LocalServers reads the raw local-scoped servers for this project from the user store.
func ProjectFile ¶
ProjectFile is the path to a project's checked-in MCP config.
func ProjectServers ¶
func ProjectServers(root string) map[string]ServerConfig
ProjectServers reads the raw (unexpanded) project-scoped servers from <root>/.mcp.json.
func RememberCalls ¶
func RememberCalls(root, name string, cfg ServerConfig, rawTool string) error
RememberCalls persists an invocation grant: rawTool == "" remembers the whole server ("Don't ask again for <server>"), otherwise the one tool ("Execute and remember"). For a local/user server this creates the record (those scopes are never connect-gated, so the record exists purely to carry grants); a stale-hash record is replaced, not merged.
func RemoveServer ¶
RemoveServer deletes a named server from a scope, reporting whether it existed.
func ResetApprovals ¶
ResetApprovals clears all project-server choices (Claude Code's reset-project-choices). It also removes any legacy repo-resident file (ignored as a trust source, but stale).
func SaveApproval ¶
func SaveApproval(root, name string, cfg ServerConfig, d Decision) error
SaveApproval records a decision for a project server, hashed against its current config. A same-config re-approve keeps any invocation grants; a rejection or config change drops them.
func ToolName ¶
ToolName builds the model-facing name for a server's tool: mcp__<server>__<raw>. Both segments are sanitized to the function-name charset [A-Za-z0-9_] and the whole is capped at maxToolNameLen, so NO lane rejects the request over an odd or long server/tool name. The ORIGINAL raw name is preserved in Tool.Raw and used for the actual CallTool (see Call), so a sanitized/truncated model-facing name never changes which server tool runs. When sanitizing or truncating could make two distinct raw names collide, a short stable hash of the (server,raw) pair disambiguates — keeping byName keys unique. The clean, short common case is returned verbatim (Claude Code's scheme) so familiar names like mcp__supabase__execute_sql are unchanged.
func UserServers ¶
func UserServers() map[string]ServerConfig
UserServers reads the raw user-scoped servers from the user store.
func UserStoreFile ¶
func UserStoreFile() string
UserStoreFile is the path to the user-global MCP store (user + local scopes).
Types ¶
type Approvals ¶
type Approvals map[string]approvalRecord
Approvals is the persisted set of project-server choices for one project.
func LoadApprovals ¶
LoadApprovals reads the remembered choices (absent file → empty, not an error). Only the user-level store is consulted — a repo-committed approvals file grants nothing.
func (Approvals) CallAllowed ¶
func (a Approvals) CallAllowed(name string, cfg ServerConfig, rawTool string) bool
CallAllowed reports whether invoking rawTool on the named server was remembered. False the moment the config hash stops matching — grants die with the config they were made against.
func (Approvals) Status ¶
func (a Approvals) Status(name string, cfg ServerConfig) Decision
Status reports a project server's standing given the current config: "approved" only when a stored approval matches the live config hash; "rejected" when explicitly rejected (and still matching); otherwise "pending" (never decided, or the config changed since).
type Decision ¶
type Decision string
Decision is a remembered approval choice for a project-scoped server.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns the live connections to all configured MCP servers and the merged tool catalog. A nil *Manager is valid and behaves as "no MCP" — all methods are safe to call.
func Connect ¶
Connect connects to each given server (already resolved across scopes and filtered by approval policy — see Resolve and approvals.go), returning a Manager with the merged tool catalog. A server that fails to connect or list is skipped (recorded in Errors), never fatal — one broken server must not sink the session. Returns nil when the set is empty, so callers can treat "no MCP" as the zero case.
func (*Manager) Add ¶
Add connects additional servers into an existing manager and merges their tools — used when a project server is approved mid-session. Safe on a nil receiver (returns it unchanged via the caller). Errors are appended to Errors(), never returned.
func (*Manager) Call ¶
Call invokes a namespaced MCP tool and returns its flattened text, whether the tool reported an error, and any transport error.
func (*Manager) Close ¶
func (m *Manager) Close()
Close tears down every connection. Safe on a nil Manager and idempotent.
func (*Manager) Errors ¶
Errors returns the per-server connect/list failures gathered during Connect.
func (*Manager) GetPrompt ¶
func (m *Manager) GetPrompt(ctx context.Context, name string, args map[string]string) (string, error)
GetPrompt renders a namespaced prompt template with args, returning the flattened message text the model can use.
func (*Manager) Has ¶
Has reports whether name is a known MCP tool (used by the dispatcher to route a call).
func (*Manager) ReadResource ¶
ReadResource fetches a resource's contents by uri, flattened to text.
type Options ¶
type Options struct {
Version string // memcode version reported to servers
AllowOAuth bool // attach the interactive OAuth flow to remote servers that need auth (interactive sessions only)
}
Options configure a connection batch.
type Prompt ¶
type Prompt struct {
Name string // namespaced
Server string
Raw string
Description string
Arguments []PromptArg
}
Prompt is one reusable MCP prompt template a server exposes. Name is namespaced (mcp__<server>__<raw>) for the catalog; the raw name is used with GetPrompt.
type Resource ¶
type Resource struct {
URI string // the server's resource uri (what ReadResource takes)
Server string
Name string
Description string
MIMEType string
}
Resource is one MCP resource exposed by a server — external context (a doc, a schema, a runbook) the model can READ by uri. Namespaced like tools so servers can't collide.
type Scope ¶
type Scope string
Scope is where a server is configured, mirroring Claude Code's three scopes.
const ( // ScopeLocal is private to you in ONE project (stored in ~/.memcode/mcp.json under the // project path). Trusted — you added it. ScopeLocal Scope = "local" // ScopeProject is shared with the team via a checked-in <root>/.mcp.json. UNTRUSTED until // approved (see approvals.go) — it's repo content that could come from anyone. ScopeProject Scope = "project" // ScopeUser is available across all your projects (stored in ~/.memcode/mcp.json). Trusted. ScopeUser Scope = "user" )
type ScopedServer ¶
type ScopedServer struct {
Name string
Scope Scope
Config ServerConfig // raw (unexpanded); ExpandServer before connecting
}
ScopedServer is a server resolved with the scope that won it. Config is the RAW entry as stored (${VAR} references intact): approvals and invocation grants hash the raw config (see approvals.ConfigHash), so env changes never invalidate them and resolved secrets never feed the hash. Expand with ExpandServer at connect time.
func Resolve ¶
func Resolve(root string) []ScopedServer
Resolve returns every configured server merged across scopes with Claude Code's precedence (local > project > user, matched by name; the whole winning entry is used, never merged), each RAW (unexpanded) and tagged with its scope. The caller applies approval policy (project scope) against the raw config and calls ExpandServer only on what it actually connects.
type ServerConfig ¶
type ServerConfig struct {
Type string `json:"type,omitempty"` // stdio | http | streamable-http | sse (inferred when empty)
Command string `json:"command,omitempty"`
Args []string `json:"args,omitempty"`
Env map[string]string `json:"env,omitempty"`
URL string `json:"url,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
// HeadersHelper is an optional command run at connect time whose stdout supplies HTTP
// headers (JSON object, or "Name: value" lines) — for tokens minted per connection rather
// than stored in config. Merged over static Headers.
HeadersHelper string `json:"headersHelper,omitempty"`
// Timeout is a per-server tool-call timeout in milliseconds (overrides the default).
Timeout int `json:"timeout,omitempty"`
// Auth controls remote authentication: "" / "auto" attaches the interactive OAuth flow when
// no static auth header is present; "oauth" forces it; "none" disables it.
Auth string `json:"auth,omitempty"`
}
ServerConfig is one declared MCP server. A stdio server is launched as a subprocess (Command+Args+Env); an http/sse server is reached at URL with optional Headers.
func ExpandServer ¶ added in v0.27.0
func ExpandServer(sc ServerConfig) ServerConfig
ExpandServer expands ${VAR} / ${VAR:-default} in every string the config carries — so a secret like an access token lives in the environment, not committed in .mcp.json. Callers expand at CONNECT time only; approvals/grants always hash the raw config (ConfigHash).
func (ServerConfig) Transport ¶
func (c ServerConfig) Transport() string
Transport returns the normalized transport (stdio | http | sse) for display/inspection.
type Tool ¶
type Tool struct {
Name string // namespaced for the model: mcp__<server>__<raw>
Server string // declaring server name
Raw string // original tool name on the server
Description string // server-provided description
InputSchema map[string]any // JSON-schema object, ready for a tool definition
}
Tool is one discovered MCP tool, flattened for memcode's tool registry.