Documentation
¶
Overview ¶
Package resolvemcp exposes registered database models as Model Context Protocol (MCP) tools and resources over HTTP/SSE transport.
It mirrors the resolvespec package patterns:
- Same model registration API
- Same filter, sort, cursor pagination, preload options
- Same lifecycle hook system
Usage:
handler := resolvemcp.NewHandlerWithGORM(db, resolvemcp.Config{BaseURL: "http://localhost:8080"})
handler.RegisterModel("public", "users", &User{})
r := mux.NewRouter()
resolvemcp.SetupMuxRoutes(r, handler)
Index ¶
- func GetEntity(ctx context.Context) string
- func GetModel(ctx context.Context) interface{}
- func GetModelPtr(ctx context.Context) interface{}
- func GetSchema(ctx context.Context) string
- func GetTableName(ctx context.Context) string
- func NewSSEServer(handler *Handler) http.Handler
- func NewStreamableHTTPHandler(handler *Handler) http.Handler
- func OAuth2CallbackHandler(auth *security.DatabaseAuthenticator, providerName, afterLoginRedirect string, ...) http.HandlerFunc
- func OAuth2LoginHandler(auth *security.DatabaseAuthenticator, providerName string) http.HandlerFunc
- func RegisterSecurityHooks(handler *Handler, securityList *security.SecurityList)
- func SetupBunRouterRoutes(router *bunrouter.Router, handler *Handler)
- func SetupBunRouterStreamableHTTPRoutes(router *bunrouter.Router, handler *Handler)
- func SetupMuxOAuth2Routes(muxRouter *mux.Router, auth *security.DatabaseAuthenticator, ...)
- func SetupMuxRoutes(muxRouter *mux.Router, handler *Handler)
- func SetupMuxRoutesWithAuth(muxRouter *mux.Router, handler *Handler, securityList *security.SecurityList)
- func SetupMuxStreamableHTTPRoutes(muxRouter *mux.Router, handler *Handler)
- func SetupMuxStreamableHTTPRoutesWithAuth(muxRouter *mux.Router, handler *Handler, securityList *security.SecurityList)
- func WithEntity(ctx context.Context, entity string) context.Context
- func WithModel(ctx context.Context, model interface{}) context.Context
- func WithModelPtr(ctx context.Context, modelPtr interface{}) context.Context
- func WithSchema(ctx context.Context, schema string) context.Context
- func WithTableName(ctx context.Context, tableName string) context.Context
- type Config
- type Handler
- func (h *Handler) AuthedSSEServer(securityList *security.SecurityList) http.Handler
- func (h *Handler) AuthedStreamableHTTPServer(securityList *security.SecurityList) http.Handler
- func (h *Handler) EnableOAuthServer(cfg security.OAuthServerConfig, auth *security.DatabaseAuthenticator)
- func (h *Handler) GetDatabase() common.Database
- func (h *Handler) HTTPHandler(securityList *security.SecurityList) http.Handler
- func (h *Handler) Hooks() *HookRegistry
- func (h *Handler) MCPServer() *server.MCPServer
- func (h *Handler) OptionalAuthSSEServer(securityList *security.SecurityList) http.Handler
- func (h *Handler) OptionalAuthStreamableHTTPServer(securityList *security.SecurityList) http.Handler
- func (h *Handler) RegisterModel(schema, entity string, model interface{}) error
- func (h *Handler) RegisterModelWithRules(schema, entity string, model interface{}, rules modelregistry.ModelRules) error
- func (h *Handler) RegisterOAuth2(auth *security.DatabaseAuthenticator, cfg OAuth2RouteConfig)
- func (h *Handler) RegisterOAuth2Provider(auth *security.DatabaseAuthenticator, providerName string)
- func (h *Handler) SSEServer() http.Handler
- func (h *Handler) SetModelRules(schema, entity string, rules modelregistry.ModelRules) error
- func (h *Handler) StreamableHTTPMux(securityList *security.SecurityList) http.Handler
- func (h *Handler) StreamableHTTPServer() http.Handler
- type HookContext
- type HookFunc
- type HookRegistry
- func (r *HookRegistry) Clear(hookType HookType)
- func (r *HookRegistry) ClearAll()
- func (r *HookRegistry) Execute(hookType HookType, ctx *HookContext) error
- func (r *HookRegistry) HasHooks(hookType HookType) bool
- func (r *HookRegistry) Register(hookType HookType, hook HookFunc)
- func (r *HookRegistry) RegisterMultiple(hookTypes []HookType, hook HookFunc)
- type HookType
- type OAuth2RouteConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetModelPtr ¶
func GetTableName ¶
func NewSSEServer ¶
NewSSEServer returns an http.Handler that serves MCP over SSE. If Config.BasePath is set it is used directly; otherwise the base path is detected from each incoming request (by stripping the "/sse" or "/message" suffix).
h := resolvemcp.NewSSEServer(handler)
http.Handle("/api/mcp/", h)
func NewStreamableHTTPHandler ¶ added in v1.0.75
NewStreamableHTTPHandler returns an http.Handler that serves MCP over the streamable HTTP transport. Mount it at the desired path; that path becomes the MCP endpoint.
h := resolvemcp.NewStreamableHTTPHandler(handler)
http.Handle("/mcp", h)
engine.Any("/mcp", gin.WrapH(h))
func OAuth2CallbackHandler ¶ added in v1.0.78
func OAuth2CallbackHandler(auth *security.DatabaseAuthenticator, providerName, afterLoginRedirect string, cookieOpts ...security.SessionCookieOptions) http.HandlerFunc
OAuth2CallbackHandler returns an http.HandlerFunc that handles the OAuth2 provider callback: exchanges the authorization code for a session token, writes the session cookie, then either redirects to afterLoginRedirect or writes the LoginResponse as JSON.
Register it on any router:
mux.Handle("/auth/google/callback", resolvemcp.OAuth2CallbackHandler(auth, "google", "/dashboard"))
func OAuth2LoginHandler ¶ added in v1.0.78
func OAuth2LoginHandler(auth *security.DatabaseAuthenticator, providerName string) http.HandlerFunc
OAuth2LoginHandler returns an http.HandlerFunc that redirects the browser to the OAuth2 provider's authorization URL.
Register it on any router:
mux.Handle("/auth/google/login", resolvemcp.OAuth2LoginHandler(auth, "google"))
func RegisterSecurityHooks ¶ added in v1.0.74
func RegisterSecurityHooks(handler *Handler, securityList *security.SecurityList)
RegisterSecurityHooks wires the security package's access-control layer into the resolvemcp handler. Call it once after creating the handler, before registering models.
The following controls are applied:
- Per-entity operation rules (CanRead, CanCreate, CanUpdate, CanDelete, CanPublic*) stored via RegisterModelWithRules / SetModelRules.
- Row-level security: WHERE clause injected per user from the SecurityList provider.
- Column-level security: sensitive columns masked/hidden in read results.
- Audit logging after each read.
func SetupBunRouterRoutes ¶ added in v1.0.69
SetupBunRouterRoutes mounts the MCP HTTP/SSE endpoints on a bunrouter router using the base path from Config.BasePath.
Two routes are registered:
- GET {basePath}/sse — SSE connection endpoint
- POST {basePath}/message — JSON-RPC message endpoint
func SetupBunRouterStreamableHTTPRoutes ¶ added in v1.0.75
SetupBunRouterStreamableHTTPRoutes mounts the MCP streamable HTTP endpoint on a bunrouter router. The streamable HTTP transport uses a single endpoint (Config.BasePath).
func SetupMuxOAuth2Routes ¶ added in v1.0.78
func SetupMuxOAuth2Routes(muxRouter *mux.Router, auth *security.DatabaseAuthenticator, cfg OAuth2RouteConfig)
SetupMuxOAuth2Routes registers the OAuth2 login and callback routes on a Gorilla Mux router.
Example:
resolvemcp.SetupMuxOAuth2Routes(r, auth, resolvemcp.OAuth2RouteConfig{
ProviderName: "google", LoginPath: "/auth/google/login",
CallbackPath: "/auth/google/callback", AfterLoginRedirect: "/",
})
func SetupMuxRoutes ¶
SetupMuxRoutes mounts the MCP HTTP/SSE endpoints on the given Gorilla Mux router using the base path from Config.BasePath (falls back to "/mcp" if empty).
Two routes are registered:
- GET {basePath}/sse — SSE connection endpoint (client subscribes here)
- POST {basePath}/message — JSON-RPC message endpoint (client sends requests here)
To protect these routes with authentication, wrap the mux router or apply middleware before calling SetupMuxRoutes.
func SetupMuxRoutesWithAuth ¶ added in v1.0.78
func SetupMuxRoutesWithAuth(muxRouter *mux.Router, handler *Handler, securityList *security.SecurityList)
SetupMuxRoutesWithAuth mounts the MCP SSE endpoints on a Gorilla Mux router with required authentication middleware applied.
func SetupMuxStreamableHTTPRoutes ¶ added in v1.0.75
SetupMuxStreamableHTTPRoutes mounts the MCP streamable HTTP endpoint on the given Gorilla Mux router. The streamable HTTP transport uses a single endpoint (Config.BasePath) for all communication: POST for client→server messages, GET for server→client streaming.
Example:
resolvemcp.SetupMuxStreamableHTTPRoutes(r, handler) // mounts at Config.BasePath
func SetupMuxStreamableHTTPRoutesWithAuth ¶ added in v1.0.78
func SetupMuxStreamableHTTPRoutesWithAuth(muxRouter *mux.Router, handler *Handler, securityList *security.SecurityList)
SetupMuxStreamableHTTPRoutesWithAuth mounts the MCP streamable HTTP endpoint on a Gorilla Mux router with required authentication middleware applied.
Types ¶
type Config ¶ added in v1.0.70
type Config struct {
// BaseURL is the public-facing base URL of the server (e.g. "http://localhost:8080").
// It is sent to MCP clients during the SSE handshake so they know where to POST messages.
BaseURL string
// BasePath is the URL path prefix where the MCP endpoints are mounted (e.g. "/mcp").
// If empty, the path is detected from each incoming request automatically.
BasePath string
}
Config holds configuration for the resolvemcp handler.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler exposes registered database models as MCP tools and resources.
func NewHandler ¶
NewHandler creates a Handler with the given database, model registry, and config.
func NewHandlerWithBun ¶
NewHandlerWithBun creates a Handler backed by a Bun database connection.
func NewHandlerWithDB ¶
NewHandlerWithDB creates a Handler using an existing common.Database and a new registry.
func NewHandlerWithGORM ¶
NewHandlerWithGORM creates a Handler backed by a GORM database connection.
func (*Handler) AuthedSSEServer ¶ added in v1.0.78
func (h *Handler) AuthedSSEServer(securityList *security.SecurityList) http.Handler
AuthedSSEServer wraps SSEServer with required authentication middleware from pkg/security. The middleware reads the session cookie / Authorization header and populates the user context into the request context, making it available to BeforeHandle security hooks. Unauthenticated requests receive 401 before reaching any MCP tool.
func (*Handler) AuthedStreamableHTTPServer ¶ added in v1.0.78
func (h *Handler) AuthedStreamableHTTPServer(securityList *security.SecurityList) http.Handler
AuthedStreamableHTTPServer wraps StreamableHTTPServer with required authentication middleware.
func (*Handler) EnableOAuthServer ¶ added in v1.0.78
func (h *Handler) EnableOAuthServer(cfg security.OAuthServerConfig, auth *security.DatabaseAuthenticator)
EnableOAuthServer activates the MCP-standard OAuth2 authorization server on this Handler.
Pass a DatabaseAuthenticator to enable direct username/password login — the server acts as its own identity provider and renders a login form at /oauth/authorize. Pass nil to use only external providers registered via RegisterOAuth2Provider.
After calling this, HTTPHandler and StreamableHTTPMux serve the full set of RFC-compliant endpoints required by MCP clients alongside the MCP transport:
GET /.well-known/oauth-authorization-server RFC 8414 — auto-discovery POST /oauth/register RFC 7591 — dynamic client registration GET /oauth/authorize OAuth 2.1 + PKCE — start login POST /oauth/authorize Login form submission (password flow) POST /oauth/token Bearer token exchange + refresh GET /oauth/provider/callback External provider redirect target
func (*Handler) GetDatabase ¶
GetDatabase returns the underlying database.
func (*Handler) HTTPHandler ¶ added in v1.0.78
func (h *Handler) HTTPHandler(securityList *security.SecurityList) http.Handler
HTTPHandler returns a single http.Handler that serves:
- MCP OAuth2 authorization server endpoints (when EnableOAuthServer has been called)
- OAuth2 login + callback routes for every registered provider (legacy cookie flow)
- The MCP SSE transport wrapped with required authentication middleware
Example:
auth := security.NewGoogleAuthenticator(...)
handler.RegisterOAuth2(auth, cfg)
handler.EnableOAuthServer(security.OAuthServerConfig{Issuer: "https://api.example.com"})
security.RegisterSecurityHooks(handler, securityList)
http.ListenAndServe(":8080", handler.HTTPHandler(securityList))
func (*Handler) OptionalAuthSSEServer ¶ added in v1.0.78
func (h *Handler) OptionalAuthSSEServer(securityList *security.SecurityList) http.Handler
OptionalAuthSSEServer wraps SSEServer with optional authentication middleware. Unauthenticated requests continue as guest rather than returning 401. Use together with RegisterSecurityHooks and per-model CanPublicRead/Write rules to allow mixed public/private access.
func (*Handler) OptionalAuthStreamableHTTPServer ¶ added in v1.0.78
func (h *Handler) OptionalAuthStreamableHTTPServer(securityList *security.SecurityList) http.Handler
OptionalAuthStreamableHTTPServer wraps StreamableHTTPServer with optional authentication middleware.
func (*Handler) RegisterModel ¶
RegisterModel registers a model and immediately exposes it as MCP tools and a resource.
func (*Handler) RegisterModelWithRules ¶ added in v1.0.74
func (h *Handler) RegisterModelWithRules(schema, entity string, model interface{}, rules modelregistry.ModelRules) error
RegisterModelWithRules registers a model and sets per-entity operation rules (CanRead, CanCreate, CanUpdate, CanDelete, CanPublic*, SecurityDisabled). Requires RegisterSecurityHooks to have been called for the rules to be enforced.
func (*Handler) RegisterOAuth2 ¶ added in v1.0.78
func (h *Handler) RegisterOAuth2(auth *security.DatabaseAuthenticator, cfg OAuth2RouteConfig)
RegisterOAuth2 attaches an OAuth2 provider to the Handler. The login and callback HTTP routes are served by HTTPHandler / StreamableHTTPMux. Call this once per provider before serving requests.
Example:
auth := security.NewGoogleAuthenticator(clientID, secret, redirectURL, db)
handler.RegisterOAuth2(auth, resolvemcp.OAuth2RouteConfig{
ProviderName: "google",
LoginPath: "/auth/google/login",
CallbackPath: "/auth/google/callback",
AfterLoginRedirect: "/",
})
func (*Handler) RegisterOAuth2Provider ¶ added in v1.0.78
func (h *Handler) RegisterOAuth2Provider(auth *security.DatabaseAuthenticator, providerName string)
RegisterOAuth2Provider adds an external OAuth2 provider to the MCP OAuth2 authorization server. EnableOAuthServer must be called before this. The auth must have been configured with WithOAuth2(providerName, ...) for the given provider name.
func (*Handler) SSEServer ¶ added in v1.0.69
SSEServer returns an http.Handler that serves MCP over SSE. Config.BasePath must be set. Config.BaseURL is used when set; if empty it is detected automatically from each incoming request.
func (*Handler) SetModelRules ¶ added in v1.0.74
func (h *Handler) SetModelRules(schema, entity string, rules modelregistry.ModelRules) error
SetModelRules updates the operation rules for an already-registered model. Requires RegisterSecurityHooks to have been called for the rules to be enforced.
func (*Handler) StreamableHTTPMux ¶ added in v1.0.78
func (h *Handler) StreamableHTTPMux(securityList *security.SecurityList) http.Handler
StreamableHTTPMux returns a single http.Handler that serves:
- MCP OAuth2 authorization server endpoints (when EnableOAuthServer has been called)
- OAuth2 login + callback routes for every registered provider (legacy cookie flow)
- The MCP streamable HTTP transport wrapped with required authentication middleware
Example:
http.ListenAndServe(":8080", handler.StreamableHTTPMux(securityList))
func (*Handler) StreamableHTTPServer ¶ added in v1.0.75
StreamableHTTPServer returns an http.Handler that serves MCP over the streamable HTTP transport. Unlike SSE (which requires two endpoints), streamable HTTP uses a single endpoint for all client-server communication (POST for requests, GET for server-initiated messages). Mount the returned handler at the desired path; the path itself becomes the MCP endpoint.
type HookContext ¶
type HookContext struct {
Context context.Context
Handler *Handler
Schema string
Entity string
Model interface{}
Options common.RequestOptions
Operation string
ID string
Data interface{}
Result interface{}
Error error
Query common.SelectQuery
Abort bool
AbortMessage string
AbortCode int
Tx common.Database
}
HookContext contains all the data available to a hook
type HookRegistry ¶
type HookRegistry struct {
// contains filtered or unexported fields
}
HookRegistry manages all registered hooks
func NewHookRegistry ¶
func NewHookRegistry() *HookRegistry
func (*HookRegistry) Clear ¶
func (r *HookRegistry) Clear(hookType HookType)
func (*HookRegistry) ClearAll ¶
func (r *HookRegistry) ClearAll()
func (*HookRegistry) Execute ¶
func (r *HookRegistry) Execute(hookType HookType, ctx *HookContext) error
func (*HookRegistry) HasHooks ¶
func (r *HookRegistry) HasHooks(hookType HookType) bool
func (*HookRegistry) Register ¶
func (r *HookRegistry) Register(hookType HookType, hook HookFunc)
func (*HookRegistry) RegisterMultiple ¶
func (r *HookRegistry) RegisterMultiple(hookTypes []HookType, hook HookFunc)
type HookType ¶
type HookType string
HookType defines the type of hook to execute
const ( // BeforeHandle fires after model resolution, before operation dispatch. BeforeHandle HookType = "before_handle" BeforeRead HookType = "before_read" AfterRead HookType = "after_read" BeforeCreate HookType = "before_create" AfterCreate HookType = "after_create" BeforeUpdate HookType = "before_update" AfterUpdate HookType = "after_update" BeforeDelete HookType = "before_delete" AfterDelete HookType = "after_delete" )
type OAuth2RouteConfig ¶ added in v1.0.78
type OAuth2RouteConfig struct {
// ProviderName is the OAuth2 provider name as registered with WithOAuth2()
// (e.g. "google", "github", "microsoft").
ProviderName string
// LoginPath is the HTTP path that redirects the browser to the OAuth2 provider
// (e.g. "/auth/google/login").
LoginPath string
// CallbackPath is the HTTP path that the OAuth2 provider redirects back to
// (e.g. "/auth/google/callback"). Must match the RedirectURL in OAuth2Config.
CallbackPath string
// AfterLoginRedirect is the URL to redirect the browser to after a successful
// login. When empty the LoginResponse JSON is written directly to the response.
AfterLoginRedirect string
// CookieOptions customises the session cookie written on successful login.
// Defaults to HttpOnly, Secure, SameSite=Lax when nil.
CookieOptions *security.SessionCookieOptions
}
OAuth2RouteConfig configures the OAuth2 HTTP endpoints for a single provider.