e071084ebe
govulncheck / govulncheck (push) Has been cancelled
Lint / golangci-lint (push) Has been cancelled
Run Tests / Unit Tests (push) Has been cancelled
Run Tests / Etcd Integration Tests (push) Has been cancelled
Harness (E2E) / Harnesses (mock LLM) (push) Has been cancelled
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Has been cancelled
236 lines
6.2 KiB
Markdown
236 lines
6.2 KiB
Markdown
---
|
|
layout: default
|
|
title: MCP Troubleshooting
|
|
---
|
|
|
|
# MCP Troubleshooting
|
|
|
|
Common issues when using the MCP gateway and AI agents with Go Micro services.
|
|
|
|
## Agent Can't Find My Tools
|
|
|
|
**Symptom:** Agent says "no tools available" or doesn't list your service endpoints.
|
|
|
|
**Check 1: Is the service registered?**
|
|
|
|
```bash
|
|
# 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?**
|
|
|
|
```bash
|
|
# 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.
|
|
|
|
## Tool Calls Return Errors
|
|
|
|
**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:
|
|
|
|
```go
|
|
// 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:
|
|
|
|
```go
|
|
// 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:
|
|
|
|
```go
|
|
mcp.Options{
|
|
RateLimit: &mcp.RateLimitConfig{
|
|
RequestsPerSecond: 100, // Increase if needed
|
|
Burst: 200,
|
|
},
|
|
}
|
|
```
|
|
|
|
## Agent Makes Bad Tool Calls
|
|
|
|
**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:
|
|
|
|
```go
|
|
// 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:
|
|
|
|
```go
|
|
type GetRequest struct {
|
|
ID string `json:"id" description:"User ID in UUID format"`
|
|
}
|
|
```
|
|
|
|
See the [Tool Descriptions Guide](tool-descriptions.md) for detailed best practices.
|
|
|
|
## WebSocket Connection Drops
|
|
|
|
**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:
|
|
|
|
```nginx
|
|
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.
|
|
|
|
## Claude Code Can't Connect
|
|
|
|
**Symptom:** Claude Code doesn't see your MCP tools after configuring the server.
|
|
|
|
**Check 1: Test stdio transport manually**
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"my-services": {
|
|
"command": "micro",
|
|
"args": ["mcp", "serve"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Common mistakes:
|
|
- Wrong path to `micro` binary (use absolute path if needed)
|
|
- Missing `"serve"` in args
|
|
- Service not running when Claude Code starts
|
|
|
|
**Check 3: Check micro is in PATH**
|
|
|
|
```bash
|
|
which micro
|
|
```
|
|
|
|
If not found, use the full path in your config:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"my-services": {
|
|
"command": "/usr/local/bin/micro",
|
|
"args": ["mcp", "serve"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## OpenTelemetry Traces Missing
|
|
|
|
**Symptom:** MCP gateway calls aren't showing up in your trace collector.
|
|
|
|
The gateway only creates real spans when a `TraceProvider` is configured:
|
|
|
|
```go
|
|
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.
|
|
|
|
## Audit Logs Not Appearing
|
|
|
|
**Symptom:** No audit records despite tool calls succeeding.
|
|
|
|
Audit logging requires an explicit callback:
|
|
|
|
```go
|
|
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.
|
|
|
|
## Performance Issues
|
|
|
|
**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.
|
|
|
|
## Still Stuck?
|
|
|
|
- Check the [MCP Documentation](../../mcp.md) for full API reference
|
|
- Search [GitHub Issues](https://github.com/micro/go-micro/issues) for similar problems
|
|
- Ask in [GitHub Discussions](https://github.com/micro/go-micro/discussions)
|