tinymcp

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: May 29, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package tinymcp provides a lightweight wrapper around the official Model Context Protocol Go SDK. It reduces boilerplate for building MCP servers (stdio, streamable HTTP, or legacy SSE) that AI clients can discover and call.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrNilServer          = errors.New("tinymcp: nil server")
	ErrNilTool            = errors.New("tinymcp: nil tool")
	ErrNilHandler         = errors.New("tinymcp: nil handler")
	ErrRegistrationFailed = errors.New("tinymcp: registration failed")
)

Sentinel errors for programmatic handling at registration time.

Functions

func AssistantPromptMessage added in v1.1.0

func AssistantPromptMessage(text string) *mcp.PromptMessage

AssistantPromptMessage returns an assistant-role prompt message with text content.

func BearerTokenAuth added in v1.1.3

func BearerTokenAuth(token string, h http.Handler) http.Handler

BearerTokenAuth requires Authorization: Bearer <token> when token is non-empty. When token is empty, h is served without auth. Unauthenticated requests receive 401 with WWW-Authenticate (preferred for Smithery and MCP gateways).

Example
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/kioie/tiny-go-mcp-server/tinymcp"
)

func main() {
	inner := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
		_, _ = w.Write([]byte("ok"))
	})
	h := tinymcp.BearerTokenAuth("secret", inner)

	req := httptest.NewRequest(http.MethodGet, "/", nil)
	req.Header.Set("Authorization", "Bearer secret")
	rec := httptest.NewRecorder()
	h.ServeHTTP(rec, req)
	fmt.Println(rec.Body.String())
}
Output:
ok

func DisableLocalhostProtectionFromEnv added in v1.1.3

func DisableLocalhostProtectionFromEnv() bool

DisableLocalhostProtectionFromEnv reports whether TINY_GO_MCP_DISABLE_LOCALHOST_PROTECTION=1. Use only for local ngrok/tunnel testing on loopback listeners.

func ListenAndServeHTTP added in v1.1.3

func ListenAndServeHTTP(addr string, handler http.Handler) error

ListenAndServeHTTP starts addr with handler using timeouts suited to MCP HTTP (SSE-friendly). It shuts down gracefully on SIGINT or SIGTERM (for container deploys).

func ListenAndServeHTTPContext added in v1.2.0

func ListenAndServeHTTPContext(ctx context.Context, addr string, handler http.Handler) error

ListenAndServeHTTPContext serves until ctx is canceled, then drains active connections.

func MustRegisterPrompt added in v1.2.0

func MustRegisterPrompt(s *TinyServer, name, description string, arguments []*mcp.PromptArgument, handler mcp.PromptHandler)

MustRegisterPrompt is like RegisterPrompt but panics on error. Safe at process startup.

func MustRegisterResource added in v1.2.0

func MustRegisterResource(s *TinyServer, uri, name, description, mimeType string, handler mcp.ResourceHandler)

MustRegisterResource is like RegisterResource but panics on error. Safe at process startup.

func MustRegisterResourceTemplate added in v1.2.0

func MustRegisterResourceTemplate(s *TinyServer, uriTemplate, name, description, mimeType string, handler mcp.ResourceHandler)

MustRegisterResourceTemplate is like RegisterResourceTemplate but panics on error.

func MustRegisterTextResource added in v1.2.0

func MustRegisterTextResource(s *TinyServer, uri, name, description, mimeType, text string)

MustRegisterTextResource is like RegisterTextResource but panics on error.

func MustRegisterTool added in v1.2.0

func MustRegisterTool[In, Out any](s *TinyServer, name, description string, handler mcp.ToolHandlerFor[In, Out])

MustRegisterTool is like RegisterTool but panics on error. Safe at process startup.

func MustRegisterToolDef added in v1.2.0

func MustRegisterToolDef[In, Out any](s *TinyServer, tool *mcp.Tool, handler mcp.ToolHandlerFor[In, Out])

MustRegisterToolDef is like RegisterToolDef but panics on error. Safe at process startup.

func PromptResult added in v1.1.0

func PromptResult(description string, messages ...*mcp.PromptMessage) *mcp.GetPromptResult

PromptResult builds a GetPromptResult from prompt messages. With no messages, returns an empty array (not JSON null).

func RegisterPrompt added in v1.1.0

func RegisterPrompt(s *TinyServer, name, description string, arguments []*mcp.PromptArgument, handler mcp.PromptHandler) error

RegisterPrompt adds a prompt template. arguments may be nil for prompts with no parameters.

func RegisterResource added in v1.1.0

func RegisterResource(s *TinyServer, uri, name, description, mimeType string, handler mcp.ResourceHandler) error

RegisterResource adds a resource with a fixed URI. uri must be absolute (e.g. file:///docs/readme).

func RegisterResourceTemplate added in v1.1.0

func RegisterResourceTemplate(s *TinyServer, uriTemplate, name, description, mimeType string, handler mcp.ResourceHandler) error

RegisterResourceTemplate adds a resource matched by URI template (e.g. file:///docs/{path}).

func RegisterTextResource added in v1.1.0

func RegisterTextResource(s *TinyServer, uri, name, description, mimeType, text string) error

RegisterTextResource registers a static text resource at uri.

func RegisterTool

func RegisterTool[In, Out any](s *TinyServer, name, description string, handler mcp.ToolHandlerFor[In, Out]) error

RegisterTool registers a tool on s with automatic JSON Schema inference from the handler's input struct (use json and jsonschema struct tags). The handler must match mcp.ToolHandlerFor[In, Out] — typically return TextResult for text tools. Invalid tool definitions surface as returned errors instead of panicking.

Example
package main

import (
	"context"
	"log"

	"github.com/kioie/tiny-go-mcp-server/tinymcp"
	"github.com/modelcontextprotocol/go-sdk/mcp"
)

type greetArgs struct {
	Name string `json:"name" jsonschema:"Person to greet"`
}

func main() {
	s := tinymcp.NewServer("demo", "1.0.0")
	err := tinymcp.RegisterTool(s, "greet", "Greet someone by name", func(_ context.Context, _ *mcp.CallToolRequest, args greetArgs) (*mcp.CallToolResult, any, error) {
		return tinymcp.TextResult("Hello, " + args.Name), nil, nil
	})
	if err != nil {
		log.Fatal(err)
	}
}

func RegisterToolDef added in v1.1.3

func RegisterToolDef[In, Out any](s *TinyServer, tool *mcp.Tool, handler mcp.ToolHandlerFor[In, Out]) error

RegisterToolDef registers a tool with full go-sdk Tool metadata (annotations, etc.). Invalid tool definitions surface as returned errors instead of panicking.

func RequiredPromptArgument added in v1.1.3

func RequiredPromptArgument(name string) error

RequiredPromptArgument returns InvalidParams for a missing required prompt argument.

func SSEHandler added in v1.1.0

func SSEHandler(s *TinyServer, opts *SSEOptions) (http.Handler, error)

SSEHandler returns an http.Handler for legacy SSE MCP clients (2024-11-05 transport).

func StreamableHTTPHandler added in v1.1.0

func StreamableHTTPHandler(s *TinyServer, opts *HTTPOptions) (http.Handler, error)

StreamableHTTPHandler returns an http.Handler for streamable HTTP MCP clients (POST JSON-RPC; responses as JSON or SSE). Wrap with auth/CORS middleware as needed.

Example
package main

import (
	"context"
	"log"
	"net/http"

	"github.com/kioie/tiny-go-mcp-server/tinymcp"
	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
	s := tinymcp.NewServer("demo", "1.0.0")
	if err := tinymcp.RegisterTool(s, "ping", "Echo ping", func(_ context.Context, _ *mcp.CallToolRequest, _ struct{}) (*mcp.CallToolResult, any, error) {
		return tinymcp.TextResult("pong"), nil, nil
	}); err != nil {
		log.Fatal(err)
	}

	handler, err := tinymcp.StreamableHTTPHandler(s, &tinymcp.HTTPOptions{Stateless: true})
	if err != nil {
		log.Fatal(err)
	}
	handler = tinymcp.WithCrossOriginProtection(handler)
	handler = tinymcp.BearerTokenAuth("secret", handler)

	http.Handle("/mcp", handler)
	// Listen with tinymcp.ListenAndServeHTTP or your own http.Server + TLS.
}

func TextResource added in v1.1.0

func TextResource(uri, mimeType, text string) *mcp.ReadResourceResult

TextResource builds a ReadResourceResult with a single text body.

func TextResourceContents added in v1.1.0

func TextResourceContents(uri, mimeType, text string) *mcp.ResourceContents

TextResourceContents builds a text ResourceContents block for ReadResourceResult.

func TextResult

func TextResult(text string) *mcp.CallToolResult

TextResult builds a successful CallToolResult with a single text content block. Use this in tool handlers so LLM clients receive consistent, readable output.

Example
package main

import (
	"fmt"

	"github.com/kioie/tiny-go-mcp-server/tinymcp"
	"github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
	r := tinymcp.TextResult("hello")
	tc := r.Content[0].(*mcp.TextContent)
	fmt.Println(tc.Text)
}
Output:
hello

func UserPromptMessage added in v1.1.0

func UserPromptMessage(text string) *mcp.PromptMessage

UserPromptMessage returns a user-role prompt message with text content.

func WithCrossOriginProtection added in v1.1.3

func WithCrossOriginProtection(h http.Handler) http.Handler

WithCrossOriginProtection wraps h with Go's cross-origin CSRF protection for browser MCP clients. Server-to-server clients without Origin/Sec-Fetch-Site headers are unaffected.

Types

type HTTPOptions added in v1.1.0

type HTTPOptions struct {
	// Stateless uses a fresh session per request (no Mcp-Session-Id). Simpler for
	// stateless gateways; server-initiated requests are not supported.
	Stateless bool
	// JSONResponse returns application/json instead of text/event-stream for POST responses.
	JSONResponse bool
	// SessionTimeout closes idle sessions after this duration (zero = never).
	SessionTimeout time.Duration
	// DisableLocalhostProtection turns off DNS rebinding checks for localhost clients.
	// Only set when you understand the security tradeoff.
	DisableLocalhostProtection bool
	// Middleware wraps the MCP handler (first entry is innermost). Use for logging,
	// rate limits, etc. Apply auth/CORS outside via StreamableHTTPHandler return value
	// or additional wrapping on your mux.
	Middleware []func(http.Handler) http.Handler
}

HTTPOptions configures streamable HTTP transport (current MCP spec: POST + SSE).

func (*HTTPOptions) WithMiddleware added in v1.2.0

func (o *HTTPOptions) WithMiddleware(mw ...func(http.Handler) http.Handler) *HTTPOptions

WithMiddleware appends middleware wrappers to opts and returns opts for chaining.

type SSEOptions added in v1.1.0

type SSEOptions struct {
	// DisableLocalhostProtection turns off DNS rebinding checks for localhost clients.
	DisableLocalhostProtection bool
}

SSEOptions configures legacy SSE transport (MCP spec 2024-11-05).

type ServerOption added in v1.1.3

type ServerOption func(*mcp.ServerOptions)

ServerOption configures optional mcp.ServerOptions passed to the underlying SDK.

func WithInstructions added in v1.1.3

func WithInstructions(instructions string) ServerOption

WithInstructions sets client-facing server instructions in the initialize result.

func WithLogger added in v1.1.3

func WithLogger(logger *slog.Logger) ServerOption

WithLogger enables structured logging of server activity via the go-sdk.

func WithSDKOptions added in v1.1.3

func WithSDKOptions(options *mcp.ServerOptions) ServerOption

WithSDKOptions applies a full *mcp.ServerOptions value. Later options override overlapping fields set by earlier ones.

func WithSchemaCache added in v1.1.3

func WithSchemaCache(cache *mcp.SchemaCache) ServerOption

WithSchemaCache enables JSON schema caching (useful for stateless HTTP handlers).

type TinyServer

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

TinyServer wraps the official MCP Server with a simplified API for registering tools, resources, prompts, and starting transports.

func NewServer

func NewServer(name, version string, opts ...ServerOption) *TinyServer

NewServer creates a TinyServer identified by name and version for connected clients. Optional server configuration uses functional options or NewServerWithOptions.

func NewServerWithOptions added in v1.1.3

func NewServerWithOptions(name, version string, options *mcp.ServerOptions) *TinyServer

NewServerWithOptions creates a TinyServer with explicit go-sdk server options. Pass nil for SDK defaults (same as NewServer without options).

func (*TinyServer) RawServer

func (s *TinyServer) RawServer() *mcp.Server

RawServer returns the underlying *mcp.Server for advanced customization.

func (*TinyServer) Start

func (s *TinyServer) Start() error

Start runs the server over stdin/stdout (stdio), the standard transport for local AI clients.

func (*TinyServer) StartHTTP added in v1.1.0

func (s *TinyServer) StartHTTP(addr string, opts *HTTPOptions) error

StartHTTP listens on addr and serves streamable HTTP MCP until the server stops or errors.

func (*TinyServer) StartHTTPContext added in v1.2.0

func (s *TinyServer) StartHTTPContext(ctx context.Context, addr string, opts *HTTPOptions) error

StartHTTPContext serves streamable HTTP until ctx is canceled.

func (*TinyServer) StartSSE added in v1.1.0

func (s *TinyServer) StartSSE(addr string, opts *SSEOptions) error

StartSSE listens on addr and serves legacy SSE MCP until the server stops or errors.

func (*TinyServer) StartSSEContext added in v1.2.0

func (s *TinyServer) StartSSEContext(ctx context.Context, addr string, opts *SSEOptions) error

StartSSEContext serves legacy SSE until ctx is canceled.

Jump to

Keyboard shortcuts

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