Documentation
¶
Overview ¶
Package edge is the client-facing side of the gateway.
It serves the Streamable HTTP MCP endpoint and guards it: every request is first validated for a permitted Origin (a DNS-rebinding defense, design §8) and then authenticated by a static API key resolved to a client identity (ADR-0003). The request guard is ordinary net/http middleware so it composes in front of the MCP handler; on success it carries the authenticated domain.Identity forward in the request context, and on failure it rejects at the door without invoking the wrapped handler.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IdentityFromContext ¶
IdentityFromContext returns the authenticated identity the request guard placed in ctx, and whether one was present. Handlers downstream of Guard.Wrap use it to attribute a request to its client.
func NewHandler ¶
NewHandler builds the client-facing http.Handler: the request guard (Origin/DNS-rebinding validation + API-key authentication) wrapping a per-connection Streamable HTTP MCP server.
Types ¶
type ClientKey ¶
type ClientKey struct {
// ID is the client identity (for example "claude-desktop").
ID string
// Key is the secret API-key value that authenticates that identity.
Key string
}
ClientKey binds a configured client identity to its resolved API-key value. The composition root resolves each client's api_key_env to a value at startup and hands the pairs here; this package never reads environment itself.
type Config ¶
type Config struct {
// ServerName and ServerVersion identify the gateway to clients during the MCP
// initialize handshake.
ServerName string
ServerVersion string
// Guard authenticates and Origin-checks every request before it reaches the
// MCP handler. It is required: NewHandler wraps the MCP handler with it.
Guard *Guard
// NewSession builds the per-connection Session for an authenticated identity.
NewSession SessionFactory
// SessionTimeout closes a client session that has received no requests for this
// long, which also reclaims its downstream sessions. Zero leaves idle sessions
// open (the registry idle reaper still reclaims downstream subprocesses).
SessionTimeout time.Duration
}
Config wires the client-facing MCP server.
type Guard ¶
type Guard struct {
// contains filtered or unexported fields
}
Guard is the edge request guard: Origin/DNS-rebinding validation followed by constant-time API-key authentication. It is safe for concurrent use, and its allowed origins and client keys are hot-reloadable: Reload swaps them atomically behind a read-write mutex so a SIGHUP config reload never drops a request in flight (design §5).
func NewGuard ¶
NewGuard builds a request guard from the permitted Origins and the resolved client keys. An Origin entry may end in "*" to match any Origin sharing the prefix before it (for example "vscode-webview://*"); other entries match exactly. The inputs are copied so later mutation by the caller cannot change the guard's decisions.
func (*Guard) Reload ¶
Reload atomically replaces the guard's allowed origins and client keys for a SIGHUP/file-watch config reload (design §5). Requests already in flight finish against whichever snapshot they read; subsequent requests see the new one. It is safe to call concurrently with request handling.
func (*Guard) Wrap ¶
Wrap returns a handler that applies the guard before delegating to next. A request with a disallowed Origin is rejected with 403; a request without a valid Bearer API key is rejected with 401 (and a WWW-Authenticate challenge). Only a request that passes both checks reaches next, with the authenticated identity injected into its context.
type Session ¶
type Session interface {
// ListTools returns one page of the client's namespaced, policy-filtered
// catalog plus the cursor for the next page ("" when the page is the last).
// The cursor is opaque and is carried to and from the client verbatim.
ListTools(ctx context.Context, cursor string) (page domain.Catalog, next string, err error)
// Call resolves a namespaced tool name and runs the invocation through the
// security pipeline, returning the downstream result. The result's Content is
// the downstream CallToolResult as (possibly redacted) JSON bytes. It returns a
// non-nil result or a non-nil error, never both nil.
Call(ctx context.Context, name string, args json.RawMessage) (*domain.Result, error)
// Close releases the connection's downstream sessions. It is called once, when
// the client's MCP session ends.
Close() error
}
Session is one client connection's view of the gateway: the policy-filtered tool catalog it may see and the pipeline-guarded invocation of those tools. The composition root supplies an implementation per connection (composing a per-connection dispatcher, the security stage chain, aggregation, and policy); this package translates between that implementation and the MCP wire, and so imports neither registry, aggregate, nor policy (ADR-0014).