Tiny Go MCP Server
Demo stdio MCP server (tools, resource, prompt) for tinymcp tests—not production use.
Open source Open in the app JSON README (API)
About
Demo stdio MCP server (tools, resource, prompt) for tinymcp tests—not production use.
Details
- Kind
- MCP servers
- Topic
- No topic detected
- Publisher
- kioie
- Origin
- official
- Category
- ferramentas
- Transport
- local
- Version
- 1.1.2
- Stars
- 1
- Open pull requests
- 3
- Last push
- 2026-07-29T04:33:29Z
- Repository state
- ativo
- Language
- Go
- License
- MIT
- Added
- 2026-08-29 04:00:21
- Updated
- 2026-08-29 04:00:21
- Origin id
io.github.kioie/tiny-go-mcp
README
<p align="center">
<img src="docs/assets/banner.png" alt="Tiny Go MCP Server — minimal Go MCP toolkit" width="720">
</p>
# Tiny Go MCP Server
[](https://github.com/kioie/tiny-go-mcp-server/actions/workflows/ci.yml)
[](https://pkg.go.dev/github.com/kioie/tiny-go-mcp-server/tinymcp)
[](https://goreportcard.com/report/github.com/kioie/tiny-go-mcp-server/tinymcp)
[](https://glama.ai/mcp/servers/kioie/tiny-go-mcp-server)
A 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.
Built on the official [`modelcontextprotocol/go-sdk`](https://github.com/modelcontextprotocol/go-sdk).
**Requirements:** Go 1.26+ ([download](https://go.dev/dl/)).
---
## Why Tiny?
| | Tiny Go MCP Server | Full frameworks |
|---|---|---|
| **Goal** | Thin helper on official go-sdk + tiny static binary | Full MCP feature surface |
| **Deps** | Official go-sdk only | Varies |
| **Binary** | ~5MB stripped, no runtime on host | Often larger stacks |
| **Schemas** | Inferred from struct tags | Manual or builder APIs |
Use this project as a **library** (`tinymcp` package) or as a **starting template** (`cmd/tiny-go-mcp`).
### When to use what
| | **tinymcp** (this repo) | **[mcp-go](https://github.com/mark3labs/mcp-go)** | **[go-sdk](https://github.com/modelcontextprotocol/go-sdk)** alone |
|---|---|---|---|
| **Best for** | Thin helper on go-sdk, tiny binary | Rich helpers, large ecosystem | Full control, no extra layer |
| **Schema** | Struct tags → auto JSON Schema | Builder APIs / helpers | `AddTool` + generics yourself |
| **Transport** | stdio (`Start()`), streamable HTTP (`StartHTTP`), legacy SSE (`StartSSE`) | stdio, SSE, HTTP, … | All transports |
| **Deps** | go-sdk only | Standalone module | go-sdk only |
Choose **tinymcp** when you want the official protocol implementation with minimal boilerplate and a small static server binary.
### Philosophy
**tinymcp is a thin helper on the official go-sdk — not a replacement for it.**
We 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).
That means handler code uses **both** imports — and that is intentional:
```go
import (
"github.com/kioie/tiny-go-mcp-server/tinymcp"
"github.com/modelcontextprotocol/go-sdk/mcp" // handler types, prompts, resources, advanced APIs
)
```
| Use **tinymcp** for | Use **go-sdk** (`mcp`) for |
|---------------------|----------------------------|
| `NewServer`, `RegisterTool`, transports | Handler signatures (`CallToolRequest`, `GetPromptRequest`, …) |
| Safe registration (errors, not panics) | Tool annotations, elicitation, custom protocol features |
| `TextResult`, HTTP middleware helpers | Anything via `server.RawServer()` |
We 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.
### tinymcp vs raw go-sdk
Same protocol implementation — tinymcp removes repetitive setup. Handler code still imports `mcp` for request types in both cases.
**go-sdk alone** (minimal stdio server):
```go
server := mcp.NewServer(&mcp.Implementation{Name: "my-mcp", Version: "1.0.0"}, nil)
mcp.AddTool(server, &mcp.Tool{
Name: "greet",
Description: "Greet someone by name",
}, greet)
if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
log.Fatal(err)
}
```
**tinymcp** (same tool, less boilerplate):
```go
s := tinymcp.NewServer("my-mcp", "1.0.0")
if err := tinymcp.RegisterTool(s, "greet", "Greet someone by name", greet); err != nil {
log.Fatal(err)
}
log.Fatal(s.Start())
```
| tinymcp adds | Still on go-sdk (`mcp`) |
|--------------|-------------------------|
| `NewServer(name, ver)` | Handler signatures (`CallToolRequest`, prompts, resources) |
| `RegisterTool` + struct-tag JSON Schema | Tool annotations via `RegisterToolDef` + `mcp.Tool` |
| Safe registration errors (no panics) | Advanced session / event-store APIs |
| `Start()` / `StartHTTP()` / HTTP middleware | Full control via `RawServer()` |
Use **go-sdk alone** when you want zero wrapper. Use **tinymcp** when you want less setup while staying on the official implementation.
### Transport
| Method | API | Typical clients |
|--------|-----|-----------------|
| **stdio** (default) | `Start()` | Cursor, Claude Desktop, Windsurf (local subprocess) |
| **Streamable HTTP** | `StartHTTP(addr, opts)` or `StreamableHTTPHandler` | Remote MCP clients, gateways, browser tools |
| **Legacy SSE** | `StartSSE(addr, opts)` or `SSEHandler` | Older clients on MCP 2024-11-05 SSE transport |
`Start()` runs **stdio** (stdin/stdout) — what most local AI clients expect.
For HTTP/SSE, tinymcp wraps the official go-sdk handlers with minimal options:
```go
// Streamable HTTP on loopback (stateless demo — no GET/SSE or server→client RPC)
log.Fatal(server.StartHTTP("127.0.0.1:8080", &tinymcp.HTTPOptions{Stateless: true}))
// Or mount on your own mux (auth, TLS, path prefix)
handler, _ := tinymcp.StreamableHTTPHandler(server, nil)
http.Handle("/mcp", handler)
```
**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).
See [`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.
---
## Quick start (library)
Step-by-step guide: [docs/QUICKSTART.md](docs/QUICKSTART.md). AI codegen: [SYSTEM_PROMPT.md](SYSTEM_PROMPT.md).
```bash
go get github.com/kioie/tiny-go-mcp-server/tinymcp@latest
```
```go
package main
import (
"context"
"fmt"
"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("my-mcp", "1.0.0")
if err := tinymcp.RegisterTool(s, "greet", "Greet someone by name", greet); err != nil {
log.Fatal(err)
}
log.Fatal(s.Start())
}
func greet(_ context.Context, _ *mcp.CallToolRequest, args greetArgs) (*mcp.CallToolResult, any, error) {
return tinymcp.TextResult(fmt.Sprintf("Hello, %s!", args.Name)), nil, nil
}
```
See [`examples/minimal`](examples/minimal) for a runnable copy-paste example.
### Scaffold a new server
Requires tagged module [`template/`](template/) (v1.1.1+) for stdio, or [`template-http/`](template-http/) for streamable HTTP:
```bash
go install golang.org/x/tools/cmd/gonew@latest
gonew github.com/kioie/tiny-go-mcp-server/template@latest example.com/my-mcp my-mcp
cd my-mcp && go run .
# HTTP deploy (Smithery / Fly / Render):
gonew github.com/kioie/tiny-go-mcp-server/template-http@latest example.com/my-mcp-http my-mcp-http
cd my-mcp-http && go run .
```
Or copy [`examples/minimal`](examples/minimal), [`template/`](template/), or [`template-http/`](template-http/) directly.
---
## Install the example server
Both install paths produce a binary named **`tiny-go-mcp`**:
```bash
# Installs to $(go env GOPATH)/bin/tiny-go-mcp
go install github.com/kioie/tiny-go-mcp-server/cmd/tiny-go-mcp@latest
```
Or build from source (binary in the repo root):
```bash
git clone https://github.com/kioie/tiny-go-mcp-server.git
cd tiny-go-mcp-server
make release # → ./tiny-go-mcp
```
| Method | Binary name | Typical path |
|--------|-------------|--------------|
| `go install …/cmd/tiny-go-mcp` | `tiny-go-mcp` | `$(go env GOPATH)/bin/tiny-go-mcp` |
| `make build` / `make release` | `tiny-go-mcp` | `./tiny-go-mcp` in the repo |
| `make install` | `tiny-go-mcp` | `$(go env GOPATH)/bin/tiny-go-mcp` |
### Example tools (reference server)
These 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.
| Tool | When to use | When not to / alternative | Arguments |
|------|-------------|---------------------------|-----------|
| `add` | Test that the client can call an addition tool | Real arithmetic → compute locally or use a calculator MCP | `a`, `b` |
| `subtract` | Test subtraction wiring (use instead of `add` for subtraction tests) | Real arithmetic → compute locally | `a`, `b` |
| `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) |
---
## Connect AI clients
MCP servers communicate over **stdio**. Point your client at the compiled binary path.
Template config: [`examples/mcp-client-config.json`](examples/mcp-client-config.json) (copy and set the absolute path to `tiny-go-mcp`).
**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.
### Cursor
Settings → **Features → MCP** → Add server:
- **Name**: `tiny-go-mcp`
- **Type**: `stdio`
- **Command**: `/absolute/path/to/tiny-go-mcp`
Or add to `.cursor/mcp.json` in your project:
```json
{
"mcpServers": {
"tiny-go-mcp": {
"command": "/absolute/path/to/tiny-go-mcp"
}
}
}
```
### Claude Desktop
`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"tiny-go-mcp": {
"command": "/absolute/path/to/tiny-go-mcp"
}
}
}
```
### Windsurf / Zed / other stdio clients
Use the same shape: **command** = absolute path to `tiny-go-mcp`, transport = stdio. Refer to your client’s MCP docs for the config file location.
### Tips for LLM-friendly tools
- 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.
- Add `jsonschema` tags on struct fields so argument docs appear in the schema.
- Return human-readable text via `tinymcp.TextResult` for predictable client display.
- See [AGENTS.md](AGENTS.md) for conventions when extending this repo with AI assistants.
---
## Resources and prompts
Register read-only context and reusable prompt templates alongside tools:
```go
if err := tinymcp.RegisterTextResource(server, "file:///info", "info", "Server metadata", "text/plain", "…"); err != nil {
log.Fatal(err)
}
if err := tinymcp.RegisterPrompt(server, "code_review", "Review code", []*mcp.PromptArgument{
{Name: "code", Required: true},
}, func(_ context.Context, req *mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
code := req.Params.Arguments["code"]
if code == "" {
return nil, tinymcp.RequiredPromptArgument("code")
}
return tinymcp.PromptResult("Review", tinymcp.UserPromptMessage("Review:\n"+code)), nil
}); err != nil {
log.Fatal(err)
}
```
Runnable example: [`examples/resources`](examples/resources). For dynamic URI templates use `RegisterResourceTemplate`.
---
## Package API
```go
server := tinymcp.NewServer("name", "version")
tinymcp.NewServer("name", "version", tinymcp.WithInstructions("…")) // optional SDK config
tinymcp.NewServerWithOptions("name", "version", &mcp.ServerOptions{…})
tinymcp.RegisterTool(server, name, description, handler) // typed handler, auto schema
tinymcp.RegisterTextResource(server, uri, name, desc, mime, text)
tinymcp.RegisterPrompt(server, name, desc, args, handler)
server.Start() // stdio transport
server.StartHTTP(":8080", &tinymcp.HTTPOptions{}) // streamable HTTP
server.StartSSE(":8080", nil) // legacy SSE
tinymcp.StreamableHTTPHandler(server, nil) // mount on custom http.Server
tinymcp.TextResult("message") // tool text helper
tinymcp.TextResource(uri, mime, text) // resource read helper
tinymcp.PromptResult(desc, tinymcp.UserPromptMessage("…")) // prompt helper
server.RawServer() // escape hatch to go-sdk
// v1.2+: panic-at-startup registration or errors.Is sentinels
tinymcp.MustRegisterTool(server, name, description, handler)
errors.Is(err, tinymcp.ErrNilServer) // ErrNilTool, ErrNilHandler, ErrRegistrationFailed
opts := (&tinymcp.HTTPOptions{Stateless: true}).WithMiddleware(requestLogger)
tinymcp.ListenAndServeHTTPContext(ctx, addr, handler) // graceful shutdown; also StartHTTPContext / StartSSEContext
```
Documentation: [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).
---
## Development
| Command | Description |
|---------|-------------|
| `make test` | Run tests with race detector |
| `make lint` | golangci-lint |
| `make lint-tools` | Validate MCP tool descriptions in reference servers |
| `make coverage` | Coverage report |
| `make build` | Dev binary `./tiny-go-mcp` |
| `make release` | Stripped static binary |
| `make install` | `go install` → `$(go env GOPATH)/bin/tiny-go-mcp` |
### Smaller binaries (~1.8MB)
After `make release`, optionally pack with [UPX](https://upx.github.io/):
```bash
upx --best --lzma tiny-go-mcp
```
---
## Project structure
```
tinymcp/ # Library package
cmd/tiny-go-mcp/ # Reference MCP server
template/ # gonew stdio scaffold
template-http/ # gonew streamable HTTP deploy scaffold
examples/minimal/ # Minimal stdio example
examples/http/ # Streamable HTTP example
examples/http-deploy/ # Deployable HTTP + Smithery URL listing (server card, Render/Fly)
examples/resources/ # Resources + prompts example
examples/mcp-client-config.json # Cursor/Claude-style template
scripts/lint-tools/ # MCP tool description linter (make lint-tools)
docs/ # Guides — see below
server.json # MCP Registry metadata (publish with mcp-publisher)
CHANGELOG.md # Release history
SYSTEM_PROMPT.md # Agent-facing API summary for codegen
.github/workflows/ # CI, lint, CodeQL, releases
```
Key docs in `docs/`:
| Doc | Purpose |
|-----|---------|
| [QUICKSTART.md](docs/QUICKSTART.md) | Step-by-step library setup |
| [HTTP.md](docs/HTTP.md) | stdio vs streamable HTTP vs legacy SSE |
| [STABILITY.md](docs/STABILITY.md) | Public API stability policy |
| [MIGRATION-v1.2.md](docs/MIGRATION-v1.2.md) | Upgrade guide from v1.1.x |
| [TLS.md](docs/TLS.md) | HTTPS via reverse proxy or Go |
| [LOCALHOST-PROTECTION.md](docs/LOCALHOST-PROTECTION.md) | DNS rebinding security advisory |
| [DISCOVERY.md](docs/DISCOVERY.md) | Registries and visibility |
| [GLAMA.md](docs/GLAMA.md) | Glama hosting |
| [SMITHERY.md](docs/SMITHERY.md) | Smithery URL and MCPB listings |
---
## Releases
Tag 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).
```bash
git tag v1.2.0
git push origin v1.2.0
```
## Discovery and registries
See [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).
## Contributing
See [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.
## License
MIT — see [LICENSE](LICENSE).