Documentation
¶
Overview ¶
Package mcpbridge registers Ghost Vault REST operations as MCP tools (memory_search, memory_save, memory_stats).
OAuth helpers for streamable HTTP MCP: RFC 9728 protected-resource metadata and RFC 7662 token introspection (see github.com/modelcontextprotocol/go-sdk/examples/auth/server).
OAuth 2.1 facade served on the MCP host itself to work around claude.ai ignoring RFC 9728 authorization_servers and instead constructing /authorize, /token and /register on the MCP host (see anthropics/claude-ai-mcp#82). These handlers 302-redirect (authorize) or reverse-proxy (token, register) to the upstream IdP (Auth0 by default), injecting the "audience" parameter so Auth0 issues a JWT bound to GHOSTVAULT_OAUTH_RESOURCE.
Index ¶
- func BearerFromEnvAndFile(bearerStr, tokenFileFlag string) (string, error)
- func NewMCPServer(cfg Config) (*mcp.Server, error)
- func RegisterTools(s *mcp.Server, cfg Config) error
- func TokenReloadPathIfFileBased(bearerStr, tokenFileFlag string) string
- type Config
- type OAuthHTTP
- func (o *OAuthHTTP) AuthorizationServerMetadataHandler() http.Handler
- func (o *OAuthHTTP) AuthorizeHandler() http.Handler
- func (o *OAuthHTTP) ProtectedResourceMetadata() *oauthex.ProtectedResourceMetadata
- func (o *OAuthHTTP) RegisterHandler() http.Handler
- func (o *OAuthHTTP) TokenHandler() http.Handler
- func (o *OAuthHTTP) VerifyToken(ctx context.Context, token string, _ *http.Request) (*auth.TokenInfo, error)
- type UpstreamOverrides
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BearerFromEnvAndFile ¶
BearerFromEnvAndFile resolves the session token. Precedence: non-empty bearerStr (from -bearer / GHOSTVAULT_BEARER_TOKEN) always wins; the token file is used only when that value is empty. Then: tokenFileFlag, else GHOSTVAULT_TOKEN_FILE, else .ghostvault-bearer if that path exists.
func NewMCPServer ¶
NewMCPServer builds an MCP server with Ghost Vault tools registered.
func RegisterTools ¶
RegisterTools adds memory_search, memory_save, and memory_stats to the MCP server.
func TokenReloadPathIfFileBased ¶
TokenReloadPathIfFileBased returns the token file path when the bearer is loaded from disk (no non-empty bearerStr from env/flag). When non-empty, callers may re-read this path before each gvsvd request so rotate-token / unlock updates apply without restarting gvmcp.
Types ¶
type Config ¶
type Config struct {
// BaseURL is the gvsvd origin without a trailing slash, e.g. http://127.0.0.1:8989/api (Docker edge) or http://ghostvault:8080 inside Compose.
BaseURL string
// BearerToken is the session token or (plaintext-vault) actions token (initial value from env/file at startup).
BearerToken string
// TokenReloadPath is set when BearerToken came from a file, not GHOSTVAULT_BEARER_TOKEN / -bearer.
// When non-empty, post() re-reads this file before each gvsvd request.
TokenReloadPath string
// DefaultVaultID and DefaultUserID fill tool args when the model omits them (from GHOSTVAULT_DEFAULT_VAULT_ID / GHOSTVAULT_DEFAULT_USER_ID).
DefaultVaultID string
DefaultUserID string
// HTTPClient is used for POST/GET to gvsvd. If nil, a client with a 125s timeout is used.
HTTPClient *http.Client
}
Config holds HTTP client settings to reach gvsvd.
func (*Config) PostIngest ¶
PostIngest calls POST /v1/ingest with the same JSON body shape as memory_save (for tests).
type OAuthHTTP ¶
type OAuthHTTP struct {
AuthServerIssuer string
ResourceURL string
MetadataURL string
// IntrospectionURL is the RFC 7662 token introspection endpoint (POST, form body token=…).
IntrospectionURL string
IntrospectionClientID string
IntrospectionClientSecret string
// RequiredScopes, if non-empty, must all appear on the token (introspection "scope" split on spaces).
RequiredScopes []string
// ScopesSupported is advertised in protected-resource metadata (RFC 9728). If nil, defaults to RequiredScopes.
ScopesSupported []string
// Upstream Auth0 (or any RFC 8414 AS) endpoints the facade on the MCP host delegates to.
// Claude.ai currently ignores authorization_servers from RFC 9728 metadata and instead
// builds /authorize, /token and /register on the MCP host itself (anthropics/claude-ai-mcp#82),
// so gvmcp exposes a thin facade that 302s / proxies to these upstream URLs.
UpstreamAuthorizeURL string
UpstreamTokenURL string
UpstreamRegisterURL string
// AudienceURL is injected into /authorize and /token as the OAuth 2.0 "audience" parameter
// (Auth0-specific extension) when the caller did not supply one, so the issued access token
// is bound to the MCP resource identifier. Defaults to ResourceURL.
AudienceURL string
HTTPClient *http.Client
}
OAuthHTTP bundles OAuth 2.0 resource-server settings for gvmcp streamable HTTP mode.
func NewOAuthHTTP ¶
func NewOAuthHTTP(issuer, resourceURL, metadataURL, introspectionURL, introClientID, introSecret string, requiredScopes, scopesSupported []string, up UpstreamOverrides) (*OAuthHTTP, error)
NewOAuthHTTP builds OAuth settings for gvmcp. If introspectionURL is empty, returns nil, nil.
func ParseOAuthHTTPFromEnv ¶
ParseOAuthHTTPFromEnv builds OAuthHTTP when GHOSTVAULT_OAUTH_INTROSPECTION_URL is set; otherwise nil.
func (*OAuthHTTP) AuthorizationServerMetadataHandler ¶
AuthorizationServerMetadataHandler serves RFC 8414 metadata pointing back at the facade endpoints.
func (*OAuthHTTP) AuthorizeHandler ¶
AuthorizeHandler 302-redirects to the upstream authorization endpoint, forwarding the query and setting `audience` to the configured canonical value when GHOSTVAULT_OAUTH_AUDIENCE is set. We always override any client-supplied audience: hosts like Auth0 match API identifiers as exact strings; Claude sometimes sends an audience derived from the resource URL without a trailing slash while the Auth0 API Identifier uses a trailing slash — forwarding the wrong value causes "Service not found" even when the API exists.
func (*OAuthHTTP) ProtectedResourceMetadata ¶
func (o *OAuthHTTP) ProtectedResourceMetadata() *oauthex.ProtectedResourceMetadata
ProtectedResourceMetadata returns RFC 9728 metadata for /.well-known/oauth-protected-resource.
func (*OAuthHTTP) RegisterHandler ¶
RegisterHandler proxies POST /register to the upstream DCR endpoint (Auth0 /oidc/register). Request body must be application/json (RFC 7591 §3).
func (*OAuthHTTP) TokenHandler ¶
TokenHandler proxies POST /token to the upstream token endpoint. Request body must be application/x-www-form-urlencoded (RFC 6749 §4.1.3). Sets `audience` to the configured value when set (same override rationale as AuthorizeHandler).
type UpstreamOverrides ¶
type UpstreamOverrides struct {
AuthorizeURL string
TokenURL string
RegisterURL string
Audience string
}
UpstreamOverrides carries optional explicit upstream endpoint URLs for NewOAuthHTTP. Any field left empty is derived from issuer ({issuer}authorize, {issuer}oauth/token, {issuer}oidc/register). Audience defaults to resourceURL when empty.