mcp

package
v0.7.24 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: AGPL-3.0 Imports: 16 Imported by: 0

Documentation

Overview

Package mcp exposes memini over the Model Context Protocol. It is a thin adapter over the same service.Service the REST API uses, served over stdio and Streamable HTTP.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HTTPHandler

func HTTPHandler(svc *service.Service, nsHeader, defaultNS, homeHeader, apiKey string,
	keyStore store.APIKeyStore, fileKeys *apiauth.FileKeySet,
) http.Handler

HTTPHandler returns an http.Handler serving MCP over Streamable HTTP.

Auth: apiKey (the admin env key), fileKeys (optional MEMINI_API_KEYS_FILE capability, K2b — nil when unused), and keyStore (optional table-key capability, nil when unsupported/unused) are resolved via apiauth.Config.Authenticate exactly like REST's authMiddleware — see its doc for the full enforcement rules, including when table or file-key auth becomes mandatory. This guarantees the two HTTP surfaces authenticate identically for the same credentials.

Sessions: this handler is served STATELESS (see HTTPHandlerWithAuth), so every request builds its own server and the resolved identity (principal, and the ns/home it carries) is fixed per SERVER INSTANCE — that is, per request here, per process over stdio. It used to be captured once per MCP session, which was a bug: requests 2..N of a session silently kept request 1's namespace/home no matter what their headers said, and a different valid key that reused a session ID inherited the first key's identity and read-only flag. Changed headers and rotated keys now take effect on the very next request.

Namespace: taken from nsHeader when present, else the authenticated key's DefaultNS, else defaultNS; tool calls may still override it per-call. This is namespace resolution as CONTEXT — the header always wins when present.

Home: taken from homeHeader when present — canonicalized exactly like REST's homeMiddleware so both transports resolve the same client input to the same namespace key — else "" (no home leg — unlike the namespace header there is no per-call override). A key bound to a home namespace (HomeNS != "") overrides this outright: the header is ignored entirely (never validated, never consulted), a conflicting value is logged once at debug level, and the request is never rejected for it. This is home resolution as IDENTITY, the deliberate opposite of namespace's header-wins precedence above — see the K2 brief's "SCOPE ADDITION" and REST's homeMiddleware doc for the full rationale.

An invalid nsHeader value is always rejected with 400 (matching the REST API); an invalid homeHeader value is rejected with 400 too, UNLESS the authenticated key is bound (in which case the header is never even looked at) — never silently falling back to the default namespace.

This builds its own apiauth.Config from apiKey/keyStore/fileKeys, which is fine when MCP is the only HTTP surface in the process. When REST is also mounted in the SAME process, use HTTPHandlerWithAuth instead and pass it the exact same apiauth.Config REST uses — otherwise the two surfaces hold independent table-emptiness caches, and an apiauth.Config.Invalidate() call from a REST key mutation never reaches this one (see apiauth.Config's doc on the shared cache pointer).

func HTTPHandlerWithAuth added in v0.6.7

func HTTPHandlerWithAuth(svc *service.Service, nsHeader, defaultNS, homeHeader string,
	keyAuth apiauth.Config,
) http.Handler

HTTPHandlerWithAuth is HTTPHandler but takes an already-built apiauth.Config instead of building one from apiKey/keyStore/fileKeys. Callers that also mount REST in the same process must construct exactly ONE apiauth.Config (e.g. via apiauth.New(...).WithFileKeys(...)) and pass that SAME value to both this function and rest.AuthConfig.KeyAuth — Config is a value type but its cache field is a shared pointer (see apiauth.Config's doc), so a copy still shares the cache and a REST-side Invalidate() reaches MCP immediately.

func IsReadTool added in v0.7.15

func IsReadTool(name string) bool

IsReadTool reports whether name is a tool a read-only session may call. It is exported for the parity test that cross-checks this allowlist against the tools' own ReadOnlyHint annotations.

func NewServer

func NewServer(svc *service.Service, defaultNS, home, author, authorKind string, opts ...ServerOption) *mcpsdk.Server

NewServer builds an MCP server exposing memini's memory tools. defaultNS is used whenever a tool call omits the namespace argument. home is the caller's personal namespace (X-Memini-Home / MEMINI_HOME), merged read-only into every recall/briefing/answer/remember; "" means no home leg. There is no per-call override — home is a transport-level default, fixed for the life of this server INSTANCE, which is one HTTP request (the Streamable HTTP handler is stateless — see HTTPHandlerWithAuth) or one stdio process. author is the name of the NAMED table key that authenticated the request ("" for the admin key, an unauthenticated stdio session, or auth-disabled dev mode); it is stamped as metadata.author on writes via RememberInput.Author — see service.stampAuthor. authorKind classifies author for activity attribution ("key" for a named key, "env" for the admin env key, "none" for an unauthenticated stdio/dev session — see store.Event); a receiving middleware stamps (author, authorKind) onto every tool call's context via service.WithActor, so all tools inherit it without threading a parameter.

func RunStdio

func RunStdio(ctx context.Context, svc *service.Service, defaultNS, home string) error

RunStdio serves the MCP server over stdio, blocking until ctx is cancelled or the client disconnects. Used by `memini mcp` for local agent integrations. home is resolved by the caller from MEMINI_HOME (there are no headers on stdio); "" means no home leg.

Types

type ServerOption added in v0.7.15

type ServerOption func(*serverOpts)

ServerOption customizes NewServer. Options exist so the common call sites — stdio, the docs generator, and a pile of tests — stay unchanged as per-session capabilities accumulate, rather than growing another positional bool argument each time.

func WithReadOnly added in v0.7.15

func WithReadOnly(v bool) ServerOption

WithReadOnly marks the session as authenticated by a read-only credential, so every tool outside readTools is refused at call time.

Jump to

Keyboard shortcuts

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