internal/website/docs/guides/troubleshooting.md
Common issues when using the MCP gateway and AI agents with Go Micro services.
Symptom: Agent says "no tools available" or doesn't list your service endpoints.
Check 1: Is the service registered?
# List registered services
micro services
If your service isn't listed, it hasn't registered with the registry. Make sure your service is running and using the same registry as the MCP gateway.
Check 2: Is the MCP gateway discovering services?
# List tools the gateway sees
curl http://localhost:3001/mcp/tools | jq
If empty, the gateway can't reach the registry. Verify both use the same registry address.
Check 3: Are you using the right port?
The MCP gateway runs on its own port (default :3001 with WithMCP), separate from the service RPC port. Make sure you're querying the MCP port, not the service port.
Symptom: Agent calls a tool but gets an error response.
"service not found"
The MCP gateway found the tool definition but can't reach the service. The service may have stopped since the gateway cached its tools. Restart the service and try again.
"method not found"
The handler method name doesn't match what the gateway expects. Ensure your handler is properly registered:
// Correct - registers all methods on the handler
service.Handle(new(MyHandler))
// Or with proto-generated code
pb.RegisterMyServiceHandler(service.Server(), handler.New())
"unauthorized" or "forbidden"
Auth scopes are configured but the agent's token doesn't have the required scope. Check your scope configuration:
// Gateway-side scopes
mcp.Options{
Scopes: map[string][]string{
"myservice.Users.Delete": {"users:admin"},
},
}
Verify the agent's bearer token includes the required scopes.
"rate limited"
The agent is making too many requests. Adjust rate limits:
mcp.Options{
RateLimit: &mcp.RateLimitConfig{
RequestsPerSecond: 100, // Increase if needed
Burst: 200,
},
}
Symptom: Agent calls tools with wrong parameters or misunderstands what a tool does.
This is almost always a documentation problem. Improve your handler doc comments:
// Bad - agent doesn't know what this does
func (s *Users) Get(ctx context.Context, req *GetRequest, rsp *GetResponse) error {
// Good - agent understands purpose, parameters, and format
// Get retrieves a user by their unique ID. Returns the full user profile
// including email, display name, and account status.
//
// @example {"id": "user-123"}
func (s *Users) Get(ctx context.Context, req *GetRequest, rsp *GetResponse) error {
Add description struct tags to your request/response types:
type GetRequest struct {
ID string `json:"id" description:"User ID in UUID format"`
}
See the Tool Descriptions Guide for detailed best practices.
Symptom: WebSocket connections to ws://localhost:3001/mcp/ws disconnect unexpectedly.
Check 1: Make sure your client sends periodic pings. The WebSocket transport expects heartbeats to detect stale connections.
Check 2: If running behind a reverse proxy (nginx, Caddy), ensure WebSocket upgrade headers are forwarded:
location /mcp/ws {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
Check 3: Check for connection limits. Each WebSocket connection is persistent. If you have many agents, you may need to increase file descriptor limits.
Symptom: Claude Code doesn't see your MCP tools after configuring the server.
Check 1: Test stdio transport manually
# This should start and wait for JSON-RPC input
micro mcp serve
If it errors, check that your services are running and the registry is accessible.
Check 2: Verify config syntax
In your Claude Code MCP settings:
{
"mcpServers": {
"my-services": {
"command": "micro",
"args": ["mcp", "serve"]
}
}
}
Common mistakes:
micro binary (use absolute path if needed)"serve" in argsCheck 3: Check micro is in PATH
which micro
If not found, use the full path in your config:
{
"mcpServers": {
"my-services": {
"command": "/usr/local/bin/micro",
"args": ["mcp", "serve"]
}
}
}
Symptom: MCP gateway calls aren't showing up in your trace collector.
The gateway only creates real spans when a TraceProvider is configured:
mcp.Options{
TraceProvider: otel.GetTracerProvider(),
}
Without this, noop spans are used (no traces exported). Make sure you've initialized the OpenTelemetry SDK before starting the gateway.
Symptom: No audit records despite tool calls succeeding.
Audit logging requires an explicit callback:
mcp.Options{
AuditFunc: func(r mcp.AuditRecord) {
log.Printf("[audit] tool=%s account=%s allowed=%t duration=%s",
r.Tool, r.AccountID, r.Allowed, r.Duration)
},
}
If AuditFunc is nil, no audit records are generated.
Symptom: MCP tool calls are slow.
Check 1: Network round-trips
Each MCP tool call makes an RPC call to the underlying service. If the service is on a different host, network latency applies. Use micro mcp test to measure raw latency.
Check 2: Service discovery caching
The gateway caches service/tool metadata. If you're seeing stale data, it's because of caching. The cache refreshes periodically based on registry TTL.
Check 3: Rate limiting
If rate limits are too low, requests queue up. Check your rate limit configuration.