O Model Context Protocol (MCP) esta transformando a forma como aplicacoes se conectam a modelos de IA. Criado pela Anthropic e agora sob governanca da Linux Foundation, o MCP define um padrao aberto para que LLMs acessem ferramentas, dados e recursos externos de forma estruturada. Com o lancamento do SDK oficial em Go – mantido em colaboracao com o Google – a linguagem ganha um papel central nesse ecossistema.
Se voce ja construiu APIs REST em Go ou microsservicos com gRPC, criar servidores MCP vai parecer natural. A arquitetura segue o mesmo padrao idiomatico que torna Go tao produtivo para backend.
O que e o Model Context Protocol
MCP e um protocolo que padroniza como assistentes de IA (Claude, ChatGPT, Gemini) se comunicam com servicos externos. Em vez de cada integracao ser um caso especial, o MCP define tres primitivas:
- Tools – funcoes que o modelo pode chamar (consultar banco de dados, enviar email, executar codigo)
- Resources – dados que o modelo pode ler (arquivos, documentos, configuracoes)
- Prompts – templates de instrucoes reutilizaveis
O protocolo usa JSON-RPC 2.0 sobre diferentes transportes: stdio (para CLIs), SSE (Server-Sent Events) e HTTP streamable.
Instalando o SDK Oficial
O SDK oficial vive em github.com/modelcontextprotocol/go-sdk. Para adicionar ao seu projeto:
go get github.com/modelcontextprotocol/go-sdk@latest
O pacote principal e mcp, que define as APIs para servidores e clientes. A arquitetura segue o padrao da standard library – similar a net/http – com tipos Server e Client como cidadaos de primeira classe.
Se voce usa Go modules, o SDK se integra sem atrito ao seu workflow existente.
Criando seu Primeiro Servidor MCP
Vamos construir um servidor MCP que expoe ferramentas uteis para um assistente de IA. O exemplo implementa uma tool que consulta informacoes sobre repositorios Go:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
func main() {
// Cria o servidor MCP
server := mcp.NewServer(
"go-tools",
"1.0.0",
mcp.WithDescription("Ferramentas Go para assistentes de IA"),
)
// Registra uma tool
server.AddTool(
mcp.NewTool(
"analisar_modulo",
"Analisa um modulo Go e retorna informacoes sobre dependencias",
mcp.Input(
mcp.Property("modulo", mcp.String(), "Nome do modulo Go (ex: github.com/gin-gonic/gin)"),
mcp.Required("modulo"),
),
),
analisarModuloHandler,
)
// Executa sobre stdio
transport := mcp.NewStdioTransport()
if err := server.Run(context.Background(), transport); err != nil {
log.Fatal(err)
}
}
func analisarModuloHandler(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
modulo := req.Params.Arguments["modulo"].(string)
info := fmt.Sprintf(
"Modulo: %s\nStatus: disponivel no pkg.go.dev\nUse: go get %s",
modulo, modulo,
)
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent(info),
},
}, nil
}
O servidor recebe requisicoes JSON-RPC via stdin e responde via stdout. Qualquer cliente MCP compativel (Claude Desktop, Cursor, etc.) pode se conectar e usar a tool analisar_modulo.
Adicionando Resources
Resources permitem que o modelo leia dados estruturados. Vamos adicionar um resource que expoe a lista de dependencias do projeto atual:
server.AddResource(
mcp.NewResource(
"go://dependencias",
"Lista de dependencias do go.mod atual",
mcp.WithMIMEType("application/json"),
),
func(ctx context.Context, req mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
data, err := os.ReadFile("go.mod")
if err != nil {
return nil, fmt.Errorf("erro ao ler go.mod: %w", err)
}
return &mcp.ReadResourceResult{
Contents: []mcp.ResourceContents{
mcp.TextResourceContents(
"go://dependencias",
string(data),
"text/plain",
),
},
}, nil
},
)
Com isso, quando o assistente de IA precisa entender as dependencias do projeto, ele consulta o resource go://dependencias em vez de adivinhar. Esse padrao de tratamento de erros com wrapping usando fmt.Errorf com %w permite que erros sejam rastreados corretamente pela cadeia de chamadas.
Registrando Prompts Reutilizaveis
Prompts sao templates que guiam o comportamento do modelo. Por exemplo, um prompt para revisao de codigo Go:
server.AddPrompt(
mcp.NewPrompt(
"revisar_codigo_go",
"Revisa codigo Go seguindo boas praticas",
mcp.WithArgument("arquivo", "Caminho do arquivo Go a revisar"),
),
func(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
arquivo := req.Params.Arguments["arquivo"]
return &mcp.GetPromptResult{
Description: "Revisao de codigo Go",
Messages: []mcp.PromptMessage{
{
Role: mcp.User,
Content: mcp.TextContent(fmt.Sprintf(
`Revise o arquivo %s seguindo estas diretrizes:
1. Tratamento de erros idiomatico (sem panic em codigo de producao)
2. Nomenclatura seguindo convencoes Go (camelCase exportado, lowercase interno)
3. Uso correto de goroutines e channels
4. Interfaces pequenas e composiveis
5. Testes unitarios adequados`,
arquivo,
)),
},
},
}, nil
},
)
Servidor Completo com Multiplas Tools
Na pratica, um servidor MCP expoe varias ferramentas complementares. Aqui esta um exemplo mais robusto que combina analise de codigo com execucao de testes:
func registrarTools(server *mcp.Server) {
// Tool: executar testes
server.AddTool(
mcp.NewTool(
"executar_testes",
"Executa testes Go no diretorio especificado",
mcp.Input(
mcp.Property("diretorio", mcp.String(), "Diretorio dos testes (ex: ./...)"),
mcp.Property("verbose", mcp.Boolean(), "Saida detalhada"),
),
),
executarTestesHandler,
)
// Tool: verificar cobertura
server.AddTool(
mcp.NewTool(
"cobertura_testes",
"Retorna a cobertura de testes do projeto",
),
coberturaHandler,
)
// Tool: analisar performance
server.AddTool(
mcp.NewTool(
"benchmark",
"Executa benchmarks Go e retorna resultados",
mcp.Input(
mcp.Property("pacote", mcp.String(), "Pacote para benchmark"),
mcp.Property("tempo", mcp.String(), "Duracao do benchmark (ex: 5s)"),
),
),
benchmarkHandler,
)
}
func executarTestesHandler(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
dir := "./..."
if d, ok := req.Params.Arguments["diretorio"].(string); ok {
dir = d
}
args := []string{"test", dir}
if v, ok := req.Params.Arguments["verbose"].(bool); ok && v {
args = append(args, "-v")
}
cmd := exec.CommandContext(ctx, "go", args...)
output, err := cmd.CombinedOutput()
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent(fmt.Sprintf("Testes falharam:\n%s", output)),
},
IsError: true,
}, nil
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent(string(output)),
},
}, nil
}
Observe como o handler retorna IsError: true em vez de retornar um erro Go – isso sinaliza ao modelo que a tool executou mas o resultado indica falha, permitindo que o assistente trate o problema. Esse padrao e diferente de retornar error, que indicaria falha no proprio servidor MCP.
Usando Concorrencia no Servidor MCP
Go brilha quando o servidor MCP precisa processar multiplas requisicoes simultaneamente. Cada chamada de tool ja roda em sua propria goroutine pelo SDK, mas voce pode usar padroes de concorrencia dentro dos handlers:
func analisarProjetoHandler(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
type resultado struct {
nome string
dados string
err error
}
analises := []string{"lint", "vet", "test"}
ch := make(chan resultado, len(analises))
for _, a := range analises {
go func(nome string) {
cmd := exec.CommandContext(ctx, "go", nome, "./...")
out, err := cmd.CombinedOutput()
ch <- resultado{nome: nome, dados: string(out), err: err}
}(a)
}
var relatorio strings.Builder
for range analises {
r := <-ch
if r.err != nil {
relatorio.WriteString(fmt.Sprintf("[%s] FALHOU:\n%s\n", r.nome, r.dados))
} else {
relatorio.WriteString(fmt.Sprintf("[%s] OK\n", r.nome))
}
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent(relatorio.String()),
},
}, nil
}
O uso de context garante que, se o cliente cancelar a requisicao, todas as goroutines filhas sao encerradas corretamente.
Configurando no Claude Desktop
Para usar seu servidor MCP com o Claude Desktop, adicione ao arquivo de configuracao:
{
"mcpServers": {
"go-tools": {
"command": "go",
"args": ["run", "./cmd/mcp-server"],
"env": {
"GOPATH": "/home/dev/go"
}
}
}
}
Para distribuir o servidor como binario, use goreleaser ou go build com cross-compilation para gerar executaveis para todas as plataformas.
Testando Servidores MCP
Testar servidores MCP em Go segue os mesmos principios de testes em Go. O SDK fornece helpers para simular o transporte:
func TestAnalisarModulo(t *testing.T) {
server := mcp.NewServer("test", "1.0.0")
server.AddTool(
mcp.NewTool("analisar_modulo", "Analisa modulo"),
analisarModuloHandler,
)
// Cria cliente de teste conectado ao servidor
client, cleanup := mcp.NewTestClient(t, server)
defer cleanup()
// Chama a tool
result, err := client.CallTool(context.Background(), "analisar_modulo", map[string]any{
"modulo": "github.com/gin-gonic/gin",
})
if err != nil {
t.Fatal(err)
}
if len(result.Content) == 0 {
t.Fatal("resultado vazio")
}
}
Usar fuzzing nativo do Go tambem e recomendado para testar a robustez dos handlers contra inputs inesperados.
MCP vs API REST: Quando Usar Cada Um
| Aspecto | API REST | MCP |
|---|---|---|
| Protocolo | HTTP/JSON | JSON-RPC 2.0 |
| Consumidor principal | Aplicacoes | Modelos de IA |
| Descoberta | OpenAPI/Swagger | Automatica pelo protocolo |
| Autenticacao | OAuth, JWT, API keys | OAuth (em desenvolvimento) |
| Transporte | HTTP | stdio, SSE, HTTP |
| Estado | Stateless por padrao | Sessao persistente |
Para APIs consumidas por humanos e aplicacoes tradicionais, REST continua sendo o padrao. MCP e especifico para a comunicacao entre assistentes de IA e ferramentas – e os dois podem coexistir no mesmo projeto.
Proximos Passos
O ecossistema MCP em Go esta crescendo rapidamente. Alem do SDK oficial, existem alternativas da comunidade como mcp-go para quem precisa de transportes HTTP e SSE avancados. Considere tambem explorar observabilidade para monitorar seus servidores MCP em producao e Docker para containerizar o deploy.
Com Go e MCP, voce pode transformar qualquer sistema existente em uma ferramenta acessivel por assistentes de IA – sem reescrever codigo, sem mudar de linguagem, e com a performance e confiabilidade que Go oferece. Para tratamento de erros robusto nos seus handlers MCP, veja como usar errors.AsType do Go 1.26 para inspecao type-safe. Para projetos que tambem envolvem frontend, veja como Go e HTMX podem complementar sua arquitetura.
FAQ
O que e o Model Context Protocol (MCP)? MCP e um protocolo aberto criado pela Anthropic, agora sob a Linux Foundation, que padroniza como modelos de IA se conectam a ferramentas e dados externos. Ele define tres primitivas: tools (funcoes), resources (dados) e prompts (templates).
Preciso saber sobre IA para usar o MCP SDK em Go? Nao. Criar um servidor MCP e essencialmente criar um backend que expoe funcionalidades via JSON-RPC. Se voce sabe construir APIs em Go, ja tem todo o conhecimento necessario.
Qual a diferenca entre o SDK oficial e o mcp-go da comunidade?
O SDK oficial (modelcontextprotocol/go-sdk) e mantido em colaboracao com o Google e foca em conformidade total com a spec. O mcp-go (mark3labs/mcp-go) oferece transportes HTTP e SSE adicionais e uma API mais simplificada para casos de uso comuns.
Posso usar MCP em producao?
Sim, mas o SDK ainda esta em desenvolvimento ativo. Para producao, fixe a versao no go.mod e acompanhe o changelog do repositorio oficial para breaking changes.
Como depurar um servidor MCP? Use slog para logging estruturado dentro dos handlers. O SDK tambem suporta o MCP Inspector, uma ferramenta de depuracao que permite testar tools e resources interativamente.