GoMCP
This GoMCP server provides search, async reporting, and connectivity testing capabilities for AI applications like Claude Desktop, Cursor, and VS Code Copilot.
Keyword Search (
search@1.0): Full-text keyword search across indexed content, ranked by relevance score. Supports a configurable result limit (1–100, default 10).Semantic Search (
search@2.0): Embedding-based search that matches by intent rather than exact keywords, ranked by semantic similarity. Same limit options as keyword search.Document Search (
search.docs): Keyword search within documents, returning titles and content snippets with pagination support (1–100, default 10).Async Report Generation (
report): Generates analytics reports as a long-running async operation — returns a task ID immediately for polling viatasks/get.Hello / Connectivity Test (
hello): Greets a user by name (defaults to 'World') to verify basic server connectivity.
All search tools include built-in parameter validation (required query, constrained limit), and the versioned search tools demonstrate the server's ability to manage multiple tool versions simultaneously.
Allows importing existing Gin web framework routes as MCP tools with one line of code, enabling AI applications to interact with existing Gin-based APIs through the MCP protocol.
Provides access to the GoMCP framework repository hosted on Gitee, enabling developers to access the codebase and documentation through this Chinese Git hosting service.
Provides access to the GoMCP framework repository hosted on GitHub, enabling developers to access the codebase, releases, and documentation through the GitHub platform.
Provides distributed tracing capabilities through OpenTelemetry middleware, enabling observability and performance monitoring of MCP server operations.
Allows generating MCP tools from Swagger/OpenAPI 3.x documentation with one line of code, enabling AI applications to interact with existing REST APIs through the MCP protocol.
Provides hot-reload capabilities for tool definitions from YAML files with file watching, enabling dynamic configuration management of MCP tools without server restarts.
GoMCP
The fast, idiomatic way to build MCP servers in Go.
🚀 Quick Links
MCP Protocol: https://modelcontextprotocol.io
🎯 What is GoMCP?
GoMCP is a framework for building Model Context Protocol (MCP) servers — not just an SDK. Think of it as "Gin for MCP".
MCP is the open protocol that lets AI applications (Claude Desktop, Cursor, Kiro, VS Code Copilot) call external tools, read data sources, and use prompt templates. GoMCP makes building those servers trivial.
Why GoMCP?
mcp-go (mark3labs) | Official Go SDK | GoMCP | |
Level | SDK | SDK | Framework |
Schema generation | Manual |
| |
Middleware | Basic hooks | None | Full chain (Logger, Auth, RateLimit, OTel…) |
Tool groups | No | No | |
Import Gin routes | No | No | ✅ One line |
Import OpenAPI/Swagger | No | No | ✅ One line |
Import gRPC services | No | No | ✅ |
Built-in auth | No | No | Bearer, API Key, Basic + RBAC |
Inspector UI | No | No | ✅ |
Test utilities | Basic | No | mcptest package |
🛠️ Tech Stack
Environment Requirements
Requirement | Version |
Go | ≥ 1.25 |
MCP Protocol | 2024-11-05 (backward compatible with 2025-11-25) |
Core Dependencies
Technology | Description |
Go standard library | Core framework — zero external dependencies |
Gin | Adapter only — import existing Gin routes |
gRPC | Adapter only — import gRPC services |
OpenTelemetry | Optional — distributed tracing |
YAML v3 | Provider only — hot-reload tool definitions |
🌟 Core Features
🔧 Tool Development
Struct-tag auto schema — define parameters with Go structs and
mcptags, JSON Schema generated automaticallyTyped handlers —
func(*Context, Input) (Output, error)— no manual parameter parsingParameter validation — required, min/max, enum, pattern — checked before your handler runs
Component versioning — register multiple versions, clients call
name@versionAsync tasks — long-running tools return task ID, with polling and cancellation
🔌 Adapters (Core Differentiator)
Gin adapter — import existing Gin routes as MCP tools with one line
OpenAPI adapter — generate tools from Swagger/OpenAPI 3.x docs
gRPC adapter — import gRPC service methods as MCP tools
🔐 Security
BearerAuth — JWT token validation
APIKeyAuth — API key validation via header
BasicAuth — HTTP Basic authentication
RequireRole / RequirePermission — RBAC authorization on tool groups
🧩 Framework Features
Middleware chain — Logger, Recovery, RequestID, Timeout, RateLimit, OpenTelemetry
Tool groups — organize tools with prefixes and group-level middleware
Resource & Prompt — full MCP support including URI templates and parameterized prompts
Auto-completions — suggest values for prompt/resource arguments
🚀 Production Ready
Multiple transports — stdio (Claude Desktop, Cursor, Kiro) and Streamable HTTP with SSE
MCP Inspector — built-in web debug UI for browsing and testing tools
Hot-reload — load tool definitions from YAML files with file watching
mcptest package — in-memory client for unit testing with snapshot support
🏗️ Architecture
┌──────────────────────────────────────────────────────────────┐
│ User Code │
│ s.Tool() / s.ToolFunc() / s.Resource() / s.Prompt() │
├──────────────────────────────────────────────────────────────┤
│ Framework Core │
│ Router → Middleware Chain → Validation → Handler → Result │
├────────────┬─────────────┬───────────────┬───────────────────┤
│ Schema │ Validator │ Adapters │ Observability │
│ Generator │ Engine │ Gin/OpenAPI/ │ OTel / Logger │
│ (mcp tags) │ (auto) │ gRPC │ / Inspector │
├────────────┴─────────────┴───────────────┴───────────────────┤
│ Protocol Layer │
│ JSON-RPC 2.0 / MCP / Capability Negotiation │
├──────────────────────────────────────────────────────────────┤
│ Transport Layer │
│ stdio / Streamable HTTP + SSE │
└──────────────────────────────────────────────────────────────┘Project Structure
gomcp/
├── server.go # Server core, tool/resource/prompt registration
├── context.go # Request context with typed accessors
├── group.go # Tool groups with prefix naming
├── middleware.go # Middleware interface and chain execution
├── middleware_builtin.go # Logger, Recovery, RequestID, Timeout, RateLimit
├── middleware_auth.go # BearerAuth, APIKeyAuth, BasicAuth, RBAC
├── middleware_otel.go # OpenTelemetry tracing
├── schema/ # struct tag → JSON Schema generator + validator
├── transport/ # stdio + Streamable HTTP
├── adapter/ # Gin, OpenAPI, gRPC adapters
├── mcptest/ # Testing utilities
├── task.go # Async task support
├── completion.go # Auto-completions
├── inspector.go # Web debug UI
├── provider.go # Hot-reload from YAML
└── examples/ # Working examples📦 Installation
go get github.com/zhangpanda/gomcp⚡ Quick Start
5 lines to a working MCP server
package main
import (
"fmt"
"github.com/zhangpanda/gomcp"
)
type SearchInput struct {
Query string `json:"query" mcp:"required,desc=Search keyword"`
Limit int `json:"limit" mcp:"default=10,min=1,max=100"`
}
type SearchResult struct {
Items []string `json:"items"`
Total int `json:"total"`
}
func main() {
s := gomcp.New("my-server", "1.0.0")
s.ToolFunc("search", "Search documents by keyword", func(ctx *gomcp.Context, in SearchInput) (SearchResult, error) {
items := []string{fmt.Sprintf("Result for %q", in.Query)}
return SearchResult{Items: items, Total: len(items)}, nil
})
s.Stdio()
}The SearchInput struct automatically generates this JSON Schema:
{
"type": "object",
"properties": {
"query": { "type": "string", "description": "Search keyword" },
"limit": { "type": "integer", "default": 10, "minimum": 1, "maximum": 100 }
},
"required": ["query"]
}Invalid parameters are rejected before your handler runs:
validation failed: query: required; limit: must be <= 100📖 Usage Guide
Struct Tag Reference
Tag | Type | Description | Example |
| flag | Field must be provided |
|
| string | Human-readable description |
|
| any | Default value |
|
| number | Minimum value (inclusive) |
|
| number | Maximum value (inclusive) |
|
| string | Pipe-separated allowed values |
|
| string | Regex validation |
|
Combine: mcp:"required,desc=User email,pattern=^[^@]+@[^@]+$"
Supported types: string, int, float64, bool, []T, nested structs.
Tools
Simple handler:
s.Tool("hello", "Say hello", func(ctx *gomcp.Context) (*gomcp.CallToolResult, error) {
return ctx.Text("Hello, " + ctx.String("name")), nil
})Typed handler (recommended):
type Input struct {
Name string `json:"name" mcp:"required,desc=User name"`
Email string `json:"email" mcp:"required,pattern=^[^@]+@[^@]+$"`
}
s.ToolFunc("create_user", "Create user", func(ctx *gomcp.Context, in Input) (User, error) {
return db.CreateUser(in.Name, in.Email)
})Resources
// Static
s.Resource("config://app", "App config", func(ctx *gomcp.Context) (any, error) {
return map[string]any{"version": "1.0"}, nil
})
// Dynamic URI template
s.ResourceTemplate("db://{table}/{id}", "DB record", func(ctx *gomcp.Context) (any, error) {
return db.Find(ctx.String("table"), ctx.String("id")), nil
})Prompts
s.Prompt("code_review", "Code review",
[]gomcp.PromptArgument{gomcp.PromptArg("language", "Language", true)},
func(ctx *gomcp.Context) ([]gomcp.PromptMessage, error) {
return []gomcp.PromptMessage{
gomcp.UserMsg(fmt.Sprintf("Review this %s code for bugs.", ctx.String("language"))),
}, nil
},
)Middleware
s.Use(gomcp.Logger()) // Log tool name + duration
s.Use(gomcp.Recovery()) // Recover from panics
s.Use(gomcp.RequestID()) // Unique request ID
s.Use(gomcp.Timeout(10 * time.Second)) // Deadline enforcement
s.Use(gomcp.RateLimit(100)) // 100 calls/minute
s.Use(gomcp.OpenTelemetry()) // Distributed tracing
s.Use(gomcp.BearerAuth(tokenValidator)) // JWT auth
s.Use(gomcp.APIKeyAuth("X-API-Key", keyValidator)) // API key authCustom middleware:
func AuditLog() gomcp.Middleware {
return func(ctx *gomcp.Context, next func() error) error {
start := time.Now()
err := next()
log.Printf("tool=%s duration=%s err=%v", ctx.String("_tool_name"), time.Since(start), err)
return err
}
}Tool Groups
user := s.Group("user", authMiddleware)
user.Tool("get", "Get user", getUser) // → user.get
user.Tool("update", "Update user", updateUser) // → user.update
admin := user.Group("admin", gomcp.RequireRole("admin"))
admin.Tool("delete", "Delete user", deleteUser) // → user.admin.deleteAdapters
Gin — one line to import your existing API:
adapter.ImportGin(s, ginRouter, adapter.ImportOptions{
IncludePaths: []string{"/api/v1/"},
})
// GET /api/v1/users/:id → Tool get_api_v1_users_by_id (id = required param)OpenAPI — generate from Swagger docs:
adapter.ImportOpenAPI(s, "./swagger.yaml", adapter.OpenAPIOptions{
TagFilter: []string{"pets"},
ServerURL: "https://api.example.com",
})gRPC:
adapter.ImportGRPC(s, grpcConn, adapter.GRPCOptions{
Services: []string{"user.UserService"},
})Component Versioning
s.ToolFunc("search", "v1", searchV1, gomcp.Version("1.0"))
s.ToolFunc("search", "v2 with embeddings", searchV2, gomcp.Version("2.0"))
// "search" → latest, "search@1.0" → exact versionAsync Tasks
s.AsyncTool("report", "Generate report", func(ctx *gomcp.Context) (*gomcp.CallToolResult, error) {
// long-running work
return ctx.Text("done"), nil
})
// Client gets taskId immediately, polls tasks/get, can tasks/cancelHot-Reload
s.LoadDir("./tools/", gomcp.DirOptions{Watch: true})MCP Inspector
s.Dev(":9090") // http://localhost:9090 — browse and test all toolsTesting
func TestSearch(t *testing.T) {
c := mcptest.NewClient(t, setupServer())
c.Initialize()
result := c.CallTool("search", map[string]any{"query": "golang"})
result.AssertNoError(t)
result.AssertContains(t, "golang")
mcptest.MatchSnapshot(t, "search_result", result)
}Transports
s.Stdio() // Claude Desktop, Cursor, Kiro
s.HTTP(":8080") // Remote deployment with SSE
s.Handler() // Embed in existing HTTP serverUse with AI Clients
{
"mcpServers": {
"my-server": {
"command": "/path/to/your/binary"
}
}
}Works with Claude Desktop, Cursor, Kiro, Windsurf, VS Code Copilot, and any MCP-compatible client.
📋 Roadmap
Core: Tool, Resource, Prompt with full MCP protocol support
Struct-tag auto schema generation + parameter validation
Middleware chain (Logger, Recovery, RateLimit, Timeout, RequestID)
Auth middleware (Bearer / API Key / Basic) + RBAC authorization
Tool groups with prefix naming and nested groups
stdio + Streamable HTTP transports with SSE notifications
Gin adapter — import existing Gin routes as MCP tools
OpenAPI adapter — generate tools from Swagger/OpenAPI docs
gRPC adapter — import gRPC services as MCP tools
OpenTelemetry integration
mcptest package with snapshot testing
Component versioning + deprecation
Async tasks with polling and cancellation
MCP Inspector web debug UI
Hot-reload provider from YAML
Auto-completions for prompt/resource arguments
MCP Client support (server-to-server calls)
🤝 Feedback & Support
Bug Reports: GitHub Issues
Feature Requests: GitHub Issues
Discussions: GitHub Discussions
💡 Recommended reading: How To Ask Questions The Smart Way
⚖️ Copyright & License
Copyright © 2026 GoMCP Contributors
Licensed under the Apache License 2.0.
Important Notes
This project is open source and free for both personal and commercial use under the Apache 2.0 license.
You must retain the copyright notice, license text, and any attribution notices in all copies or substantial portions of the software.
The Apache 2.0 license includes an express grant of patent rights from contributors to users.
Contributions to this project are licensed under the same Apache 2.0 license.
Unauthorized removal of copyright notices may result in legal action.
Patent Notice
Certain features of this framework (struct-tag schema generation, HTTP-to-MCP automatic adapter, OpenAPI-to-MCP automatic adapter) are the subject of pending patent applications. The Apache 2.0 license grants you a perpetual, worldwide, royalty-free patent license to use these features as part of this software.
⭐ Star History
If you find GoMCP useful, please consider giving it a star! It helps others discover the project.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/zhangpanda/gomcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server