|
1 | 1 | <!-- Autogenerated by weave; DO NOT EDIT --> |
2 | 2 | # Troubleshooting |
| 3 | + |
| 4 | +The Model Context Protocol is a complicated spec that leaves some room for |
| 5 | +interpretation. Client and server SDKs can behave differently, or can be more |
| 6 | +or less strict about their inputs. And of course, bugs happen. |
| 7 | + |
| 8 | +When you encounter a problem using the Go SDK, these instructions can help |
| 9 | +collect information that will be useful in debugging. Please try to provide |
| 10 | +this information in a bug report, so that maintainers can more quickly |
| 11 | +understand what's going wrong. |
| 12 | + |
| 13 | +And most of all, please do [file bugs](https://github.com/modelcontextprotocol/go-sdk/issues/new?template=bug_report.md). |
| 14 | + |
| 15 | +## Using the MCP inspector |
| 16 | + |
| 17 | +To debug an MCP server, you can use the [MCP |
| 18 | +inspector](https://modelcontextprotocol.io/legacy/tools/inspector). This is |
| 19 | +useful for testing your server and verifying that it works with the typescript |
| 20 | +SDK, as well as inspecting MCP traffic. |
| 21 | + |
| 22 | +## Collecting MCP logs |
| 23 | + |
| 24 | +For [stdio](protocol.md#stdio-transport) transport connections, you can also |
| 25 | +inspect MCP traffic using a `LoggingTransport`: |
| 26 | + |
| 27 | +```go |
| 28 | +func ExampleLoggingTransport() { |
| 29 | + ctx := context.Background() |
| 30 | + t1, t2 := mcp.NewInMemoryTransports() |
| 31 | + server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) |
| 32 | + if _, err := server.Connect(ctx, t1, nil); err != nil { |
| 33 | + log.Fatal(err) |
| 34 | + } |
| 35 | + |
| 36 | + client := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil) |
| 37 | + var b bytes.Buffer |
| 38 | + logTransport := &mcp.LoggingTransport{Transport: t2, Writer: &b} |
| 39 | + if _, err := client.Connect(ctx, logTransport, nil); err != nil { |
| 40 | + log.Fatal(err) |
| 41 | + } |
| 42 | + fmt.Println(b.String()) |
| 43 | + // Output: |
| 44 | + // write: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{"roots":{"listChanged":true}},"clientInfo":{"name":"client","version":"v0.0.1"},"protocolVersion":"2025-06-18"}} |
| 45 | + // read: {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"logging":{}},"protocolVersion":"2025-06-18","serverInfo":{"name":"server","version":"v0.0.1"}}} |
| 46 | + // write: {"jsonrpc":"2.0","method":"notifications/initialized","params":{}} |
| 47 | + |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +That example uses a `bytes.Buffer`, but you can also log to a file, or to |
| 52 | +`os.Stderr`. |
| 53 | + |
| 54 | +## Inspecting HTTP traffic |
| 55 | + |
| 56 | +There are a couple different ways to investigate traffic to an HTTP transport |
| 57 | +([streamable](protocol.md#streamable-transport) or legacy SSE). |
| 58 | + |
| 59 | +The first is to use an HTTP middleware: |
| 60 | + |
| 61 | +```go |
| 62 | +func ExampleStreamableHTTPHandler_httpMiddleware() { |
| 63 | + server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.1.0"}, nil) |
| 64 | + handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server { |
| 65 | + return server |
| 66 | + }, nil) |
| 67 | + loggingHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { |
| 68 | + // Example debugging; you could also capture the response. |
| 69 | + body, err := io.ReadAll(req.Body) |
| 70 | + if err != nil { |
| 71 | + log.Fatal(err) |
| 72 | + } |
| 73 | + req.Body.Close() // ignore error |
| 74 | + req.Body = io.NopCloser(bytes.NewBuffer(body)) |
| 75 | + fmt.Println(req.Method, string(body)) |
| 76 | + handler.ServeHTTP(w, req) |
| 77 | + }) |
| 78 | + httpServer := httptest.NewServer(loggingHandler) |
| 79 | + defer httpServer.Close() |
| 80 | + |
| 81 | + // The SDK is currently permissive of some missing keys in "params". |
| 82 | + mustPostMessage(`{"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {}}`, httpServer.URL) |
| 83 | + // Output: |
| 84 | + // POST {"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {}} |
| 85 | +} |
| 86 | +``` |
| 87 | + |
| 88 | +The second is to use a general purpose tool to inspect http traffic, such as |
| 89 | +[wireshark](https://www.wireshark.org/) or |
| 90 | +[tcpdump](https://linux.die.net/man/8/tcpdump). |
0 commit comments