mcpruntime

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jan 12, 2026 License: MIT Imports: 19 Imported by: 0

README

MCP Runtime

Build Status Lint Status Go Report Card Docs Visualization License

A library-first runtime for building MCP servers with interchangeable execution modes.

Overview

mcpruntime wraps the official MCP Go SDK to provide a unified API where tools, prompts, and resources are defined once and can be invoked either:

  • Library mode: Direct in-process function calls without JSON-RPC overhead
  • Server mode: Standard MCP transports (stdio, HTTP, SSE)

Installation

go get github.com/grokify/mcpruntime

Quick Start

Library Mode Example

Use tools directly in your application without MCP transport overhead:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/grokify/mcpruntime"
    "github.com/modelcontextprotocol/go-sdk/mcp"
)

type AddInput struct {
    A int `json:"a"`
    B int `json:"b"`
}

type AddOutput struct {
    Sum int `json:"sum"`
}

func main() {
    rt := mcpruntime.New(&mcp.Implementation{
        Name:    "calculator",
        Version: "v1.0.0",
    }, nil)

    mcpruntime.AddTool(rt, &mcp.Tool{
        Name:        "add",
        Description: "Add two numbers",
    }, func(ctx context.Context, req *mcp.CallToolRequest, in AddInput) (*mcp.CallToolResult, AddOutput, error) {
        return nil, AddOutput{Sum: in.A + in.B}, nil
    })

    // Call tool directly - no JSON-RPC, no transport
    result, err := rt.CallTool(context.Background(), "add", map[string]any{"a": 1, "b": 2})
    if err != nil {
        log.Fatal(err)
    }

    text := result.Content[0].(*mcp.TextContent).Text
    fmt.Println(text) // Output: {"sum":3}
}
Server Mode Example (stdio)

Expose the same tools as an MCP server for Claude Desktop or other MCP clients:

package main

import (
    "context"
    "log"

    "github.com/grokify/mcpruntime"
    "github.com/modelcontextprotocol/go-sdk/mcp"
)

type AddInput struct {
    A int `json:"a"`
    B int `json:"b"`
}

type AddOutput struct {
    Sum int `json:"sum"`
}

func main() {
    rt := mcpruntime.New(&mcp.Implementation{
        Name:    "calculator",
        Version: "v1.0.0",
    }, nil)

    mcpruntime.AddTool(rt, &mcp.Tool{
        Name:        "add",
        Description: "Add two numbers",
    }, func(ctx context.Context, req *mcp.CallToolRequest, in AddInput) (*mcp.CallToolResult, AddOutput, error) {
        return nil, AddOutput{Sum: in.A + in.B}, nil
    })

    // Run as MCP server over stdio
    if err := rt.ServeStdio(context.Background()); err != nil {
        log.Fatal(err)
    }
}
Server Mode Example (HTTP)

Expose tools over HTTP with SSE for server-to-client messages:

package main

import (
    "log"
    "net/http"

    "github.com/grokify/mcpruntime"
    "github.com/modelcontextprotocol/go-sdk/mcp"
)

func main() {
    rt := mcpruntime.New(&mcp.Implementation{
        Name:    "calculator",
        Version: "v1.0.0",
    }, nil)

    // Register tools...

    http.Handle("/mcp", rt.StreamableHTTPHandler(nil))
    log.Println("MCP server listening on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Design Philosophy

MCP (Model Context Protocol) is fundamentally a client-server protocol based on JSON-RPC. However, many use cases benefit from invoking MCP capabilities directly in-process:

  • Unit testing without mocking transports
  • Embedding agent capabilities in applications
  • Building local pipelines
  • Serverless runtimes

mcpruntime treats MCP as an "edge protocol" while providing a library-first internal API. Tools registered with mcpruntime use the exact same handler signatures as the MCP SDK, ensuring behavior is identical regardless of execution mode.

Key Features

Same Handlers, Two Modes

Tools, prompts, and resources are defined once using MCP SDK types:

// Register tool
mcpruntime.AddTool(rt, &mcp.Tool{Name: "calculate"}, handler)

// Library mode
result, err := rt.CallTool(ctx, "calculate", args)

// Server mode
rt.ServeStdio(ctx)
Full MCP SDK Compatibility
  • Uses mcp.Tool, mcp.Prompt, mcp.Resource types directly
  • Typed handlers with automatic schema inference via AddTool[In, Out]
  • All MCP transports supported (stdio, HTTP, SSE)
Transport Adapters
// Stdio (subprocess)
rt.ServeStdio(ctx)

// HTTP/SSE
http.Handle("/mcp", rt.StreamableHTTPHandler(nil))

// In-memory (testing)
_, clientSession, _ := rt.InMemorySession(ctx)

Feature Comparison: Library vs Server Mode

Feature Library Mode Server Mode Notes
Tools Yes Yes Full parity
Prompts Yes Yes Full parity
Static Resources Yes Yes Full parity
Resource Templates No Yes See below
JSON-RPC overhead None Yes Library mode is faster
MCP client required No Yes Library mode is standalone
Static vs Dynamic Resource Templates

Static resources have fixed URIs and work identically in both modes:

rt.AddResource(&mcp.Resource{
    URI:  "config://app/settings",
    Name: "settings",
}, handler)

// Library mode
rt.ReadResource(ctx, "config://app/settings")

// Server mode - same handler, MCP protocol

Dynamic resource templates use RFC 6570 URI Template syntax for pattern matching:

rt.AddResourceTemplate(&mcp.ResourceTemplate{
    URITemplate: "file:///{+path}",  // {+path} can contain /
}, handler)

// Matches: file:///docs/readme.md, file:///src/main.go, etc.

Resource templates are registered with the MCP server and work in server mode. Library-mode dispatch (ReadResource) currently supports exact URI matches only. For template matching in library mode, use MCPServer() directly.

Important: The URI scheme (e.g., file:///) is just an identifier—it doesn't mean the resource is on the filesystem. Your handler determines what content is returned:

// This "file:///" resource returns computed content, not filesystem data
rt.AddResourceTemplate(&mcp.ResourceTemplate{
    URITemplate: "file:///{+path}",
}, func(ctx context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
    // You decide: read from disk, database, return hardcoded data, etc.
    return &mcp.ReadResourceResult{
        Contents: []*mcp.ResourceContents{{
            URI:  req.Params.URI,
            Text: "This content is computed, not from a file",
        }},
    }, nil
})

MCP Feature Adoption

Based on MCP ecosystem patterns, feature adoption varies significantly:

Feature Adoption Recommendation
Tools ~80% of servers Primary focus
Static Resources ~50% Use when needed
Prompts ~10-20% Optional
Resource Templates Rare Usually unnecessary

Why tools dominate: Tools perform actions and return results—they cover most use cases. Resources are better suited for data that clients may cache or subscribe to.

Why templates are uncommon:

  1. Tools with parameters are simpler - Instead of file:///{+path}, use a read_file tool with a path parameter
  2. Static resources usually suffice - A few fixed URIs cover most configuration/data needs
  3. Added complexity - Template matching and URI parsing add overhead for little benefit

When to use resource templates:

  • File browsers where URI semantics matter to the client
  • REST-like resource hierarchies
  • When clients need resource-specific features (subscriptions, caching hints)

API Reference

Runtime Creation
rt := mcpruntime.New(impl *mcp.Implementation, opts *mcpruntime.Options)
Tool Registration
// Generic (with schema inference)
mcpruntime.AddTool(rt, tool *mcp.Tool, handler ToolHandlerFor[In, Out])

// Low-level
rt.AddToolHandler(tool *mcp.Tool, handler mcp.ToolHandler)
Library Mode Invocation
result, err := rt.CallTool(ctx, name string, args any)
result, err := rt.GetPrompt(ctx, name string, args map[string]string)
result, err := rt.ReadResource(ctx, uri string)
Server Mode
rt.ServeStdio(ctx)
rt.ServeIO(ctx, reader, writer)
rt.Serve(ctx, transport)
rt.StreamableHTTPHandler(opts) // returns http.Handler
rt.SSEHandler(opts)            // returns http.Handler
Inspection
rt.ListTools() []*mcp.Tool
rt.ListPrompts() []*mcp.Prompt
rt.ListResources() []*mcp.Resource
rt.HasTool(name) bool
rt.ToolCount() int

License

MIT License - see LICENSE file for details.

Documentation

Overview

Package mcpruntime provides a library-first runtime for building MCP servers with interchangeable execution modes: in-process library calls and MCP server transports (stdio, HTTP).

mcpruntime wraps the official MCP Go SDK (github.com/modelcontextprotocol/go-sdk) to provide a unified API where tools, prompts, and resources are defined once and can be invoked either directly as library calls or exposed over standard MCP transports.

Design Philosophy

MCP (Model Context Protocol) is fundamentally a client-server protocol based on JSON-RPC. However, many use cases benefit from invoking MCP capabilities directly in-process without the overhead of transport serialization:

  • Unit testing tools without mocking transports
  • Embedding agent capabilities in applications
  • Building local pipelines
  • Serverless runtimes

mcpruntime treats MCP as an "edge protocol" while providing a library-first internal API. Tools registered with mcpruntime use the exact same handler signatures as the MCP SDK, ensuring behavior is identical regardless of execution mode.

Quick Start

Create a runtime, register tools, and use them either directly or via MCP:

// Create runtime
rt := mcpruntime.New(&mcp.Implementation{
	Name:    "my-server",
	Version: "v1.0.0",
}, nil)

// Register a tool using MCP SDK types
type AddInput struct {
	A int `json:"a"`
	B int `json:"b"`
}
type AddOutput struct {
	Sum int `json:"sum"`
}
rt.AddTool(&mcp.Tool{Name: "add"}, func(ctx context.Context, req *mcp.CallToolRequest, in AddInput) (*mcp.CallToolResult, AddOutput, error) {
	return nil, AddOutput{Sum: in.A + in.B}, nil
})

// Library mode: call directly
result, err := rt.CallTool(ctx, "add", map[string]any{"a": 1, "b": 2})

// Server mode: expose via stdio
rt.ServeStdio(ctx)

Tool Registration

Tools use the exact same types as the MCP SDK:

The generic [Runtime.AddTool] method provides automatic input/output schema generation and validation, matching the behavior of mcp.AddTool.

Prompts and Resources

Similarly, prompts and resources use MCP SDK types directly:

Transport Adapters

When ready to expose capabilities over MCP transports, use:

Index

Constants

This section is empty.

Variables

View Source
var ErrPromptNotFound = errors.New("prompt not found")

ErrPromptNotFound is returned when attempting to get a prompt that doesn't exist.

View Source
var ErrResourceNotFound = errors.New("resource not found")

ErrResourceNotFound is returned when attempting to read a resource that doesn't exist.

View Source
var ErrToolNotFound = errors.New("tool not found")

ErrToolNotFound is returned when attempting to call a tool that doesn't exist.

Functions

func AddTool

func AddTool[In, Out any](r *Runtime, t *mcp.Tool, h mcp.ToolHandlerFor[In, Out])

AddTool adds a typed tool to the runtime with automatic schema inference.

This mirrors mcp.AddTool from the MCP SDK. The generic type parameters In and Out are used to automatically generate JSON schemas for the tool's input and output if not already specified in the Tool struct.

The In type provides the default input schema (must be a struct or map). The Out type provides the default output schema (use 'any' to omit).

Example:

type AddInput struct {
	A int `json:"a" jsonschema:"first number to add"`
	B int `json:"b" jsonschema:"second number to add"`
}
type AddOutput struct {
	Sum int `json:"sum"`
}

mcpruntime.AddTool(rt, &mcp.Tool{
	Name:        "add",
	Description: "Add two numbers",
}, func(ctx context.Context, req *mcp.CallToolRequest, in AddInput) (*mcp.CallToolResult, AddOutput, error) {
	return nil, AddOutput{Sum: in.A + in.B}, nil
})

func AuthorizationServerMetadataHandler added in v0.2.0

func AuthorizationServerMetadataHandler(tokenPath string) http.Handler

AuthorizationServerMetadataHandler returns an http.Handler for the OAuth 2.0 Authorization Server Metadata endpoint (RFC 8414). This should be mounted at /.well-known/oauth-authorization-server The tokenPath is the path to the token endpoint (e.g., "/oauth/token").

func ProtectedResourceMetadataHandler added in v0.2.0

func ProtectedResourceMetadataHandler(mcpPath string) http.Handler

ProtectedResourceMetadataHandler returns an http.Handler for the OAuth 2.0 Protected Resource Metadata endpoint (RFC 9728). This should be mounted at /.well-known/oauth-protected-resource The mcpPath is the path to the MCP endpoint (e.g., "/mcp").

Types

type HTTPServerOptions added in v0.2.0

type HTTPServerOptions struct {
	// Addr is the local address to listen on (e.g., ":8080").
	// Required when Ngrok is nil. When Ngrok is configured, this is optional
	// and defaults to a random available port.
	Addr string

	// Path is the HTTP path for the MCP endpoint. Defaults to "/mcp".
	Path string

	// ReadHeaderTimeout is the timeout for reading request headers.
	// Defaults to 10 seconds.
	ReadHeaderTimeout time.Duration

	// Ngrok configures optional ngrok tunneling. When set, the server
	// is exposed via ngrok and the PublicURL in the result will be populated.
	Ngrok *NgrokOptions

	// StreamableHTTPOptions are passed to the MCP StreamableHTTP handler.
	StreamableHTTPOptions *mcp.StreamableHTTPOptions

	// OAuth configures simple OAuth 2.0 client credentials authentication.
	// When set, the /mcp endpoint requires a Bearer token and a token
	// endpoint is exposed at /oauth/token (or OAuth.TokenPath if set).
	// Deprecated: Use OAuth2 for full OAuth 2.1 with PKCE support (required by ChatGPT.com).
	OAuth *OAuthOptions

	// OAuth2 configures full OAuth 2.1 Authorization Code + PKCE authentication.
	// This is required for ChatGPT.com and other clients that need DCR and PKCE.
	// When set, the following endpoints are exposed:
	//   - /oauth/authorize - Authorization endpoint with login page
	//   - /oauth/token - Token endpoint
	//   - /oauth/register - Dynamic Client Registration
	//   - /.well-known/oauth-authorization-server - Metadata
	//   - /.well-known/oauth-protected-resource - Resource metadata
	OAuth2 *OAuth2Options

	// OnReady is called when the server is ready to accept connections,
	// before ServeHTTP blocks. This is useful for logging the server URL.
	OnReady func(result *HTTPServerResult)
}

HTTPServerOptions configures HTTP-based serving.

type HTTPServerResult added in v0.2.0

type HTTPServerResult struct {
	// LocalAddr is the local address the server is listening on (e.g., "localhost:8080").
	LocalAddr string

	// LocalURL is the full local URL including path (e.g., "http://localhost:8080/mcp").
	LocalURL string

	// PublicURL is the ngrok public URL including path, if ngrok is enabled.
	// Empty string if ngrok is not configured.
	PublicURL string

	// OAuth contains the OAuth credentials if OAuth (client_credentials) is enabled.
	// Nil if OAuth is not configured.
	// Deprecated: Use OAuth2 for full OAuth 2.1 support.
	OAuth *OAuthCredentials

	// OAuth2 contains the OAuth 2.1 server information if OAuth2 is enabled.
	// Nil if OAuth2 is not configured.
	OAuth2 *OAuth2Credentials
}

HTTPServerResult contains information about the running HTTP server.

type NgrokOptions added in v0.2.0

type NgrokOptions struct {
	// Authtoken is the ngrok authentication token.
	// If empty, uses the NGROK_AUTHTOKEN environment variable.
	Authtoken string

	// Domain is an optional custom ngrok domain (e.g., "myapp.ngrok.io").
	// Requires a paid ngrok plan.
	Domain string
}

NgrokOptions configures ngrok tunneling.

type OAuth2Credentials added in v0.2.0

type OAuth2Credentials struct {
	// ClientID is the pre-registered client ID.
	ClientID string

	// ClientSecret is the pre-registered client secret.
	ClientSecret string

	// AuthorizationEndpoint is the authorization URL.
	AuthorizationEndpoint string

	// TokenEndpoint is the token URL.
	TokenEndpoint string

	// RegistrationEndpoint is the DCR URL.
	RegistrationEndpoint string

	// Users is the map of configured users (for display/logging).
	Users []string
}

OAuth2Credentials contains the OAuth 2.1 server information.

type OAuth2Options added in v0.2.0

type OAuth2Options struct {
	// Users is a map of username to password for authentication.
	// At least one user must be configured.
	Users map[string]string

	// ClientID is the pre-registered OAuth client ID.
	// If empty, one will be auto-generated.
	ClientID string

	// ClientSecret is the pre-registered OAuth client secret.
	// If empty, one will be auto-generated.
	ClientSecret string

	// RedirectURIs is the list of allowed redirect URIs for the pre-registered client.
	// Defaults to allowing any URI (for flexibility with ChatGPT.com).
	RedirectURIs []string

	// AccessTokenExpiry is how long access tokens are valid.
	// Defaults to 1 hour.
	AccessTokenExpiry time.Duration

	// RefreshTokenExpiry is how long refresh tokens are valid.
	// Defaults to 24 hours. Set to 0 to disable refresh tokens.
	RefreshTokenExpiry time.Duration

	// AllowedScopes is the list of scopes this server supports.
	// If empty, no scope validation is performed.
	AllowedScopes []string

	// LoginPageTemplate is custom HTML for the login page.
	// If empty, a default login page is used.
	LoginPageTemplate string

	// Debug enables verbose logging for OAuth operations.
	Debug bool
}

OAuth2Options configures OAuth 2.1 Authorization Code + PKCE authentication.

type OAuthCredentials added in v0.2.0

type OAuthCredentials struct {
	// ClientID is the OAuth client ID (provided or auto-generated).
	ClientID string

	// ClientSecret is the OAuth client secret (provided or auto-generated).
	ClientSecret string

	// TokenEndpoint is the full URL of the token endpoint.
	TokenEndpoint string
}

OAuthCredentials contains the OAuth credentials for the server. This is returned in HTTPServerResult when OAuth is enabled.

type OAuthOptions added in v0.2.0

type OAuthOptions struct {
	// ClientID is the OAuth client ID. If empty, one will be auto-generated.
	ClientID string

	// ClientSecret is the OAuth client secret. If empty, one will be auto-generated.
	ClientSecret string

	// TokenExpiry is how long access tokens are valid. Defaults to 1 hour.
	TokenExpiry time.Duration

	// TokenPath is the path for the token endpoint. Defaults to "/oauth/token".
	TokenPath string
}

OAuthOptions configures OAuth 2.0 client credentials grant authentication.

type Options

type Options struct {
	// Logger for runtime activity. If nil, a default logger is used.
	Logger *slog.Logger

	// ServerOptions are passed directly to the underlying mcp.Server.
	ServerOptions *mcp.ServerOptions
}

Options configures a Runtime.

type PromptHandler

type PromptHandler = mcp.PromptHandler

PromptHandler is an alias for the MCP SDK's prompt handler.

type ResourceHandler

type ResourceHandler = mcp.ResourceHandler

ResourceHandler is an alias for the MCP SDK's resource handler.

type Runtime

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

Runtime is the core type for mcpruntime. It wraps an MCP Server and provides both library-mode direct invocation and transport-based MCP server capabilities.

A Runtime should be created with New and configured with tools, prompts, and resources before use.

func New

func New(impl *mcp.Implementation, opts *Options) *Runtime

New creates a new Runtime with the given implementation info and options.

The implementation parameter must not be nil and describes the server identity (name, version, etc.) that will be reported to MCP clients.

The options parameter may be nil to use default options.

func (*Runtime) AddPrompt

func (r *Runtime) AddPrompt(p *mcp.Prompt, h mcp.PromptHandler)

AddPrompt adds a prompt to the runtime.

The prompt handler is called when clients request the prompt via prompts/get. In library mode, it can be invoked directly via Runtime.GetPrompt.

Example:

rt.AddPrompt(&mcp.Prompt{
	Name:        "summarize",
	Description: "Summarize the given text",
	Arguments: []*mcp.PromptArgument{
		{Name: "text", Description: "Text to summarize", Required: true},
	},
}, func(ctx context.Context, req *mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
	text := req.Params.Arguments["text"]
	return &mcp.GetPromptResult{
		Messages: []*mcp.PromptMessage{
			{Role: "user", Content: &mcp.TextContent{
				Text: fmt.Sprintf("Please summarize: %s", text),
			}},
		},
	}, nil
})

func (*Runtime) AddResource

func (r *Runtime) AddResource(res *mcp.Resource, h mcp.ResourceHandler)

AddResource adds a resource to the runtime.

The resource handler is called when clients request the resource via resources/read. In library mode, it can be invoked directly via Runtime.ReadResource.

Example:

rt.AddResource(&mcp.Resource{
	URI:         "config://app/settings",
	Name:        "settings",
	Description: "Application settings",
	MIMEType:    "application/json",
}, func(ctx context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
	return &mcp.ReadResourceResult{
		Contents: []*mcp.ResourceContents{{
			URI:  req.Params.URI,
			Text: `{"debug": true}`,
		}},
	}, nil
})

func (*Runtime) AddResourceTemplate

func (r *Runtime) AddResourceTemplate(t *mcp.ResourceTemplate, h mcp.ResourceHandler)

AddResourceTemplate adds a resource template to the runtime.

Resource templates allow dynamic resource URIs using URI template syntax (RFC 6570). The handler is called for any URI matching the template.

Note: Resource templates are registered with the MCP server but not currently supported in library-mode dispatch. Use Runtime.MCPServer for full resource template support.

func (*Runtime) AddToolHandler

func (r *Runtime) AddToolHandler(t *mcp.Tool, h mcp.ToolHandler)

AddToolHandler adds a tool with a low-level handler to the runtime.

This is the low-level API that mirrors mcp.Server.AddTool. It does not perform automatic input validation or output schema generation.

The tool's InputSchema must be non-nil and have type "object". See mcp.Server.AddTool for full documentation on requirements.

Most users should use the generic AddTool function instead.

func (*Runtime) CallTool

func (r *Runtime) CallTool(ctx context.Context, name string, args any) (*mcp.CallToolResult, error)

CallTool invokes a tool by name with the given arguments.

This is the library-mode entry point for tool invocation. It bypasses MCP JSON-RPC transport and directly invokes the tool handler.

The args parameter should be a map[string]any or a struct that can be marshaled to JSON matching the tool's input schema.

Returns ErrToolNotFound if no tool with the given name exists.

func (*Runtime) Connect

func (r *Runtime) Connect(ctx context.Context, transport mcp.Transport) (*mcp.ServerSession, error)

Connect creates a session for a single connection.

Unlike Runtime.ServeStdio which runs a blocking loop, Connect returns immediately with a session that can be used to await client termination or manage the connection lifecycle.

This is useful for HTTP-based transports or when managing multiple concurrent sessions.

func (*Runtime) GetPrompt

func (r *Runtime) GetPrompt(ctx context.Context, name string, args map[string]string) (*mcp.GetPromptResult, error)

GetPrompt retrieves a prompt by name with the given arguments.

This is the library-mode entry point for prompt retrieval. It bypasses MCP JSON-RPC transport and directly invokes the prompt handler.

Returns ErrPromptNotFound if no prompt with the given name exists.

func (*Runtime) HasPrompt

func (r *Runtime) HasPrompt(name string) bool

HasPrompt reports whether a prompt with the given name is registered.

func (*Runtime) HasResource

func (r *Runtime) HasResource(uri string) bool

HasResource reports whether a resource with the given URI is registered.

func (*Runtime) HasTool

func (r *Runtime) HasTool(name string) bool

HasTool reports whether a tool with the given name is registered.

func (*Runtime) Implementation

func (r *Runtime) Implementation() *mcp.Implementation

Implementation returns the server's implementation info.

func (*Runtime) InMemorySession

func (r *Runtime) InMemorySession(ctx context.Context) (*mcp.ServerSession, *mcp.ClientSession, error)

InMemorySession creates an in-memory client-server session pair.

This is useful for testing or for scenarios where you want MCP semantics (including JSON-RPC serialization) but don't need network transport.

Returns the server session and client session. The caller should close the client session when done, which will also terminate the server session.

Example:

serverSession, clientSession, err := rt.InMemorySession(ctx)
if err != nil {
	log.Fatal(err)
}
defer clientSession.Close()

// Use clientSession to call tools via MCP protocol
result, err := clientSession.CallTool(ctx, &mcp.CallToolParams{Name: "add", Arguments: map[string]any{"a": 1, "b": 2}})

func (*Runtime) ListPrompts

func (r *Runtime) ListPrompts() []*mcp.Prompt

ListPrompts returns all registered prompts.

func (*Runtime) ListResources

func (r *Runtime) ListResources() []*mcp.Resource

ListResources returns all registered resources.

func (*Runtime) ListTools

func (r *Runtime) ListTools() []*mcp.Tool

ListTools returns all registered tools.

func (*Runtime) MCPServer

func (r *Runtime) MCPServer() *mcp.Server

MCPServer returns the underlying mcp.Server for advanced use cases.

This is an escape hatch for scenarios where direct access to the MCP SDK server is needed, such as plugging into existing MCP infrastructure or accessing features not yet exposed by mcpruntime.

Use with caution: modifications to the returned server may not be reflected in mcpruntime's library-mode dispatch.

func (*Runtime) PromptCount

func (r *Runtime) PromptCount() int

PromptCount returns the number of registered prompts.

func (*Runtime) ReadResource

func (r *Runtime) ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)

ReadResource reads a resource by URI.

This is the library-mode entry point for resource reading. It bypasses MCP JSON-RPC transport and directly invokes the resource handler.

Returns ErrResourceNotFound if no resource with the given URI exists.

func (*Runtime) RemovePrompts

func (r *Runtime) RemovePrompts(names ...string)

RemovePrompts removes prompts with the given names from the runtime.

func (*Runtime) RemoveResourceTemplates

func (r *Runtime) RemoveResourceTemplates(uriTemplates ...string)

RemoveResourceTemplates removes resource templates with the given URI templates.

func (*Runtime) RemoveResources

func (r *Runtime) RemoveResources(uris ...string)

RemoveResources removes resources with the given URIs from the runtime.

func (*Runtime) RemoveTools

func (r *Runtime) RemoveTools(names ...string)

RemoveTools removes tools with the given names from the runtime.

func (*Runtime) ResourceCount

func (r *Runtime) ResourceCount() int

ResourceCount returns the number of registered resources.

func (*Runtime) SSEHandler

func (r *Runtime) SSEHandler(opts *mcp.SSEOptions) http.Handler

SSEHandler returns an http.Handler for the legacy SSE transport.

This is provided for backwards compatibility with older MCP clients. New implementations should prefer Runtime.StreamableHTTPHandler.

func (*Runtime) Serve

func (r *Runtime) Serve(ctx context.Context, transport mcp.Transport) error

Serve runs the runtime with a custom MCP transport.

This is the most flexible option, allowing any transport that implements the mcp.Transport interface.

func (*Runtime) ServeHTTP added in v0.2.0

func (r *Runtime) ServeHTTP(ctx context.Context, opts *HTTPServerOptions) (*HTTPServerResult, error)

ServeHTTP starts an HTTP server for the MCP runtime.

When opts.Ngrok is configured, the server is exposed via ngrok tunnel and the returned result includes the public URL.

ServeHTTP blocks until the context is cancelled, at which point it performs a graceful shutdown.

Example without ngrok:

result, err := rt.ServeHTTP(ctx, &mcpruntime.HTTPServerOptions{
    Addr: ":8080",
})
if err != nil {
    log.Fatal(err)
}
log.Printf("MCP server running at %s", result.LocalURL)

Example with ngrok:

result, err := rt.ServeHTTP(ctx, &mcpruntime.HTTPServerOptions{
    Ngrok: &mcpruntime.NgrokOptions{
        Authtoken: os.Getenv("NGROK_AUTHTOKEN"),
    },
})
if err != nil {
    log.Fatal(err)
}
log.Printf("MCP server running at %s", result.PublicURL)

func (*Runtime) ServeIO

func (r *Runtime) ServeIO(ctx context.Context, reader io.ReadCloser, writer io.WriteCloser) error

ServeIO runs the runtime as an MCP server over custom IO streams.

This is useful for testing or when you need to control the IO streams directly rather than using stdin/stdout.

func (*Runtime) ServeStdio

func (r *Runtime) ServeStdio(ctx context.Context) error

ServeStdio runs the runtime as an MCP server over stdio transport.

This is the standard way to run an MCP server as a subprocess. The server communicates with the client via stdin/stdout using newline-delimited JSON.

ServeStdio blocks until the client terminates the connection or the context is cancelled.

Example:

func main() {
	rt := mcpruntime.New(&mcp.Implementation{Name: "my-server", Version: "v1.0.0"}, nil)
	// ... register tools ...
	if err := rt.ServeStdio(context.Background()); err != nil {
		log.Fatal(err)
	}
}

func (*Runtime) StreamableHTTPHandler

func (r *Runtime) StreamableHTTPHandler(opts *mcp.StreamableHTTPOptions) http.Handler

StreamableHTTPHandler returns an http.Handler for MCP's Streamable HTTP transport.

This enables serving MCP over HTTP using Server-Sent Events (SSE) for server-to-client messages. The handler can be mounted on any HTTP server.

Example:

rt := mcpruntime.New(&mcp.Implementation{Name: "my-server", Version: "v1.0.0"}, nil)
// ... register tools ...
http.Handle("/mcp", rt.StreamableHTTPHandler(nil))
http.ListenAndServe(":8080", nil)

func (*Runtime) ToolCount

func (r *Runtime) ToolCount() int

ToolCount returns the number of registered tools.

type ToolHandler

type ToolHandler = mcp.ToolHandler

ToolHandler is an alias for the MCP SDK's low-level tool handler.

type ToolHandlerFor

type ToolHandlerFor[In, Out any] = mcp.ToolHandlerFor[In, Out]

ToolHandlerFor is an alias for the MCP SDK's typed tool handler. It provides automatic input/output schema inference and validation.

Directories

Path Synopsis
Package oauth2server provides a standalone OAuth 2.1 Authorization Server with PKCE support, designed for MCP server authentication.
Package oauth2server provides a standalone OAuth 2.1 Authorization Server with PKCE support, designed for MCP server authentication.

Jump to

Keyboard shortcuts

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