Skip to content

[go-fan] Go Module Review: modelcontextprotocol/go-sdk #3054

@github-actions

Description

@github-actions

🐹 Go Fan Report: modelcontextprotocol/go-sdk

Module Overview

github.com/modelcontextprotocol/go-sdk is the official Go SDK for the Model Context Protocol (MCP). It provides production-ready client and server implementations covering the full MCP spec, including stdio, SSE, and Streamable HTTP transports. For gh-aw-mcpg, this is the foundational dependency — the entire gateway is built on top of it.


Current Usage in gh-aw

The SDK is used pervasively across 12 production files and 9 test/utility files.

  • Files (production): internal/mcp/connection.go, internal/mcp/tool_result.go, internal/mcp/http_transport.go, internal/server/unified.go, internal/server/routed.go, internal/server/transport.go, internal/server/tool_registry.go, internal/middleware/jqschema.go
  • Files (test utils): internal/testutil/mcptest/ (5 files), internal/server/*_test.go, internal/middleware/*_test.go, test/integration/
  • Import alias: sdk "github.com/modelcontextprotocol/go-sdk/mcp" (consistent across all files ✅)

Key APIs Used

API Where Purpose
sdk.NewServer unified.go, routed.go, mcptest/server.go Create MCP server instances
sdk.NewClient http_transport.go, mcptest/validator.go Create backend client connections
sdk.Server.AddTool tool_registry.go, routed.go Register tools (method form, bypasses schema validation)
sdk.NewStreamableHTTPHandler transport.go, routed.go HTTP handler for Streamable HTTP transport
sdk.StreamableHTTPOptions transport.go, routed.go Configure stateful sessions, logger, 2h timeout
sdk.CommandTransport connection.go, mcptest/driver.go Stdio transport for Docker containers
sdk.StreamableClientTransport connection.go, http_transport.go HTTP client transport to backends
sdk.SSEClientTransport connection.go, http_transport.go SSE transport to legacy backends
sdk.NewInMemoryTransports mcptest/driver.go In-memory transport for tests
sdk.CallToolRequest/Result tool_registry.go, unified.go, middleware/ Tool invocation types
sdk.Content, sdk.TextContent, etc. tool_result.go, unified.go, middleware/ MCP content types
sdk.ToolAnnotations tool_registry.go, unified.go Tool metadata passthrough

Notable Usage Patterns

  1. Server-side (gateway): sdk.NewServer creates the unified aggregator; backends' tools are registered with prefixed names (serverID___toolName) via server.AddTool — the method form (not the sdk.AddTool function) to bypass JSON Schema validation and support draft-07 schemas from backends.

  2. Client-side (backend connections): sdk.NewClient + sdk.ClientSession connect to backend MCP servers over stdio, Streamable HTTP, or SSE.

  3. Routed mode filtered servers: A custom filteredServerCache maintains per-session *sdk.Server instances with a TTL, allowing guard-filtered tool sets per session.

  4. SDK logging integration: logger.NewSlogLoggerWithHandler(log) is passed as sdk.StreamableHTTPOptions.Logger — correctly bridges SDK's slog-based logging into the project's structured logger.

  5. In-memory testing: sdk.NewInMemoryTransports() is used in mcptest/driver.go for fast, deterministic unit testing without real Docker containers.


Research Findings

Key Features Available in the SDK

  • Dual role: Same SDK handles both the server (gateway) and client (backend connection) sides
  • Transport abstraction: CommandTransport, StreamableClientTransport, SSEClientTransport, InMemoryTransport — all used by the project
  • Schema validation control: sdk.AddTool validates schemas; server.AddTool does not — project exploits this intentionally
  • Stateful session management: StreamableHTTPOptions.Stateless=false + SessionTimeout properly support long-running agentic sessions
  • Pagination: ClientSession.ListTools, ListResources, ListPrompts all support cursor-based pagination — project uses these via paginateAll

Recent Updates (observed from SDK versioning)

  • SDK is in rapid iteration (v1.4.1) alongside the MCP specification evolution
  • Streamable HTTP transport is the primary recommended transport (spec 2025-03-26+)

Improvement Opportunities

🏃 Quick Wins

  1. Centralize the server.AddTool bypass pattern: The workaround is duplicated in tool_registry.go and routed.go with a long comment explaining why. Extract a helper registerToolWithoutValidation(server, tool, handler) to reduce comment duplication and make the intent clearer.

  2. ParseToolArguments consistency: mcptest/server.go re-implements json.Unmarshal(req.Params.Arguments, &args) inline (not using mcp.ParseToolArguments). Standardize on the helper to keep argument parsing consistent.

  3. Error result constructor: newErrorCallToolResult(err) exists in unified.go but isn't exported. If mcptest or other packages need to create error results, they duplicate the pattern. Consider exporting it from the mcp package.

✨ Feature Opportunities

  1. Expand in-memory transport usage in integration tests: sdk.NewInMemoryTransports() is already in mcptest/driver.go but the more complex integration tests in server/*_integration_test.go spin up real servers. More test coverage with in-memory transports would be faster and wouldn't require Docker.

  2. SDK resources/prompts via the gateway: The project uses ClientSession.ListResources, ListPrompts, ReadResource, and GetPrompt on the client side (to query backends) but doesn't expose these through the gateway's MCP server. As the SDK matures and resources/prompts become more prominent in MCP workflows, consider proxying them through the gateway.

  3. Session context enrichment: The SDK passes context through all handlers. If future SDK versions add session metadata to context (e.g., client capabilities, initialization params), the project could leverage this to simplify us.getSessionID(ctx) and related patterns.

📐 Best Practice Alignment

  1. Schema validation bypass is well-documented ✅ — Comments explain the server.AddTool vs sdk.AddTool choice. Monitor SDK releases for configurable validation that natively handles draft-07 schemas from backends.

  2. SessionTimeout: 2*time.Hour — Good choice for long-running agentic workflows. This should ideally be a configurable value (via config file or environment variable) rather than a hard-coded constant. Adding MCP_GATEWAY_SESSION_TIMEOUT support would give operators control.

  3. Slog logger integration ✅ — logger.NewSlogLoggerWithHandler passed to StreamableHTTPOptions.Logger is the correct idiomatic pattern.

  4. Transport selection ✅ — The project correctly negotiates transport type (Streamable HTTP preferred → SSE fallback → plain JSON) per the MCP spec evolution.

🔧 General Improvements

  1. filteredServerCache TTL: The per-session *sdk.Server cache in routed mode uses lazy eviction. This is correct but could grow unbounded if many unique sessions are created in quick succession. Consider adding a background sweeper goroutine or a max-size limit.

  2. ConvertToCallToolResult complexity: The function in mcp/tool_result.go has 4 distinct parsing paths (array, empty-content-field, missing-content-field, standard). This complexity exists to handle diverse backend behaviors. Adding table-driven unit tests for all paths would improve confidence during SDK upgrades.


Recommendations

  1. [Low effort] Extract registerToolWithoutValidation helper to deduplicate the server.AddTool bypass pattern and its comment (appears in 2 files).
  2. [Low effort] Use mcp.ParseToolArguments in mcptest/server.go instead of inline json.Unmarshal.
  3. [Medium effort] Make SessionTimeout configurable via env var (MCP_GATEWAY_SESSION_TIMEOUT) with the current 2h as default.
  4. [Medium effort] Add more in-memory transport tests to reduce Docker dependency in integration test suite.
  5. [Medium effort] Add a max-size or background sweeper to filteredServerCache in routed.go.
  6. [Future] Watch SDK releases for native draft-07 schema support to remove the server.AddTool bypass.
  7. [Future] Evaluate proxying MCP resources and prompts through the gateway as SDK/spec support matures.

Next Steps


Generated by Go Fan 🐹
Module summary: specs/mods/go-sdk.md (directory creation restricted in this workflow run)
Run: §23889513585

References:

Note

🔒 Integrity filter blocked 15 items

The following items were blocked because they don't meet the GitHub integrity level.

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by Go Fan ·

  • expires on Apr 9, 2026, 7:41 AM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions