{
  "markdown": "<p align=\"center\">\n  <img src=\"docs/assets/banner.png\" alt=\"Tiny Go MCP Server — minimal Go MCP toolkit\" width=\"720\">\n</p>\n\n# Tiny Go MCP Server\n\n[![CI](https://github.com/kioie/tiny-go-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/kioie/tiny-go-mcp-server/actions/workflows/ci.yml)\n[![Go Reference](https://pkg.go.dev/badge/github.com/kioie/tiny-go-mcp-server/tinymcp.svg)](https://pkg.go.dev/github.com/kioie/tiny-go-mcp-server/tinymcp)\n[![Go Report Card](https://goreportcard.com/badge/github.com/kioie/tiny-go-mcp-server/tinymcp)](https://goreportcard.com/report/github.com/kioie/tiny-go-mcp-server/tinymcp)\n[![tiny-go-mcp-server MCP server](https://glama.ai/mcp/servers/kioie/tiny-go-mcp-server/badges/score.svg)](https://glama.ai/mcp/servers/kioie/tiny-go-mcp-server)\n\nA lightweight **Model Context Protocol (MCP)** toolkit for Go. Build spec-compliant MCP servers (stdio, streamable HTTP, legacy SSE) with tools, resources, and prompts — minimal boilerplate and automatic JSON Schema from Go structs.\n\nBuilt on the official [`modelcontextprotocol/go-sdk`](https://github.com/modelcontextprotocol/go-sdk).\n\n**Requirements:** Go 1.26+ ([download](https://go.dev/dl/)).\n\n---\n\n## Why Tiny?\n\n| | Tiny Go MCP Server | Full frameworks |\n|---|---|---|\n| **Goal** | Thin helper on official go-sdk + tiny static binary | Full MCP feature surface |\n| **Deps** | Official go-sdk only | Varies |\n| **Binary** | ~5MB stripped, no runtime on host | Often larger stacks |\n| **Schemas** | Inferred from struct tags | Manual or builder APIs |\n\nUse this project as a **library** (`tinymcp` package) or as a **starting template** (`cmd/tiny-go-mcp`).\n\n### When to use what\n\n| | **tinymcp** (this repo) | **[mcp-go](https://github.com/mark3labs/mcp-go)** | **[go-sdk](https://github.com/modelcontextprotocol/go-sdk)** alone |\n|---|---|---|---|\n| **Best for** | Thin helper on go-sdk, tiny binary | Rich helpers, large ecosystem | Full control, no extra layer |\n| **Schema** | Struct tags → auto JSON Schema | Builder APIs / helpers | `AddTool` + generics yourself |\n| **Transport** | stdio (`Start()`), streamable HTTP (`StartHTTP`), legacy SSE (`StartSSE`) | stdio, SSE, HTTP, … | All transports |\n| **Deps** | go-sdk only | Standalone module | go-sdk only |\n\nChoose **tinymcp** when you want the official protocol implementation with minimal boilerplate and a small static server binary.\n\n### Philosophy\n\n**tinymcp is a thin helper on the official go-sdk — not a replacement for it.**\n\nWe reduce setup and transport boilerplate (server creation, registration error handling, stdio/HTTP/SSE, `TextResult`, deploy examples). The protocol implementation, generics, and schema inference still come from [`modelcontextprotocol/go-sdk`](https://github.com/modelcontextprotocol/go-sdk).\n\nThat means handler code uses **both** imports — and that is intentional:\n\n```go\nimport (\n    \"github.com/kioie/tiny-go-mcp-server/tinymcp\"\n    \"github.com/modelcontextprotocol/go-sdk/mcp\" // handler types, prompts, resources, advanced APIs\n)\n```\n\n| Use **tinymcp** for | Use **go-sdk** (`mcp`) for |\n|---------------------|----------------------------|\n| `NewServer`, `RegisterTool`, transports | Handler signatures (`CallToolRequest`, `GetPromptRequest`, …) |\n| Safe registration (errors, not panics) | Tool annotations, elicitation, custom protocol features |\n| `TextResult`, HTTP middleware helpers | Anything via `server.RawServer()` |\n\nWe are **not** aiming for a non-leaky facade that hides the SDK. If you need full control, call `RawServer()` or use go-sdk directly — same underlying server, no lock-in.\n\n### tinymcp vs raw go-sdk\n\nSame protocol implementation — tinymcp removes repetitive setup. Handler code still imports `mcp` for request types in both cases.\n\n**go-sdk alone** (minimal stdio server):\n\n```go\nserver := mcp.NewServer(&mcp.Implementation{Name: \"my-mcp\", Version: \"1.0.0\"}, nil)\nmcp.AddTool(server, &mcp.Tool{\n    Name:        \"greet\",\n    Description: \"Greet someone by name\",\n}, greet)\nif err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {\n    log.Fatal(err)\n}\n```\n\n**tinymcp** (same tool, less boilerplate):\n\n```go\ns := tinymcp.NewServer(\"my-mcp\", \"1.0.0\")\nif err := tinymcp.RegisterTool(s, \"greet\", \"Greet someone by name\", greet); err != nil {\n    log.Fatal(err)\n}\nlog.Fatal(s.Start())\n```\n\n| tinymcp adds | Still on go-sdk (`mcp`) |\n|--------------|-------------------------|\n| `NewServer(name, ver)` | Handler signatures (`CallToolRequest`, prompts, resources) |\n| `RegisterTool` + struct-tag JSON Schema | Tool annotations via `RegisterToolDef` + `mcp.Tool` |\n| Safe registration errors (no panics) | Advanced session / event-store APIs |\n| `Start()` / `StartHTTP()` / HTTP middleware | Full control via `RawServer()` |\n\nUse **go-sdk alone** when you want zero wrapper. Use **tinymcp** when you want less setup while staying on the official implementation.\n\n### Transport\n\n| Method | API | Typical clients |\n|--------|-----|-----------------|\n| **stdio** (default) | `Start()` | Cursor, Claude Desktop, Windsurf (local subprocess) |\n| **Streamable HTTP** | `StartHTTP(addr, opts)` or `StreamableHTTPHandler` | Remote MCP clients, gateways, browser tools |\n| **Legacy SSE** | `StartSSE(addr, opts)` or `SSEHandler` | Older clients on MCP 2024-11-05 SSE transport |\n\n`Start()` runs **stdio** (stdin/stdout) — what most local AI clients expect.\n\nFor HTTP/SSE, tinymcp wraps the official go-sdk handlers with minimal options:\n\n```go\n// Streamable HTTP on loopback (stateless demo — no GET/SSE or server→client RPC)\nlog.Fatal(server.StartHTTP(\"127.0.0.1:8080\", &tinymcp.HTTPOptions{Stateless: true}))\n\n// Or mount on your own mux (auth, TLS, path prefix)\nhandler, _ := tinymcp.StreamableHTTPHandler(server, nil)\nhttp.Handle(\"/mcp\", handler)\n```\n\n**Stateless mode** (`Stateless: true`) is the default in examples: one POST JSON-RPC per request, no long-lived SSE GET stream, and no server-initiated messages. Omit it or use session options when you need full streamable HTTP sessions — see [`docs/HTTP.md`](docs/HTTP.md).\n\nSee [`docs/HTTP.md`](docs/HTTP.md) and [`examples/http`](examples/http). To host for [Smithery URL listing](docs/SMITHERY.md) (no Docker for end users), use [`examples/http-deploy`](examples/http-deploy). For advanced session routing or event stores, use `server.RawServer()` with the [go-sdk](https://github.com/modelcontextprotocol/go-sdk) directly.\n\n---\n\n## Quick start (library)\n\nStep-by-step guide: [docs/QUICKSTART.md](docs/QUICKSTART.md). AI codegen: [SYSTEM_PROMPT.md](SYSTEM_PROMPT.md).\n\n```bash\ngo get github.com/kioie/tiny-go-mcp-server/tinymcp@latest\n```\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/kioie/tiny-go-mcp-server/tinymcp\"\n\t\"github.com/modelcontextprotocol/go-sdk/mcp\"\n)\n\ntype greetArgs struct {\n\tName string `json:\"name\" jsonschema:\"Person to greet\"`\n}\n\nfunc main() {\n\ts := tinymcp.NewServer(\"my-mcp\", \"1.0.0\")\n\tif err := tinymcp.RegisterTool(s, \"greet\", \"Greet someone by name\", greet); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tlog.Fatal(s.Start())\n}\n\nfunc greet(_ context.Context, _ *mcp.CallToolRequest, args greetArgs) (*mcp.CallToolResult, any, error) {\n\treturn tinymcp.TextResult(fmt.Sprintf(\"Hello, %s!\", args.Name)), nil, nil\n}\n```\n\nSee [`examples/minimal`](examples/minimal) for a runnable copy-paste example.\n\n### Scaffold a new server\n\nRequires tagged module [`template/`](template/) (v1.1.1+) for stdio, or [`template-http/`](template-http/) for streamable HTTP:\n\n```bash\ngo install golang.org/x/tools/cmd/gonew@latest\ngonew github.com/kioie/tiny-go-mcp-server/template@latest example.com/my-mcp my-mcp\ncd my-mcp && go run .\n\n# HTTP deploy (Smithery / Fly / Render):\ngonew github.com/kioie/tiny-go-mcp-server/template-http@latest example.com/my-mcp-http my-mcp-http\ncd my-mcp-http && go run .\n```\n\nOr copy [`examples/minimal`](examples/minimal), [`template/`](template/), or [`template-http/`](template-http/) directly.\n\n---\n\n## Install the example server\n\nBoth install paths produce a binary named **`tiny-go-mcp`**:\n\n```bash\n# Installs to $(go env GOPATH)/bin/tiny-go-mcp\ngo install github.com/kioie/tiny-go-mcp-server/cmd/tiny-go-mcp@latest\n```\n\nOr build from source (binary in the repo root):\n\n```bash\ngit clone https://github.com/kioie/tiny-go-mcp-server.git\ncd tiny-go-mcp-server\nmake release   # → ./tiny-go-mcp\n```\n\n| Method | Binary name | Typical path |\n|--------|-------------|--------------|\n| `go install …/cmd/tiny-go-mcp` | `tiny-go-mcp` | `$(go env GOPATH)/bin/tiny-go-mcp` |\n| `make build` / `make release` | `tiny-go-mcp` | `./tiny-go-mcp` in the repo |\n| `make install` | `tiny-go-mcp` | `$(go env GOPATH)/bin/tiny-go-mcp` |\n\n### Example tools (reference server)\n\nThese tools exist for **MCP integration demos**, not production logic. Agents should compute math and write greetings in-chat unless they are explicitly testing tool calls.\n\n| Tool | When to use | When not to / alternative | Arguments |\n|------|-------------|---------------------------|-----------|\n| `add` | Test that the client can call an addition tool | Real arithmetic → compute locally or use a calculator MCP | `a`, `b` |\n| `subtract` | Test subtraction wiring (use instead of `add` for subtraction tests) | Real arithmetic → compute locally | `a`, `b` |\n| `greet` | Test a text-returning tool (use instead of `add`/`subtract` for messaging demos) | User-facing hello → reply in the conversation | `name` (required), `greeting` (optional) |\n\n---\n\n## Connect AI clients\n\nMCP servers communicate over **stdio**. Point your client at the compiled binary path.\n\nTemplate config: [`examples/mcp-client-config.json`](examples/mcp-client-config.json) (copy and set the absolute path to `tiny-go-mcp`).\n\n**Logging:** The protocol uses stdin/stdout. Server logs (if any) go to **stderr** only. Set `TINY_GO_MCP_VERBOSE=1` on the server process to enable startup log lines.\n\n### Cursor\n\nSettings → **Features → MCP** → Add server:\n\n- **Name**: `tiny-go-mcp`\n- **Type**: `stdio`\n- **Command**: `/absolute/path/to/tiny-go-mcp`\n\nOr add to `.cursor/mcp.json` in your project:\n\n```json\n{\n  \"mcpServers\": {\n    \"tiny-go-mcp\": {\n      \"command\": \"/absolute/path/to/tiny-go-mcp\"\n    }\n  }\n}\n```\n\n### Claude Desktop\n\n`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\\Claude\\claude_desktop_config.json` (Windows):\n\n```json\n{\n  \"mcpServers\": {\n    \"tiny-go-mcp\": {\n      \"command\": \"/absolute/path/to/tiny-go-mcp\"\n    }\n  }\n}\n```\n\n### Windsurf / Zed / other stdio clients\n\nUse the same shape: **command** = absolute path to `tiny-go-mcp`, transport = stdio. Refer to your client’s MCP docs for the config file location.\n\n### Tips for LLM-friendly tools\n\n- Use clear **tool names** (`snake_case`) and descriptions that say **when to use**, **when not to**, and **which sibling tool** applies — models pick tools from these and often have overlapping options.\n- Add `jsonschema` tags on struct fields so argument docs appear in the schema.\n- Return human-readable text via `tinymcp.TextResult` for predictable client display.\n- See [AGENTS.md](AGENTS.md) for conventions when extending this repo with AI assistants.\n\n---\n\n## Resources and prompts\n\nRegister read-only context and reusable prompt templates alongside tools:\n\n```go\nif err := tinymcp.RegisterTextResource(server, \"file:///info\", \"info\", \"Server metadata\", \"text/plain\", \"…\"); err != nil {\n\tlog.Fatal(err)\n}\nif err := tinymcp.RegisterPrompt(server, \"code_review\", \"Review code\", []*mcp.PromptArgument{\n\t{Name: \"code\", Required: true},\n}, func(_ context.Context, req *mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {\n\tcode := req.Params.Arguments[\"code\"]\n\tif code == \"\" {\n\t\treturn nil, tinymcp.RequiredPromptArgument(\"code\")\n\t}\n\treturn tinymcp.PromptResult(\"Review\", tinymcp.UserPromptMessage(\"Review:\\n\"+code)), nil\n}); err != nil {\n\tlog.Fatal(err)\n}\n```\n\nRunnable example: [`examples/resources`](examples/resources). For dynamic URI templates use `RegisterResourceTemplate`.\n\n---\n\n## Package API\n\n```go\nserver := tinymcp.NewServer(\"name\", \"version\")\ntinymcp.NewServer(\"name\", \"version\", tinymcp.WithInstructions(\"…\")) // optional SDK config\ntinymcp.NewServerWithOptions(\"name\", \"version\", &mcp.ServerOptions{…})\ntinymcp.RegisterTool(server, name, description, handler)     // typed handler, auto schema\ntinymcp.RegisterTextResource(server, uri, name, desc, mime, text)\ntinymcp.RegisterPrompt(server, name, desc, args, handler)\nserver.Start()                                              // stdio transport\nserver.StartHTTP(\":8080\", &tinymcp.HTTPOptions{})         // streamable HTTP\nserver.StartSSE(\":8080\", nil)                             // legacy SSE\ntinymcp.StreamableHTTPHandler(server, nil)                // mount on custom http.Server\ntinymcp.TextResult(\"message\")                               // tool text helper\ntinymcp.TextResource(uri, mime, text)                       // resource read helper\ntinymcp.PromptResult(desc, tinymcp.UserPromptMessage(\"…\")) // prompt helper\nserver.RawServer()                                          // escape hatch to go-sdk\n\n// v1.2+: panic-at-startup registration or errors.Is sentinels\ntinymcp.MustRegisterTool(server, name, description, handler)\nerrors.Is(err, tinymcp.ErrNilServer)                        // ErrNilTool, ErrNilHandler, ErrRegistrationFailed\nopts := (&tinymcp.HTTPOptions{Stateless: true}).WithMiddleware(requestLogger)\ntinymcp.ListenAndServeHTTPContext(ctx, addr, handler)       // graceful shutdown; also StartHTTPContext / StartSSEContext\n```\n\nDocumentation: [pkg.go.dev/github.com/kioie/tiny-go-mcp-server/tinymcp](https://pkg.go.dev/github.com/kioie/tiny-go-mcp-server/tinymcp). Upgrading from v1.1.x: [docs/MIGRATION-v1.2.md](docs/MIGRATION-v1.2.md).\n\n---\n\n## Development\n\n| Command | Description |\n|---------|-------------|\n| `make test` | Run tests with race detector |\n| `make lint` | golangci-lint |\n| `make lint-tools` | Validate MCP tool descriptions in reference servers |\n| `make coverage` | Coverage report |\n| `make build` | Dev binary `./tiny-go-mcp` |\n| `make release` | Stripped static binary |\n| `make install` | `go install` → `$(go env GOPATH)/bin/tiny-go-mcp` |\n\n### Smaller binaries (~1.8MB)\n\nAfter `make release`, optionally pack with [UPX](https://upx.github.io/):\n\n```bash\nupx --best --lzma tiny-go-mcp\n```\n\n---\n\n## Project structure\n\n```\ntinymcp/              # Library package\ncmd/tiny-go-mcp/      # Reference MCP server\ntemplate/             # gonew stdio scaffold\ntemplate-http/        # gonew streamable HTTP deploy scaffold\nexamples/minimal/     # Minimal stdio example\nexamples/http/        # Streamable HTTP example\nexamples/http-deploy/ # Deployable HTTP + Smithery URL listing (server card, Render/Fly)\nexamples/resources/   # Resources + prompts example\nexamples/mcp-client-config.json  # Cursor/Claude-style template\nscripts/lint-tools/   # MCP tool description linter (make lint-tools)\ndocs/                 # Guides — see below\nserver.json           # MCP Registry metadata (publish with mcp-publisher)\nCHANGELOG.md          # Release history\nSYSTEM_PROMPT.md      # Agent-facing API summary for codegen\n.github/workflows/    # CI, lint, CodeQL, releases\n```\n\nKey docs in `docs/`:\n\n| Doc | Purpose |\n|-----|---------|\n| [QUICKSTART.md](docs/QUICKSTART.md) | Step-by-step library setup |\n| [HTTP.md](docs/HTTP.md) | stdio vs streamable HTTP vs legacy SSE |\n| [STABILITY.md](docs/STABILITY.md) | Public API stability policy |\n| [MIGRATION-v1.2.md](docs/MIGRATION-v1.2.md) | Upgrade guide from v1.1.x |\n| [TLS.md](docs/TLS.md) | HTTPS via reverse proxy or Go |\n| [LOCALHOST-PROTECTION.md](docs/LOCALHOST-PROTECTION.md) | DNS rebinding security advisory |\n| [DISCOVERY.md](docs/DISCOVERY.md) | Registries and visibility |\n| [GLAMA.md](docs/GLAMA.md) | Glama hosting |\n| [SMITHERY.md](docs/SMITHERY.md) | Smithery URL and MCPB listings |\n\n---\n\n## Releases\n\nTag a semver version (e.g. `v1.2.0`) to publish stable `go get` versions and trigger [GitHub Releases](https://github.com/kioie/tiny-go-mcp-server/releases) with cross-platform binaries and multi-arch GHCR images. Release history: [CHANGELOG.md](CHANGELOG.md). Public API stability: [docs/STABILITY.md](docs/STABILITY.md). Agent-facing API summary: [SYSTEM_PROMPT.md](SYSTEM_PROMPT.md). Upgrading from v1.1.x: [docs/MIGRATION-v1.2.md](docs/MIGRATION-v1.2.md).\n\n```bash\ngit tag v1.2.0\ngit push origin v1.2.0\n```\n\n## Discovery and registries\n\nSee [docs/DISCOVERY.md](docs/DISCOVERY.md) for MCP Registry (`server.json`), awesome lists, and community directories. Listing copy and launch posts: [docs/SUBMISSIONS.md](docs/SUBMISSIONS.md). For Glama hosting with Docker, see [docs/GLAMA.md](docs/GLAMA.md).\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md). For AI codegen outside this repo, see [SYSTEM_PROMPT.md](SYSTEM_PROMPT.md). CI runs tests, lint, and CodeQL; Dependabot keeps Go and Actions dependencies updated.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n",
  "bytes": 16918,
  "sha": "2ae6adc369c7d3105c6ecd278387b113f5ad2448e11413acb4d4e3f58abf65b3",
  "repo_slug": "kioie/tiny-go-mcp-server",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_kioie_tiny_go_mcp_673da9fc/readme"
}