mcpbroker

package
v0.0.26 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: Apache-2.0 Imports: 45 Imported by: 0

Documentation

Overview

Package mcpbroker implements the in-process, session-scoped MCP broker. Model-facing catalogues contain only neutral tool specifications; backend routing remains private to this adapter.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidCatalogue reports an invalid declaration, discovery result, or
	// model-visible tool-name collision.
	ErrInvalidCatalogue = errors.New("mcpbroker: invalid catalogue")
	// ErrProtectedRouteUnsupported reports the P08 boundary: OAuth routes are
	// declared by P07 but are not executable until protected-route custody lands.
	ErrProtectedRouteUnsupported = errors.New("mcpbroker: protected route unsupported")
)
View Source
var ErrAuthenticatedDiscovery = errors.New("mcpbroker: authenticated capability discovery failed")

ErrAuthenticatedDiscovery reports a provider-scoped capability discovery failure without exposing a provider key, broker credential, or upstream state.

View Source
var ErrWorkspaceEnrollmentUnsupported = errors.New("mcpbroker: workspace enrollment is not required")

ErrWorkspaceEnrollmentUnsupported reports that this attachment's Runtime has no owning Process or no configured protected ToolHive backend.

Functions

This section is empty.

Types

type Attachment

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

Attachment is a local handle to a logical broker session. Tools is an adapter-specific projection used by composition; the P06 lifecycle methods satisfy the neutral contract.

func (*Attachment) Abort

func (a *Attachment) Abort(ctx context.Context) error

Abort closes this attachment and conditionally rolls back only a still-private creation. A peer attachment publishes the logical session at reattachment, so aborting the creator can never invalidate an observed peer.

func (*Attachment) AuthorizationStatus

func (a *Attachment) AuthorizationStatus(ctx context.Context, authorization session.ExternalAuthorization) (session.AuthorizationStatus, error)

AuthorizationStatus reports the exact transaction's current lifecycle status.

func (*Attachment) BeginWorkspaceEnrollment

func (a *Attachment) BeginWorkspaceEnrollment(ctx context.Context) (contract.WorkspaceEnrollmentPresentation, error)

BeginWorkspaceEnrollment starts, or idempotently re-presents, the one bundle-wide pre-prompt ToolHive authorization transaction for every protected backend.

func (*Attachment) Binding

func (a *Attachment) Binding() session.ExternalBinding

Binding returns the opaque identity of this logical-session incarnation.

func (*Attachment) CancelAuthorization

func (a *Attachment) CancelAuthorization(ctx context.Context, authorization session.ExternalAuthorization) (contract.CancelOutcome, error)

CancelAuthorization idempotently settles only the exact pending transaction.

func (*Attachment) CancelWorkspaceEnrollment

CancelWorkspaceEnrollment cancels the exact pending bundle and clears its aggregate broker credential. No terminal outcome leaves partial authority.

func (*Attachment) Close

Close rejects new work through this attachment and joins work that was already registered through it. It does not cancel sibling attachments or logical state.

func (*Attachment) Commit

func (a *Attachment) Commit(ctx context.Context) error

Commit publishes this attachment's private creation. Reattached attachments have already published the logical session by observing it, so Commit is a harmless idempotent settlement for them.

func (*Attachment) FreezeAuthenticatedCatalogue

func (a *Attachment) FreezeAuthenticatedCatalogue(ctx context.Context, ref contract.WorkspaceEnrollmentRef, process *Process, brokerCredential oauth2.TokenSource, occupied []string) (contract.WorkspaceCatalogue, error)

FreezeAuthenticatedCatalogue stages the configured protected backends in their configured order and publishes one immutable attachment catalogue only after every backend has supplied valid live metadata. occupied is the complete model-visible name set outside this attachment catalogue (core/global tools). brokerCredential is opaque and is passed only through ToolHive's incoming identity middleware.

func (*Attachment) ObserveWorkspaceEnrollment

ObserveWorkspaceEnrollment reports the current bundle status. A granted transaction triggers authenticated discovery across the whole bundle and, only if every backend succeeds, publishes the frozen catalogue.

func (*Attachment) PresentAuthorization

func (a *Attachment) PresentAuthorization(ctx context.Context, authorization session.ExternalAuthorization) (string, error)

PresentAuthorization returns a live URL for the exact process-local transaction.

func (*Attachment) Tools

func (a *Attachment) Tools() []tool.Tool

Tools returns a copy of the attachment's current whole catalogue. Publication replaces the catalogue in one assignment, so callers cannot observe staged protected tools.

type AuthenticatedCapabilities

type AuthenticatedCapabilities struct {
	Backend string
	Tools   []ToolDefinition
}

AuthenticatedCapabilities is the neutral, copied result of discovering one protected backend. It deliberately contains no ToolHive capability value or authentication material.

type AuthorizedCaller

AuthorizedCaller is the protected-route execution seam. The token source is scoped to the exact logical session and route and retains refresh custody.

type Caller

Caller is the private execution seam used by the in-process transport. The opaque session incarnation and configured backend are passed separately from model-controlled arguments.

type Catalogue

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

Catalogue is an immutable compiled broker catalogue. Specs deliberately expose no backend route or execution metadata.

func Compile

func Compile(config mcpauthority.BrokerConfig, discovered []ToolDefinition, occupied []string) (*Catalogue, error)

Compile validates anonymous P07 declarations and neutral discovery results. occupied contains names already visible to the model; collisions are rejected before any session attachment is created.

func (*Catalogue) Specs

func (c *Catalogue) Specs() []tool.ToolSpec

Specs returns the stable model-facing catalogue in name order.

type HandlerBundle

type HandlerBundle struct {
	Authorization     http.Handler
	Token             http.Handler
	UpstreamCallback  http.Handler
	Discovery         http.Handler
	JWKS              http.Handler
	ProtectedResource http.Handler
	VMCP              http.Handler
	Callback          http.Handler
}

HandlerBundle is the fixed process-owned HTTP surface of an in-process broker. Command roots choose the listener, but the adapter owns the exact route set.

func (HandlerBundle) Empty

func (h HandlerBundle) Empty() bool

Empty reports whether the process exposes no HTTP surface.

func (HandlerBundle) Mount

func (h HandlerBundle) Mount(mux *http.ServeMux, callbackPath string) (err error)

Mount registers the complete fixed route set and the callback path selected by trusted composition. It rejects incomplete protected bundles and route collisions before mutating the mux.

type Option

type Option func(*Runtime)

Option configures process-owned OAuth custody without widening the broker contract.

func WithAuthorizedCaller

func WithAuthorizedCaller(caller AuthorizedCaller) Option

WithAuthorizedCaller installs the protected-route transport seam.

func WithBrokerHTTPClientForTest

func WithBrokerHTTPClientForTest(t interface{ Helper() }, client *http.Client) Option

WithBrokerHTTPClientForTest supplies a client that trusts the in-process TLS vMCP handler. It is honored only together with WithOAuthLoopbackForTest.

func WithOAuthLimits

func WithOAuthLimits(transactionTTL, exchangeTimeout time.Duration) Option

WithOAuthLimits overrides transaction and network bounds. Non-positive values retain defaults.

func WithOAuthLoopbackForTest

func WithOAuthLoopbackForTest(t interface{ Helper() }, roots *x509.CertPool) Option

WithOAuthLoopbackForTest enables only an in-process TLS test token endpoint. No production configuration surface can relax the hardened client's IP policy.

func WithOAuthSecretResolver

func WithOAuthSecretResolver(resolver func(context.Context, string) (string, error)) Option

WithOAuthSecretResolver resolves trusted secret references from P07 declarations.

type Process

type Process struct {
	Runtime  *Runtime
	Handlers HandlerBundle
	// contains filtered or unexported fields
}

Process is the single owner of a valid broker Runtime and all bundled ToolHive resources. ToolHive values never cross the neutral broker boundary.

func NewToolHiveProcess

func NewToolHiveProcess(ctx context.Context, config ToolHiveConfig, options ...Option) (*Process, error)

NewToolHiveProcess discovers anonymous upstreams, constructs one ordered ToolHive process, and returns only after the Runtime and every owned resource are valid. Any partial construction is rolled back in reverse dependency order.

func (*Process) Close

func (p *Process) Close() error

Close first cancels process-owned work, then drains the neutral Runtime (waiting for in-flight attachment operations to actually return, bounded by closeDrainTimeout), stops vMCP, and closes authserver. It is idempotent.

func (*Process) QueryAuthenticatedCapabilities

func (p *Process) QueryAuthenticatedCapabilities(ctx context.Context, credential oauth2.TokenSource, backend string) (AuthenticatedCapabilities, error)

QueryAuthenticatedCapabilities sends the opaque outer broker credential through ToolHive's incoming identity middleware before making one backend-scoped capability query. Mecatl never reads ToolHive's token-session claim or retrieves an upstream provider credential.

func (*Process) WorkspaceEnrollmentRequired

func (p *Process) WorkspaceEnrollmentRequired() bool

WorkspaceEnrollmentRequired reports whether at least one configured protected upstream has no trusted static tool declaration, so its complete tool catalogue can only be learned by authenticating first and then running live authenticated discovery (workspace enrollment). Composition uses this to decide whether to advertise the enrollment capability.

type Runtime

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

Runtime owns logical broker sessions and creates process-local attachments.

func New

func New(catalogue *Catalogue, caller Caller, options ...Option) (*Runtime, error)

New constructs an in-process broker. OAuth options are required only when the catalogue contains protected routes.

func (*Runtime) AttachSession

AttachSession creates or reattaches to logical state keyed by the canonical mecatl session ID. Each call returns an independently closeable local handle.

func (*Runtime) CallbackHandler

func (r *Runtime) CallbackHandler() http.Handler

CallbackHandler returns the process-owned, bounded one-time OAuth callback handler.

func (*Runtime) Close

func (r *Runtime) Close() error

Close releases all process-owned callbacks, transactions, grants and logical sessions. It cancels every in-flight attachment operation but does NOT wait for them to actually return — a bare Runtime (constructed via New/Compile, with no Process-owned resources beyond its own http.Client) has nothing an in-flight operation could race after Close returns. A Runtime bundled into a Process, which DOES tear down additional owned resources (vMCP/authserver) right after closing its Runtime, must drain first: see closeAndDrain.

func (*Runtime) DeleteSession

func (r *Runtime) DeleteSession(ctx context.Context, id session.SessionID) (contract.DeleteOutcome, error)

DeleteSession logically deletes one broker session and invalidates all handles to that incarnation. Reattachment later creates a fresh incarnation.

func (*Runtime) Handlers

func (r *Runtime) Handlers(callbackURL string) (HandlerBundle, string, error)

Handlers returns the fixed callback bundle and its exact mount path.

type SessionRef

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

SessionRef is an opaque reference to one in-process logical-session incarnation. SessionID is exposed for backend attribution; the incarnation remains private.

func (SessionRef) SessionID

func (r SessionRef) SessionID() session.SessionID

SessionID returns the canonical mecatl session identity without exposing its incarnation.

type StaticTool

type StaticTool struct {
	Name, Description string
	Schema            json.RawMessage
	ReadOnly          bool
}

StaticTool is one trusted protected tool declaration. Its schema is copied into the frozen model-facing catalogue; backend routing remains private.

type ToolDefinition

type ToolDefinition struct {
	Backend     string
	Name        string
	Description string
	Schema      json.RawMessage
	ReadOnly    bool
}

ToolDefinition is the neutral result of discovering one tool on a configured MCP route. Backend is matched to a P07 route declaration and is never copied into the model-facing ToolSpec.

type ToolHiveConfig

type ToolHiveConfig struct {
	CallbackURL string
	Profiles    []ToolHiveProfile
	Occupied    []string
	// AuthStorage backs the embedded auth server's pending-authorization,
	// token, grant, and DCR storage directly. Tests use this to inject a
	// fake/spy storage.Storage; composition (which cannot import the
	// vendored toolhive storage package — see
	// TestToolHiveImportsStayBehindApprovedAdapterLeaves) uses AuthRedisClient
	// instead. Precedence: AuthStorage wins if set, else AuthRedisClient
	// selects a Redis-backed store (under toolHiveAuthStoragePrefix), else
	// storage.NewMemoryStorage() — which does not survive a process restart,
	// so a pod bounce between a user starting and completing an OAuth
	// authorization loses the pending state (a genuine "pending authorization
	// not found" failure).
	AuthStorage storage.Storage
	// AuthRedisClient, when set (and AuthStorage is nil), backs the embedded
	// auth server with a Redis-backed storage.Storage sharing this managed
	// Redis instance with mecatl's own session store, under
	// toolHiveAuthStoragePrefix. The caller (composition) owns the client's
	// lifecycle — EmbeddedAuthServer.Close calls storage.Close, which closes
	// the client it was given, so no separate cleanup is needed beyond that.
	AuthRedisClient redis.UniversalClient
}

ToolHiveConfig is the immutable adapter-owned input to bundled process construction. Composition reduces the operator schema to this value before invoking the adapter.

type ToolHiveOAuth

type ToolHiveOAuth struct {
	Issuer                string
	AuthorizationEndpoint string
	TokenEndpoint         string
	ClientID              string
	ClientSecretEnv       string
	Scopes                []string
	RequestRefreshToken   bool
}

ToolHiveOAuth contains only values needed to construct ToolHive's upstream.

type ToolHiveProfile

type ToolHiveProfile struct {
	Name   string
	URL    string
	Auth   string
	OAuth  *ToolHiveOAuth
	Static []StaticTool
}

ToolHiveProfile is one configured Streamable HTTP upstream.

Jump to

Keyboard shortcuts

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