mcpgateway

package
v0.1.98 Latest Latest
Warning

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

Go to latest
Published: Sep 26, 2026 License: MIT Imports: 32 Imported by: 0

Documentation

Overview

Package mcpgateway aggregates upstream MCP servers behind GoModel's authenticated /mcp endpoints. The gateway terminates the MCP protocol on both legs: it is an MCP server to clients and an MCP client to upstreams. It is also the credential boundary — client bearer tokens never reach an upstream; upstream credentials come only from server configuration.

Index

Constants

View Source
const ScopeHeader = "X-MCP-Servers"

ScopeHeader restricts a request's visible servers to a comma-separated subset, so one gateway key can serve differently-scoped clients without extra endpoints. Unknown names are ignored; an empty header means all.

Variables

View Source
var ErrNotFound = errors.New("mcp server not found")

ErrNotFound indicates a requested managed MCP server was not found.

View Source
var ErrServerNotVisible = errors.New("server is not available for this user path")

ErrServerNotVisible rejects a call from a session whose user path may no longer use the server.

View Source
var ErrToolExcluded = errors.New("tool is excluded by the gateway tool filters")

ErrToolExcluded rejects a call to a tool the operator filters hide.

Functions

func NamespacedName

func NamespacedName(server, name string) string

NamespacedName is the aggregated-endpoint name for one upstream feature.

Types

type CatalogFeature

type CatalogFeature struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	ReadOnly    bool   `json:"read_only,omitempty"`
	Destructive bool   `json:"destructive,omitempty"`
}

CatalogFeature is one listed tool or prompt in a catalog view, using the upstream's original (un-prefixed) name. ReadOnly and Destructive relay the upstream's tool annotations only when it set them explicitly; they are hints for operators choosing tools to exclude, not guarantees.

type CatalogResource

type CatalogResource struct {
	URI         string `json:"uri"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
}

CatalogResource is one listed resource in a catalog view.

type CatalogTemplate

type CatalogTemplate struct {
	URITemplate string `json:"uri_template"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
}

CatalogTemplate is one listed resource template in a catalog view.

type CatalogView

type CatalogView struct {
	Server        string            `json:"server"`
	Status        ServerStatus      `json:"status"`
	Instructions  string            `json:"instructions,omitempty"`
	Tools         []CatalogFeature  `json:"tools"`
	ExcludedTools []CatalogFeature  `json:"excluded_tools"`
	Prompts       []CatalogFeature  `json:"prompts"`
	Resources     []CatalogResource `json:"resources"`
	Templates     []CatalogTemplate `json:"templates"`
}

CatalogView is the admin-facing snapshot of what one upstream currently exposes through the gateway. Tools are the ones the operator tool filters expose; ExcludedTools are discovered upstream but hidden by those filters.

type ManagedServer

type ManagedServer struct {
	// Name is the immutable ASCII slug and remains the storage primary key.
	Name        string `json:"slug"`
	DisplayName string `json:"name"`

	URL                 string            `json:"url"`
	Transport           string            `json:"transport"`
	Headers             map[string]string `json:"headers,omitempty"`
	Description         string            `json:"description,omitempty"`
	Enabled             bool              `json:"enabled"`
	AllowedTools        []string          `json:"allowed_tools,omitempty"`
	DisallowedTools     []string          `json:"disallowed_tools,omitempty"`
	UserPaths           []string          `json:"user_paths,omitempty"`
	DisallowedUserPaths []string          `json:"disallowed_user_paths,omitempty"`
	ToolTimeoutSeconds  int               `json:"tool_timeout_seconds,omitempty"`
	CreatedAt           time.Time         `json:"created_at"`
	UpdatedAt           time.Time         `json:"updated_at"`
}

ManagedServer is one admin-managed upstream server row. Stdio fields are deliberately absent: runtime-registered subprocesses are a remote code execution vector (see the gateway spec), so stdio servers exist only as declarative config.

func (ManagedServer) Spec

func (m ManagedServer) Spec() ServerSpec

Spec converts the row into a runtime spec.

func (*ManagedServer) Validate

func (m *ManagedServer) Validate() error

Validate checks the row against the same rules as declarative config, additionally rejecting the stdio transport. The receiver is only mutated (normalized transport/URL) once every check has passed.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager owns the set of upstream connections and their catalogs.

func NewManager

func NewManager(httpClient *http.Client) *Manager

NewManager creates an empty manager. Apply installs the initial specs.

func (*Manager) Apply

func (m *Manager) Apply(specs []ServerSpec)

Apply reconciles the running upstreams with the desired specs: removed servers are closed, new servers are added, changed servers are redialed. Unchanged servers keep their live session and catalog; servers whose only change is the access policy (tool filters, user-path scopes) keep their session and apply the new policy in place. Initial connects run asynchronously so startup and admin edits never block on upstream IO.

func (*Manager) CallTool

func (m *Manager) CallTool(ctx context.Context, server, tool string, args json.RawMessage) (*mcp.CallToolResult, error)

CallTool forwards one tool call to the named server using the original (un-prefixed) tool name.

func (*Manager) Close

func (m *Manager) Close()

Close terminates the maintenance loop and every upstream session.

func (*Manager) GetPrompt

func (m *Manager) GetPrompt(ctx context.Context, server string, params *mcp.GetPromptParams) (*mcp.GetPromptResult, error)

GetPrompt forwards one prompts/get to the named server.

func (*Manager) ReadResource

func (m *Manager) ReadResource(ctx context.Context, server string, params *mcp.ReadResourceParams) (*mcp.ReadResourceResult, error)

ReadResource forwards one resources/read to the named server.

func (*Manager) Reconnect

func (m *Manager) Reconnect(ctx context.Context, name string) (ServerView, error)

Reconnect force-redials one server and relists its catalog synchronously.

func (*Manager) Views

func (m *Manager) Views() []ServerView

Views returns admin snapshots of every upstream, sorted by name.

type MongoDBStore

type MongoDBStore struct {
	// contains filtered or unexported fields
}

MongoDBStore stores managed MCP servers in MongoDB.

func NewMongoDBStore

func NewMongoDBStore(database *mongo.Database) (*MongoDBStore, error)

NewMongoDBStore creates collection indexes if needed.

func (*MongoDBStore) Close

func (s *MongoDBStore) Close() error

func (*MongoDBStore) Delete

func (s *MongoDBStore) Delete(ctx context.Context, name string) error

func (*MongoDBStore) Get

func (s *MongoDBStore) Get(ctx context.Context, name string) (*ManagedServer, error)

func (*MongoDBStore) List

func (s *MongoDBStore) List(ctx context.Context) ([]ManagedServer, error)

func (*MongoDBStore) Upsert

func (s *MongoDBStore) Upsert(ctx context.Context, server ManagedServer) error

type Options

type Options struct {
	// ConfigServers are the declarative servers from config.yaml / MCP_SERVERS.
	ConfigServers map[string]ServerSpec
	// Store persists admin-managed servers. Optional.
	Store Store
	// HTTPClient is the shared outbound HTTP client for http/sse upstreams.
	HTTPClient *http.Client
	// UsageLogger records one usage entry per tool call. Optional.
	UsageLogger usage.LoggerInterface
	// UserPathHeader is the configured user-path header name.
	UserPathHeader string
	// AllowedOrigins are the browser origins permitted to reach the endpoint.
	// Empty trusts none, which is the default; see originGuard.
	AllowedOrigins []string
}

Options configures NewService.

type Result

type Result struct {
	Service *Service
	Store   Store
	// contains filtered or unexported fields
}

Result holds the initialized MCP gateway and any owned resources.

func New

func New(ctx context.Context, cfg *config.Config, shared storage.Storage, httpClient *http.Client, usageLogger usage.LoggerInterface) (*Result, error)

New creates the MCP gateway subsystem using an existing storage connection.

func (*Result) Close

func (r *Result) Close() error

Close releases resources held by the MCP gateway subsystem.

type SQLStore added in v0.1.60

type SQLStore struct {
	// contains filtered or unexported fields
}

SQLStore stores managed MCP servers in a SQL database.

func NewSQLStore added in v0.1.60

func NewSQLStore(ctx context.Context, db sqlx.DB) (*SQLStore, error)

NewSQLStore creates the mcp_servers table and indexes if needed.

func (*SQLStore) Close added in v0.1.60

func (s *SQLStore) Close() error

func (*SQLStore) Delete added in v0.1.60

func (s *SQLStore) Delete(ctx context.Context, name string) error

func (*SQLStore) Get added in v0.1.60

func (s *SQLStore) Get(ctx context.Context, name string) (*ManagedServer, error)

func (*SQLStore) List added in v0.1.60

func (s *SQLStore) List(ctx context.Context) ([]ManagedServer, error)

func (*SQLStore) Upsert added in v0.1.60

func (s *SQLStore) Upsert(ctx context.Context, server ManagedServer) error

type ServerSpec

type ServerSpec struct {
	// Name is the stable ASCII slug used for routing and namespacing.
	Name        string
	DisplayName string

	URL             string
	Transport       string
	Headers         map[string]string
	Command         string
	Args            []string
	Env             map[string]string
	Description     string
	Enabled         bool
	AllowedTools    []string
	DisallowedTools []string
	UserPaths       []string
	// DisallowedUserPaths hides the server from these subtrees; it wins over
	// UserPaths.
	DisallowedUserPaths []string
	ToolTimeout         time.Duration

	// Managed marks specs declared in config.yaml / MCP_SERVERS. They override
	// admin-store rows with the same name and are read-only in the dashboard.
	Managed bool
}

ServerSpec is the runtime-normalized definition of one upstream server, merged from declarative config (Managed=true) and the admin store.

func SpecFromConfig

func SpecFromConfig(name string, cfg config.MCPServerConfig) ServerSpec

SpecFromConfig converts one declarative config entry into a runtime spec.

type ServerStatus

type ServerStatus string

ServerStatus describes the runtime connection state of one upstream server.

const (
	// StatusDisabled means the server is declared but switched off.
	StatusDisabled ServerStatus = "disabled"
	// StatusConnecting means no session has been established yet.
	StatusConnecting ServerStatus = "connecting"
	// StatusConnected means the session is live and the catalog is fresh.
	StatusConnected ServerStatus = "connected"
	// StatusDegraded means the last connect or listing failed; any previous
	// catalog is kept (stale carry-forward) and the server is re-probed.
	StatusDegraded ServerStatus = "degraded"
)

type ServerView

type ServerView struct {
	Spec      ServerSpec
	Status    ServerStatus
	LastError string
	ToolCount int
	// ExcludedToolCount counts discovered tools hidden by the tool filters.
	ExcludedToolCount int
	PromptCount       int
	// ResourceCount includes resource templates.
	ResourceCount int
	ConnectedAt   time.Time
}

ServerView is a point-in-time snapshot of one upstream for admin and dashboard consumption.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service is the MCP gateway: it merges declarative and admin-store server specs into the upstream manager and serves the downstream MCP endpoints.

func NewService

func NewService(ctx context.Context, opts Options) (*Service, error)

NewService builds the gateway service and starts connecting to the merged server set. Upstream connects are asynchronous; construction never blocks.

func (*Service) Catalog

func (s *Service) Catalog(name string) (CatalogView, bool)

Catalog returns the current catalog snapshot for one server, for the admin API and dashboard inspector. ok is false for unknown server names; a known server that has never listed successfully returns empty (non-nil) lists.

func (*Service) Close

func (s *Service) Close()

Close stops background work, terminates upstream sessions, and cancels downstream HTTP exchanges. Streamable HTTP clients keep a GET request open for server events, so those request contexts must be ended before the HTTP server can complete its graceful drain.

func (*Service) Delete

func (s *Service) Delete(ctx context.Context, name string) error

Delete removes one admin-managed server, then reconciles.

func (*Service) GetManaged

func (s *Service) GetManaged(ctx context.Context, name string) (*ManagedServer, error)

GetManaged returns one admin-managed server row from the store. Config- declared servers are not store rows, so they (and a missing store) report ErrNotFound.

func (*Service) IsManaged

func (s *Service) IsManaged(name string) bool

IsManaged reports whether name is declared in config/env (read-only).

func (*Service) Reconnect

func (s *Service) Reconnect(ctx context.Context, name string) (ServerView, error)

Reconnect force-redials one server and returns its fresh state.

func (*Service) Reload

func (s *Service) Reload(ctx context.Context) error

Reload re-merges declarative and store specs and reconciles the upstream set. Declarative entries shadow store rows with the same name, mirroring the tagging/virtual-models source precedence.

func (*Service) ServeHTTP

func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request, pinnedServer string) error

ServeHTTP handles one downstream MCP HTTP exchange. pinnedServer is the /mcp/{server} path segment ("" for the aggregated endpoint). Gateway authentication has already run; this layer enforces session-to-principal binding and stamps the internal identity headers tool handlers read.

func (*Service) Upsert

func (s *Service) Upsert(ctx context.Context, server ManagedServer) error

Upsert validates and persists one admin-managed server, then reconciles. Config-declared names are read-only; stdio definitions are rejected at the store boundary (declarative-only by design — see the gateway spec).

func (*Service) Views

func (s *Service) Views() []ServerView

Views returns the current admin snapshot of all servers.

type Store

type Store interface {
	List(ctx context.Context) ([]ManagedServer, error)
	Get(ctx context.Context, name string) (*ManagedServer, error)
	Upsert(ctx context.Context, server ManagedServer) error
	Delete(ctx context.Context, name string) error
	Close() error
}

Store defines persistence operations for admin-managed MCP servers.

Jump to

Keyboard shortcuts

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