mcpgateway

package
v0.1.58 Latest Latest
Warning

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

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 31 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.

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"`
}

CatalogFeature is one listed tool or prompt in a catalog view, using the upstream's original (un-prefixed) name.

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"`
	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, after the operator tool filters were applied.

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"`
	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. 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
}

Options configures NewService.

type PostgreSQLStore

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

PostgreSQLStore stores managed MCP servers in PostgreSQL.

func NewPostgreSQLStore

func NewPostgreSQLStore(ctx context.Context, pool *pgxpool.Pool) (*PostgreSQLStore, error)

NewPostgreSQLStore creates the mcp_servers table and indexes if needed.

func (*PostgreSQLStore) Close

func (s *PostgreSQLStore) Close() error

func (*PostgreSQLStore) Delete

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

func (*PostgreSQLStore) Get

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

func (*PostgreSQLStore) List

func (*PostgreSQLStore) Upsert

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

type Result

type Result struct {
	Service *Service
	Store   Store
	Storage storage.Storage
	// 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, httpClient *http.Client, usageLogger usage.LoggerInterface) (*Result, error)

New creates the MCP gateway subsystem with its own storage connection.

func NewWithSharedStorage

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

NewWithSharedStorage 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 SQLiteStore

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

SQLiteStore stores managed MCP servers in SQLite.

func NewSQLiteStore

func NewSQLiteStore(db *sql.DB) (*SQLiteStore, error)

NewSQLiteStore creates the mcp_servers table and indexes if needed.

func (*SQLiteStore) Close

func (s *SQLiteStore) Close() error

func (*SQLiteStore) Delete

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

func (*SQLiteStore) Get

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

func (*SQLiteStore) List

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

func (*SQLiteStore) Upsert

func (s *SQLiteStore) 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
	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
	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