xmcp

package
v0.0.0-...-d412f43 Latest Latest
Warning

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

Go to latest
Published: May 6, 2026 License: AGPL-3.0 Imports: 32 Imported by: 0

Documentation

Overview

Package xmcp implements the experimental Remote MCP Server runtime endpoint at /x/mcp/{remoteMcpServerId}. It is a temporary path used to prove out the Remote MCP Server proxy plumbing; once the MCP Frontend work lands, Remote MCP Server runtime handling will move under /mcp/... and use slug-based routing.

This package owns the HTTP lifecycle (routing, auth, DB load, header decryption) and delegates the actual forwarding work to github.com/speakeasy-api/gram/server/internal/remotemcp/proxy.

Index

Constants

View Source
const RuntimePath = "/x/mcp/{remoteMcpServerId}"

RuntimePath is the experimental runtime path served by this package.

Variables

This section is empty.

Functions

func Attach

func Attach(mux goahttp.Muxer, service *Service, mcpService *mcp.Service, metadataService *mcpmetadata.Service)

Attach registers the experimental Remote MCP Server runtime handler for all supported HTTP methods. DELETE, GET, and POST are required by the MCP Streamable HTTP transport (see spec § Session Management for DELETE and § Listening for Messages from the Server for GET).

Attach also registers /x/mcp aliases for the install page and OAuth .well-known metadata routes, delegating to the existing mcp and mcpmetadata service handlers so the experimental endpoint has parity with /mcp.

Types

type Service

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

Service owns dependencies for the Remote MCP Server runtime endpoint.

func NewService

func NewService(
	logger *slog.Logger,
	tracerProvider trace.TracerProvider,
	meterProvider metric.MeterProvider,
	db *pgxpool.Pool,
	sessionManager *sessions.Manager,
	enc *encryption.Client,
	authzEngine *authz.Engine,
	guardianPolicy *guardian.Policy,
	billingRepo billing.Repository,
	billingTracker billing.Tracker,
) *Service

NewService constructs a Service with its full dependency graph wired up.

func (*Service) ServeMCP

func (s *Service) ServeMCP(w http.ResponseWriter, r *http.Request) error

ServeMCP handles DELETE, GET, and POST on /x/mcp/{remoteMcpServerId}. It authenticates the caller with a Gram API key, loads the configured Remote MCP Server, and delegates the actual forwarding work to the remotemcp/proxy package.

type ToolUsageLimitsInterceptor

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

ToolUsageLimitsInterceptor enforces the free-tier hard cap on tools/call invocations by consulting the billing repository's cached period usage. It is a proxy.ToolsCallRequestInterceptor: it runs after the generic user-request chain and before the request is forwarded upstream. Non-free tiers and orgs with an active subscription skip the check.

The interceptor intentionally fails open when cached usage is unavailable (the billing cache should always be warm, but a transient miss must not take down tool invocation). Failures are logged with the originating org ID so operators can spot them in dashboards.

func NewToolUsageLimitsInterceptor

func NewToolUsageLimitsInterceptor(billingRepo billing.Repository, logger *slog.Logger) *ToolUsageLimitsInterceptor

NewToolUsageLimitsInterceptor constructs an interceptor bound to the given billing repository. The same instance can be reused across requests.

func (*ToolUsageLimitsInterceptor) InterceptToolsCallRequest

func (i *ToolUsageLimitsInterceptor) InterceptToolsCallRequest(ctx context.Context, _ *proxy.ToolsCallRequest) error

InterceptToolsCallRequest implements proxy.ToolsCallRequestInterceptor. It reads the organization and account type from the request's auth context, consults cached billing usage, and returns a forbidden error when the org has exceeded its hard cap.

func (*ToolUsageLimitsInterceptor) Name

Name implements proxy.ToolsCallRequestInterceptor.

type ToolUsageTrackingInterceptor

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

ToolUsageTrackingInterceptor emits a billing.ToolCallUsageEvent for each tools/call response so Remote MCP Server invocations feed the same Polar meter that gates free-tier usage on the existing /mcp endpoint. It is a proxy.ToolsCallResponseInterceptor: it runs after the generic proxy.RemoteMessageInterceptor chain has accepted the response and before the payload is relayed to the user.

Tracking is fire-and-forget: events are emitted in a goroutine bound to a context derived via context.WithoutCancel so the call completes even if the inbound request context cancels mid-relay. Missing auth context is treated as a no-op and logged so operators can spot misconfiguration without taking down tool invocation.

func NewToolUsageTrackingInterceptor

func NewToolUsageTrackingInterceptor(tracker billing.Tracker, logger *slog.Logger) *ToolUsageTrackingInterceptor

NewToolUsageTrackingInterceptor constructs an interceptor bound to the given billing tracker. The same instance can be reused across requests.

func (*ToolUsageTrackingInterceptor) InterceptToolsCallResponse

func (i *ToolUsageTrackingInterceptor) InterceptToolsCallResponse(ctx context.Context, call *proxy.ToolsCallResponse) error

InterceptToolsCallResponse implements proxy.ToolsCallResponseInterceptor. It emits a billing event for every observed tools/call response — paid tiers included — so Polar metering matches the existing /mcp surface. Always returns nil: tracking is best-effort and must not block the response from reaching the user.

func (*ToolUsageTrackingInterceptor) Name

Name implements proxy.ToolsCallResponseInterceptor.

Jump to

Keyboard shortcuts

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