Skip to content

tinywasm/mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tinywasm/mcp

Lean Go implementation of the Model Context Protocol (MCP) over JSON-RPC 2.0. Protocol-only, WASM-safe, minimal public API.

Installation

go get github.com/tinywasm/mcp

Quickstart

1. Define tool arguments with validation (using ormc)

// Tool arguments are plain structs with validation tags
// ormc generates Schema(), Pointers(), Validate() automatically
type SearchArgs struct {
    Query string `validate:"required,min=1,max=255"`
    Limit int64  `validate:"min=1,max=100"`
}

2. Write the handler

func handleSearch(ctx *context.Context, req mcp.Request) (*mcp.Result, error) {
    var args SearchArgs
    if err := req.Bind(&args); err != nil {
        return nil, err // server wraps as JSON-RPC error
    }
    return mcp.Text("found 3 results"), nil
}

3. Register and serve

srv := mcp.NewServer(mcp.Config{
    Name:    "my-server",
    Version: "1.0.0",
    Auth:    myAuth, // implements mcp.Authorizer
}, nil)

srv.AddTool(mcp.Tool{
    Name:        "search",
    Description: "Search items by query",
    InputSchema: new(SearchArgs).Schema(),
    Resource:    "items",
    Action:      'r',
    Execute:     handleSearch,
})

http.Handle("/mcp", srv.HTTPHandler())
http.ListenAndServe(":3030", nil)

4. Tool results

return mcp.Text("operation completed"), nil   // text
return mcp.JSON(&MyData{Name: "test"})        // JSON (Fielder)
text, err := mcp.GetText(result)              // extract text

Authorizer

mcp defines the interface; implementation lives in tinywasm/user:

type Authorizer interface {
    Authorize(token string) (userID string, err error)
}

// In your app:
auth := user.NewBearerAuth(secret) // satisfies mcp.Authorizer

ToolProvider

Group related tools and their dependencies in a provider:

type CatalogProvider struct {
    db *postgres.DB
}

type CatalogSearchArgs struct {
    Query    string `validate:"required,min=1,max=255"`
    Category string `validate:"max=50"`
}

type CatalogUpdateArgs struct {
    ProductID string  `validate:"required"`
    Price     float64 `validate:"required,min=0"`
}

func (p *CatalogProvider) Tools() []mcp.Tool {
    return []mcp.Tool{
        {
            Name:        "catalog_search",
            Description: "Search product catalog",
            InputSchema: new(CatalogSearchArgs).Schema(),
            Resource:    "catalog",
            Action:      'r',
            Execute:     p.handleSearch,
        },
        {
            Name:        "catalog_update",
            Description: "Update product price",
            InputSchema: new(CatalogUpdateArgs).Schema(),
            Resource:    "catalog",
            Action:      'u',
            Execute:     p.handleUpdate,
        },
    }
}

func (p *CatalogProvider) handleSearch(ctx *context.Context, req mcp.Request) (*mcp.Result, error) {
    var args CatalogSearchArgs
    if err := req.Bind(&args); err != nil {
        return nil, err
    }
    // ... query p.db
    return mcp.Text("found 3 products"), nil
}

// Pass providers to NewServer
srv := mcp.NewServer(config, []mcp.ToolProvider{&CatalogProvider{db: db}})

WASM / Browser

The protocol core compiles with TinyGo. Server-only files (//go:build !wasm) are excluded automatically.

In browser mode, call the handler directly — no HTTP server needed:

handler := mcp.NewServer(config, providers)
response := handler.HandleMessage(&ctx, message)

API Reference

Symbol Description
NewServer(config, providers) Create MCP server
Server.AddTool(tool) Register a single tool
Server.HTTPHandler() HTTP endpoint (server-only)
Server.HandleMessage(ctx, msg) Process JSON-RPC message (WASM-safe)
Tool{Name, Description, InputSchema, Resource, Action, Execute} Tool definition
ToolProvider Interface: Tools() []Tool
Authorizer Interface: Authorize(token) (userID, error)
Request Incoming tool call
Request.Bind(target) Decode + validate arguments
Result Tool call result
Text(s) Create text result
JSON(data) Create JSON result
GetText(result) Extract text from result
Config Server configuration
FilterFunc Filter tools by context
CtxKeySessionID Context key for session ID (ctx.Set / ctx.Value)

See docs/WHY_ARQ.md for architecture decisions and trade-offs.

About

implementation of the Model Context Protocol (MCP)

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages