GoMCP
GoMCP
Go로 MCP 서버를 구축하는 빠르고 관용적인 방법입니다.
🚀 빠른 링크
MCP 프로토콜: https://modelcontextprotocol.io
Related MCP server: Filesystem MCP Server
🎯 GoMCP란 무엇인가요?
GoMCP는 단순한 SDK가 아닌, Model Context Protocol (MCP) 서버를 구축하기 위한 프레임워크입니다. **"MCP를 위한 Gin"**이라고 생각하시면 됩니다.
MCP는 AI 애플리케이션(Claude Desktop, Cursor, Kiro, VS Code Copilot)이 외부 도구를 호출하고, 데이터 소스를 읽고, 프롬프트 템플릿을 사용할 수 있게 해주는 개방형 프로토콜입니다. GoMCP를 사용하면 이러한 서버를 매우 쉽게 구축할 수 있습니다.
왜 GoMCP인가요?
mcp-go (mark3labs) | 공식 Go SDK | GoMCP | |
수준 | SDK | SDK | 프레임워크 |
스키마 생성 | 수동 |
| |
미들웨어 | 기본 훅 | 없음 | 전체 체인 (로거, 인증, 속도 제한, OTel 등) |
도구 그룹 | 없음 | 없음 | |
Gin 라우트 가져오기 | 없음 | 없음 | ✅ 한 줄 |
OpenAPI/Swagger 가져오기 | 없음 | 없음 | ✅ 한 줄 |
gRPC 서비스 가져오기 | 없음 | 없음 | ✅ |
내장 인증 | 없음 | 없음 | Bearer, API Key, Basic + RBAC |
인스펙터 UI | 없음 | 없음 | ✅ |
테스트 유틸리티 | 기본 | 없음 | mcptest 패키지 |
🛠️ 기술 스택
환경 요구 사항
요구 사항 | 버전 |
Go | ≥ 1.25 |
MCP 프로토콜 | 2024-11-05 (2025-11-25와 하위 호환) |
핵심 의존성
기술 | 설명 |
Go 표준 라이브러리 | 핵심 프레임워크 — 외부 의존성 없음 |
Gin | 어댑터 전용 — 기존 Gin 라우트 가져오기 |
gRPC | 어댑터 전용 — gRPC 서비스 가져오기 |
OpenTelemetry | 선택 사항 — 분산 추적 |
YAML v3 | 제공자 전용 — 도구 정의 핫 리로드 |
🌟 핵심 기능
🔧 도구 개발
구조체 태그 자동 스키마 — Go 구조체와
mcp태그로 매개변수를 정의하면 JSON 스키마가 자동으로 생성됩니다.타입 지정 핸들러 —
func(*Context, Input) (Output, error)— 수동 매개변수 파싱이 필요 없습니다.매개변수 검증 — 필수, 최소/최대, 열거형, 패턴 — 핸들러 실행 전에 검증됩니다.
컴포넌트 버전 관리 — 여러 버전을 등록하고 클라이언트가
name@version으로 호출할 수 있습니다.비동기 작업 — 오래 걸리는 도구는 작업 ID를 반환하며, 폴링 및 취소를 지원합니다.
🔌 어댑터 (핵심 차별점)
Gin 어댑터 — 기존 Gin 라우트를 한 줄로 MCP 도구로 가져옵니다.
OpenAPI 어댑터 — Swagger/OpenAPI 3.x 문서에서 도구를 생성합니다.
gRPC 어댑터 — gRPC 서비스 메서드를 MCP 도구로 가져옵니다.
🔐 보안
BearerAuth — JWT 토큰 검증
APIKeyAuth — 헤더를 통한 API 키 검증
BasicAuth — HTTP 기본 인증
RequireRole / RequirePermission — 도구 그룹에 대한 RBAC 권한 부여
🧩 프레임워크 기능
미들웨어 체인 — 로거, 복구, 요청 ID, 타임아웃, 속도 제한, OpenTelemetry
도구 그룹 — 접두사와 그룹 수준 미들웨어로 도구 구성
리소스 및 프롬프트 — URI 템플릿 및 매개변수화된 프롬프트를 포함한 전체 MCP 지원
자동 완성 — 프롬프트/리소스 인수에 대한 값 제안
🚀 프로덕션 준비 완료
다중 전송 — stdio (Claude Desktop, Cursor, Kiro) 및 SSE를 사용하는 스트리밍 가능 HTTP
MCP 인스펙터 — 도구 탐색 및 테스트를 위한 내장 웹 디버그 UI
핫 리로드 — 파일 감시를 통해 YAML 파일에서 도구 정의 로드
mcptest 패키지 — 스냅샷 지원을 포함한 단위 테스트용 인메모리 클라이언트
🏗️ 아키텍처
┌──────────────────────────────────────────────────────────────┐
│ 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 │
└──────────────────────────────────────────────────────────────┘프로젝트 구조
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📦 설치
go get github.com/zhangpanda/gomcp⚡ 빠른 시작
5줄로 작동하는 MCP 서버 만들기
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()
}SearchInput 구조체는 다음 JSON 스키마를 자동으로 생성합니다:
{
"type": "object",
"properties": {
"query": { "type": "string", "description": "Search keyword" },
"limit": { "type": "integer", "default": 10, "minimum": 1, "maximum": 100 }
},
"required": ["query"]
}잘못된 매개변수는 핸들러가 실행되기 전에 거부됩니다:
validation failed: query: required; limit: must be <= 100📖 사용 가이드
구조체 태그 참조
태그 | 타입 | 설명 | 예시 | |
| 플래그 | 필수 필드 |
| |
| 문자열 | 사람이 읽을 수 있는 설명 |
| |
| 임의 | 기본값 |
| |
| 숫자 | 최소값 (포함) |
| |
| 숫자 | 최대값 (포함) |
| |
| 문자열 | 파이프로 구분된 허용 값 | `mcp:"enum=asc | desc"` |
| 문자열 | 정규식 검증 |
|
조합: mcp:"required,desc=사용자 이메일,pattern=^[^@]+@[^@]+$"
지원 타입: string, int, float64, bool, []T, 중첩 구조체.
도구
간단한 핸들러:
s.Tool("hello", "Say hello", func(ctx *gomcp.Context) (*gomcp.CallToolResult, error) {
return ctx.Text("Hello, " + ctx.String("name")), nil
})타입 지정 핸들러 (권장):
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)
})리소스
// 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
})프롬프트
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
},
)미들웨어
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 auth사용자 정의 미들웨어:
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
}
}도구 그룹
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.delete어댑터
Gin — 기존 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 — Swagger 문서에서 생성:
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"},
})컴포넌트 버전 관리
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 version비동기 작업
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/cancel핫 리로드
s.LoadDir("./tools/", gomcp.DirOptions{Watch: true})MCP 인스펙터
s.Dev(":9090") // http://localhost:9090 — browse and test all tools테스트
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)
}전송 방식
s.Stdio() // Claude Desktop, Cursor, Kiro
s.HTTP(":8080") // Remote deployment with SSE
s.Handler() // Embed in existing HTTP serverAI 클라이언트와 함께 사용
{
"mcpServers": {
"my-server": {
"command": "/path/to/your/binary"
}
}
}Claude Desktop, Cursor, Kiro, Windsurf, VS Code Copilot 및 모든 MCP 호환 클라이언트와 작동합니다.
📋 로드맵
[x] 핵심: 전체 MCP 프로토콜 지원을 포함한 도구, 리소스, 프롬프트
[x] 구조체 태그 자동 스키마 생성 + 매개변수 검증
[x] 미들웨어 체인 (로거, 복구, 속도 제한, 타임아웃, 요청 ID)
[x] 인증 미들웨어 (Bearer / API Key / Basic) + RBAC 권한 부여
[x] 접두사 명명 및 중첩 그룹을 지원하는 도구 그룹
[x] stdio + SSE 알림을 포함한 스트리밍 가능 HTTP 전송
[x] Gin 어댑터 — 기존 Gin 라우트를 MCP 도구로 가져오기
[x] OpenAPI 어댑터 — Swagger/OpenAPI 문서에서 도구 생성
[x] gRPC 어댑터 — gRPC 서비스를 MCP 도구로 가져오기
[x] OpenTelemetry 통합
[x] 스냅샷 테스트를 포함한 mcptest 패키지
[x] 컴포넌트 버전 관리 + 폐기(deprecation) 지원
[x] 폴링 및 취소를 지원하는 비동기 작업
[x] MCP 인스펙터 웹 디버그 UI
[x] YAML에서 로드하는 핫 리로드 제공자
[x] 프롬프트/리소스 인수에 대한 자동 완성
[ ] MCP 클라이언트 지원 (서버 간 호출)
🤝 피드백 및 지원
버그 리포트: GitHub Issues
기능 요청: GitHub Issues
💡 추천 읽기: 질문을 스마트하게 하는 방법
⚖️ 저작권 및 라이선스
Copyright © 2026 GoMCP Contributors
Apache License 2.0에 따라 라이선스가 부여됩니다.
중요 참고 사항
이 프로젝트는 Apache 2.0 라이선스에 따라 개인 및 상업적 용도로 오픈 소스이며 무료입니다.
소프트웨어의 모든 사본 또는 상당 부분에 저작권 고지, 라이선스 텍스트 및 모든 귀속 고지를 유지해야 합니다.
Apache 2.0 라이선스에는 기여자로부터 사용자에게 부여되는 명시적인 특허권 부여가 포함되어 있습니다.
이 프로젝트에 대한 기여는 동일한 Apache 2.0 라이선스에 따라 라이선스가 부여됩니다.
저작권 고지를 무단으로 제거할 경우 법적 조치가 취해질 수 있습니다.
특허 고지
이 프레임워크의 특정 기능(구조체 태그 스키마 생성, HTTP-to-MCP 자동 어댑터, OpenAPI-to-MCP 자동 어댑터)은 특허 출원 중인 주제입니다. Apache 2.0 라이선스는 귀하에게 이 소프트웨어의 일부로서 이러한 기능을 사용할 수 있는 영구적이고 전 세계적이며 로열티가 없는 특허 라이선스를 부여합니다.
⭐ Star History
GoMCP가 유용하다면 별을 눌러주세요! 다른 사람들이 프로젝트를 발견하는 데 도움이 됩니다.
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