mcp

package
v0.37.0 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package mcp is part of the GoFastr framework. See https://github.com/DonaldMurillo/gofastr for documentation.

Package mcp implements a Model Context Protocol server for GoFastr.

It provides tool registration, JSON-RPC 2.0 message handling, and transports for stdio and HTTP/SSE.

Index

Constants

View Source
const (
	ErrMethodNotFound = -32601
	ErrInvalidParams  = -32602
	ErrInternalError  = -32603
)

JSON-RPC 2.0 standard error codes.

View Source
const AppResourceMimeType = "text/html;profile=mcp-app"

AppResourceMimeType is the MIME type an MCP App's UI resource is served with, per the MCP Apps extension (spec 2026-01-26). A spec-compliant host (Claude, ChatGPT via the Apps SDK) renders such a resource in a sandboxed iframe inside the conversation.

Variables

This section is empty.

Functions

func RequestFromContext

func RequestFromContext(ctx context.Context) (*http.Request, bool)

RequestFromContext returns the original inbound *http.Request stashed by the transport, if any. Tool handlers that re-dispatch through an HTTP router use it to copy the caller's auth onto the internal request so session/JWT middleware re-resolves the same user instead of demoting to anonymous.

func StreamSSE

func StreamSSE(w io.Writer, event, data string)

StreamSSE writes a single SSE event to the writer. It is the hardened entry point for tool-result streaming and treats both arguments as untrusted:

  • the event name is truncated at the first CR/LF/NUL so the caller can't terminate the "event:" field and inject a forged directive below it.
  • data is collapsed to a single line (CR/LF/NUL stripped) and any occurrence of a literal SSE directive marker (e.g. "event:", "id:", "retry:", "data:") inside the payload has its colon replaced with " -" so the bytes can no longer be mistaken for — or substring-matched as — an injected directive.

func WithRequest

func WithRequest(ctx context.Context, r *http.Request) context.Context

WithRequest stashes the original inbound *http.Request in ctx so tool handlers can recover the caller's transport-level auth (Cookie / Authorization headers). The HTTP transports call this automatically; it is exported so non-HTTP callers (and tests) can populate the same slot.

Types

type AppConfig added in v0.33.0

type AppConfig struct {
	// Tool half.
	Name        string         // tool name (also the resource's display name)
	Description string         // tool description
	InputSchema map[string]any // tool inputSchema
	Handler     ToolHandler    // tool handler

	// UI resource half.
	ResourceURI string // e.g. "ui://myapp/studio.html"
	HTML        string // the widget's single-file HTML (inline JS/CSS)
	MimeType    string // optional; defaults to AppResourceMimeType

	// Optional resource `_meta.ui` fields the host honors when sandboxing
	// the iframe.
	CSP         string         // Content-Security-Policy for the widget
	Permissions map[string]any // iframe permissions descriptor

	// ToolMeta merges extra keys into the tool's `_meta` (alongside the
	// auto-added ui.resourceUri linkage and the ChatGPT compat alias).
	ToolMeta map[string]any
}

AppConfig describes an MCP App: an interactive HTML widget plus the tool that launches it. RegisterApp wires both halves — a `ui://` resource carrying the HTML and a tool whose `_meta` links to it — so the model can call the tool and the host can render the widget.

type Content added in v0.33.0

type Content struct {
	Type     string            // "text" | "image" | "audio" | "resource"
	Text     string            // type=="text"
	Data     string            // type=="image"/"audio" — base64-encoded bytes
	MimeType string            // type=="image"/"audio"
	Resource *EmbeddedResource // type=="resource"
	Meta     map[string]any    // optional per-block _meta
}

Content is a single MCP content block in a tools/call result. It models the spec's content union (text, image, audio, embedded resource). A tool handler may return a Content, a []Content, or a ToolResult to emit rich blocks instead of the default JSON-marshaled text. Construct blocks with TextContent / ImageContent / AudioContent / ResourceContent.

func AudioContent added in v0.33.0

func AudioContent(data []byte, mimeType string) Content

AudioContent returns an audio content block; data is base64-encoded.

func ImageContent added in v0.33.0

func ImageContent(data []byte, mimeType string) Content

ImageContent returns an image content block; data is base64-encoded for the wire (e.g. ImageContent(pngBytes, "image/png")).

func ResourceContent added in v0.33.0

func ResourceContent(uri, mimeType, text string) Content

ResourceContent returns an embedded-resource content block carrying a text resource inline.

func TextContent added in v0.33.0

func TextContent(text string) Content

TextContent returns a text content block.

func (Content) MarshalJSON added in v0.33.0

func (c Content) MarshalJSON() ([]byte, error)

MarshalJSON emits exactly the fields the spec defines for the block's type, so an image block never carries a stray empty "text" and a text block never carries empty "data"/"mimeType".

type EmbeddedResource added in v0.33.0

type EmbeddedResource struct {
	URI      string `json:"uri"`
	MimeType string `json:"mimeType,omitempty"`
	Text     string `json:"text,omitempty"`
	Blob     string `json:"blob,omitempty"` // base64
}

EmbeddedResource is the payload of a type=="resource" content block: an inline copy of a resource (text or base64 blob) carried in a tool result.

type ImageResult added in v0.33.0

type ImageResult struct {
	Data     []byte
	MimeType string
}

ImageResult is a convenience tool result for the common "return a generated image" case: mcp.ImageResult{Data: pngBytes, MimeType: "image/png"}.

type RPCError

type RPCError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
}

RPCError represents a JSON-RPC 2.0 error object.

func (*RPCError) Error

func (e *RPCError) Error() string

Error implements the error interface for RPCError.

type Request

type Request struct {
	JSONRPC string          `json:"jsonrpc"`
	ID      any             `json:"id"`
	Method  string          `json:"method"`
	Params  json.RawMessage `json:"params,omitempty"`
}

Request represents a JSON-RPC 2.0 request.

type Resource added in v0.33.0

type Resource struct {
	URI         string         `json:"uri"`
	Name        string         `json:"name"`
	Description string         `json:"description,omitempty"`
	MimeType    string         `json:"mimeType,omitempty"`
	Meta        map[string]any `json:"_meta,omitempty"`
	// contains filtered or unexported fields
}

Resource is a registered MCP resource. MCP Apps serve their UI as a `ui://` resource (mimeType "text/html;profile=mcp-app"); resources are also useful for docs, schemas, and templates.

type ResourceContents added in v0.33.0

type ResourceContents struct {
	Text     string
	Blob     []byte
	MimeType string
}

ResourceContents is the payload a resource yields on resources/read. Set exactly one of Text (UTF-8) or Blob (arbitrary bytes, base64-encoded on the wire). MimeType, if set, overrides the resource's declared MimeType for this read.

type ResourceContentsFunc added in v0.33.0

type ResourceContentsFunc func(ctx context.Context) (ResourceContents, error)

ResourceContentsFunc lazily produces a resource's contents. It runs per resources/read, receiving the request context (auth/tenant enriched).

type ResourceOption added in v0.33.0

type ResourceOption func(*Resource)

ResourceOption customizes a resource at registration time.

func WithResourceDescription added in v0.33.0

func WithResourceDescription(desc string) ResourceOption

WithResourceDescription sets a human/agent-readable description.

func WithResourceGate added in v0.33.0

func WithResourceGate(gate func(ctx context.Context) error) ResourceOption

WithResourceGate auth-gates a resource's contents: the gate runs before resources/read invokes the contents func, receiving the read's context (auth/tenant enriched, carrying the inbound request). A non-nil error refuses the read. This is the resource-side analogue of mcp.Gated — use it to serve per-caller or sensitive data via a first-class gate instead of an inline check. Resource metadata (uri/name) still appears in resources/list; the gate protects the contents. battery/auth's auth.MCPUser() / auth.MCPRole(...) work as gates here too.

func WithResourceMeta added in v0.33.0

func WithResourceMeta(meta map[string]any) ResourceOption

WithResourceMeta attaches a `_meta` object to a resource, serialized verbatim in resources/list. MCP Apps ride csp/permissions here on the resource's `_meta.ui`.

type Response

type Response struct {
	JSONRPC string    `json:"jsonrpc"`
	ID      any       `json:"id"`
	Result  any       `json:"result,omitempty"`
	Error   *RPCError `json:"error,omitempty"`
}

Response represents a JSON-RPC 2.0 response.

type Server

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

Server is an MCP server with a tool registry.

func NewServer

func NewServer() *Server

NewServer creates a new MCP server with an empty tool registry.

func (*Server) CallTool

func (s *Server) CallTool(ctx context.Context, name string, params map[string]any) (any, error)

CallTool is the exported form of callTool: invokes a registered tool by name with the given params. Use this when calling MCP tools in-process (tests, server-side integrations) without going through the JSON-RPC transport layer.

func (*Server) HandleRequest

func (s *Server) HandleRequest(ctx context.Context, req Request) Response

HandleRequest routes a JSON-RPC 2.0 request to the correct handler and returns the appropriate response.

func (*Server) ListTools

func (s *Server) ListTools() []Tool

ListTools returns all registered tools whose call gate (if set) allows them. Tools owned by a disabled module are excluded. Handlers are nilled out for safety. This is the exported version of listTools.

func (*Server) RegisterApp added in v0.33.0

func (s *Server) RegisterApp(cfg AppConfig) error

RegisterApp registers an MCP App: the UI resource and the linking tool in one call. The tool's `_meta` gets `ui.resourceUri` (the standard linkage) and `openai/outputTemplate` (the ChatGPT Apps SDK compat alias), both pointing at ResourceURI. The resource carries `_meta.ui` (csp/permissions) when provided. Registering an App advertises the `resources` capability.

Returns an error on missing fields or a duplicate tool name / resource uri; on a duplicate it registers neither half.

func (*Server) RegisterResource added in v0.33.0

func (s *Server) RegisterResource(uri, name, mimeType string, contents ResourceContentsFunc, opts ...ResourceOption) error

RegisterResource adds a resource to the server. Registering at least one resource makes the server advertise the `resources` capability in initialize. Returns an error on empty uri/name, nil contents, or a duplicate uri.

Auth note: resources are NOT covered by the tool call gate (mcp.Gated / auth.MCPUser / auth.MCPRole gate tool handlers, not resources/read). A resource serving PUBLIC content (e.g. an MCP App's widget HTML) needs no gating. To serve per-caller or sensitive data, self-gate inside the contents func — it receives the auth/tenant-enriched request context, so it can inspect the caller and return an error for unauthorized reads.

func (*Server) RegisterTool

func (s *Server) RegisterTool(name, description string, inputSchema map[string]any, fn ToolHandler, opts ...ToolOption) error

RegisterTool adds a tool to the server's registry. Returns an error if a tool with the same name already exists.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles HTTP POST requests for MCP JSON-RPC calls. It reads a JSON-RPC request from the body and writes the response.

func (*Server) ServeSSE

func (s *Server) ServeSSE(path string) http.Handler

ServeSSE sets up an HTTP handler that supports Server-Sent Events for streaming responses. The POST endpoint at path handles JSON-RPC calls, and the GET endpoint streams responses via SSE.

func (*Server) ServeStdio

func (s *Server) ServeStdio(ctx context.Context, in io.Reader, out io.Writer) error

ServeStdio reads JSON-RPC requests from in line-by-line and writes responses to out. It blocks until in returns EOF or ctx is cancelled.

func (*Server) ServerInfo added in v0.10.0

func (s *Server) ServerInfo() (name, version string)

ServerInfo returns the name/version advertised in the MCP initialize handshake. Used by well-known discovery artifacts (e.g. an MCP server card) that mirror the handshake's serverInfo.

func (*Server) SetCallGate added in v0.17.0

func (s *Server) SetCallGate(fn func(toolName string) error)

SetCallGate installs a gate checked in callTool right after the tool is resolved. A non-nil error blocks the handler and returns a JSON-RPC error result. Framework code uses it to gate tools owned by a disabled module. Pass nil to clear.

func (*Server) SetRegisterHook added in v0.17.0

func (s *Server) SetRegisterHook(fn func(toolName string))

SetRegisterHook installs a callback fired for every RegisterTool call. Framework code uses it to attribute tools to the module whose Init registered them. Pass nil to clear.

func (*Server) SetServerInfo added in v0.10.0

func (s *Server) SetServerInfo(name, version string)

SetServerInfo overrides the name/version advertised in the MCP `initialize` handshake (serverInfo). Call before serving requests.

func (*Server) SetServerName added in v0.10.0

func (s *Server) SetServerName(name string)

SetServerName overrides just the serverInfo name advertised in the MCP initialize handshake, leaving the version at its default. Used by hosts that know their app name but not a separate MCP server version.

type Tool

type Tool struct {
	Name         string         `json:"name"`
	Description  string         `json:"description"`
	InputSchema  map[string]any `json:"inputSchema"`
	OutputSchema map[string]any `json:"outputSchema,omitempty"`
	// Meta is serialized verbatim as the tool's `_meta` in tools/list. MCP
	// Apps use it to link a tool to its UI resource, e.g.
	// {"ui": {"resourceUri": "ui://app/widget.html"}} (and the ChatGPT
	// compat alias "openai/outputTemplate").
	Meta    map[string]any `json:"_meta,omitempty"`
	Handler ToolHandler    `json:"-"`
}

Tool represents a registered MCP tool with its metadata and handler.

type ToolHandler

type ToolHandler func(ctx context.Context, params map[string]any) (any, error)

ToolHandler is the function signature for MCP tool handlers. It receives a context (carrying auth/tenant info) and a map of parameters.

The return value is normalized into the tools/call response by result type:

  • mcp.ToolResult — explicit content blocks and/or structuredContent
  • mcp.ImageResult — a single base64 image block (renders inline)
  • mcp.Content / []mcp.Content — one or more content blocks (build with TextContent / ImageContent / AudioContent / ResourceContent)
  • string — a single text block
  • anything else — JSON-marshaled into a text block (the legacy default)

A non-nil error is returned as a JSON-RPC error; report an in-band tool failure with mcp.ToolResult{IsError: true} instead.

func Gated added in v0.25.0

func Gated(gate func(ctx context.Context) error, h ToolHandler) ToolHandler

Gated wraps a ToolHandler with a precondition that runs before the handler on every call. Use it to auth-gate custom tools: the gate receives the tool call's context, which carries the inbound HTTP request (RequestFromContext) and whatever identity the router's middleware chain resolved onto it — so a gate can require a signed-in user, a role, or any other per-caller policy. A refused call returns the gate's error as the JSON-RPC tool error; the handler never runs.

The entity CRUD tools don't need this — they re-dispatch through the router and inherit HTTP auth wholesale. Gated exists for DIRECT handlers: app.MCP.RegisterTool(...) registrations and entity.Endpoint.MCPHandler twins, which bypass the route middleware.

battery/auth ships ready-made gates: auth.MCPUser() and auth.MCPRole("admin").

type ToolOption added in v0.33.0

type ToolOption func(*Tool)

ToolOption customizes a tool at registration time.

func WithOutputSchema added in v0.33.0

func WithOutputSchema(schema map[string]any) ToolOption

WithOutputSchema declares the JSON Schema for a tool's structuredContent.

func WithToolMeta added in v0.33.0

func WithToolMeta(meta map[string]any) ToolOption

WithToolMeta attaches a `_meta` object to a tool, serialized verbatim in tools/list. Use it for the MCP Apps UI linkage. Symmetric with WithResourceMeta on the resource side.

type ToolResult added in v0.33.0

type ToolResult struct {
	Content    []Content
	Structured any
	IsError    bool
}

ToolResult is a rich tool result a handler can return for full control over the tools/call response: explicit content blocks and/or a structured payload (structuredContent, machine-readable and validated against the tool's outputSchema). When Content is empty but Structured is set, core/mcp mirrors the structured value into a text block so non-structured clients still see output.

Jump to

Keyboard shortcuts

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