mcpbridge

package
v0.0.0-...-1593ee1 Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2026 License: MIT Imports: 16 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func BearerFromEnvAndFile

func BearerFromEnvAndFile(bearerStr, tokenFileFlag string) (string, error)

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

func NewMCPServer(cfg Config) (*mcp.Server, error)

NewMCPServer builds an MCP server with Ghost Vault tools registered.

func RegisterTools

func RegisterTools(s *mcp.Server, cfg Config) error

RegisterTools adds memory_search, memory_save, and memory_stats to the MCP server.

func TokenReloadPathIfFileBased

func TokenReloadPathIfFileBased(bearerStr, tokenFileFlag string) string

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

func (c *Config) PostIngest(ctx context.Context, vaultID, userID, text string) ([]byte, int, error)

PostIngest calls POST /v1/ingest with the same JSON body shape as memory_save (for tests).

func (*Config) PostRetrieve

func (c *Config) PostRetrieve(ctx context.Context, vaultID, userID, query string, maxChunks, maxTokens int) ([]byte, int, error)

PostRetrieve calls POST /v1/retrieve with the same JSON body as memory_search (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

func ParseOAuthHTTPFromEnv() (*OAuthHTTP, error)

ParseOAuthHTTPFromEnv builds OAuthHTTP when GHOSTVAULT_OAUTH_INTROSPECTION_URL is set; otherwise nil.

func (*OAuthHTTP) AuthorizationServerMetadataHandler

func (o *OAuthHTTP) AuthorizationServerMetadataHandler() http.Handler

AuthorizationServerMetadataHandler serves RFC 8414 metadata pointing back at the facade endpoints.

func (*OAuthHTTP) AuthorizeHandler

func (o *OAuthHTTP) AuthorizeHandler() http.Handler

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

func (o *OAuthHTTP) RegisterHandler() http.Handler

RegisterHandler proxies POST /register to the upstream DCR endpoint (Auth0 /oidc/register). Request body must be application/json (RFC 7591 §3).

func (*OAuthHTTP) TokenHandler

func (o *OAuthHTTP) TokenHandler() http.Handler

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).

func (*OAuthHTTP) VerifyToken

func (o *OAuthHTTP) VerifyToken(ctx context.Context, token string, _ *http.Request) (*auth.TokenInfo, error)

VerifyToken implements auth.TokenVerifier via RFC 7662 introspection.

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.

Jump to

Keyboard shortcuts

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