Skip to content

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

Closed

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), maintained by Anthropic and the MCP community. It provides the core building blocks for both MCP clients and servers: transport types (stdio, streamable HTTP, SSE), session management, tool/resource/prompt registration, and type-safe protocol structs.

This is the most critical dependency in the project — it is the protocol layer that gh-aw-mcpg proxies between clients and backend MCP servers.

Current Usage in gh-aw

The SDK is used across 35 files with a single import alias sdk:

sdk "github.com/modelcontextprotocol/go-sdk/mcp"
  • Files: 35 (26 production + 9 test)
  • Import Count: 1 unique import path (/mcp subpackage)
  • Key APIs Used:
    • sdk.Client / sdk.NewClient — MCP client for connecting to backends
    • sdk.ClientSession / session.Connect() — session lifecycle
    • sdk.Server / sdk.NewServer — MCP server for exposing tools to clients
    • sdk.CommandTransport — stdio backend process communication
    • sdk.StreamableClientTransport — streamable HTTP (2025-03-26 spec)
    • sdk.SSEClientTransport — legacy SSE transport (2024-11-05 spec)
    • sdk.NewStreamableHTTPHandler — HTTP handler for serving MCP over streamable transport
    • sdk.NewInMemoryTransports — in-memory transport pair for unit tests
    • sdk.ErrSessionMissing — typed sentinel for session expiry detection
    • sdk.CallToolResult, sdk.CallToolRequest — tool invocation types
    • sdk.TextContent, sdk.ImageContent, sdk.AudioContent, sdk.EmbeddedResource — content types
    • sdk.Tool, sdk.Resource, sdk.Prompt — protocol entity types
    • sdk.ClientOptions / sdk.ServerOptions — with Logger and KeepAlive fields

Research Findings

Architecture Decisions

The project uses the SDK in a sophisticated proxy gateway pattern:

  • The gateway itself is an SDK server (exposing tools to upstream clients)
  • The gateway is also an SDK client (connecting to downstream MCP backends)
  • Multiple transport fallback strategies are implemented (streamable → SSE → plain JSON-RPC)

Notable Usage Patterns

Multi-transport fallback (NewHTTPConnection):

1. Try streamable HTTP (2025-03-26 spec)
2. Try SSE (2024-11-05 spec) with deprecation warning
3. Fall back to plain JSON-RPC HTTP

This is well-architected and spec-compliant.

Session reconnection with sdk.ErrSessionMissing:

if err != nil && isSessionNotFoundError(err) {
    // reconnect + retry once
}

Proper use of the typed sentinel added in v1.5.0.

MaxRetries sentinel on StreamableClientTransport:

MaxRetries: -1, // Disables SDK retry; gateway manages reconnection

Clever — prevents double-retry but depends on SDK internals verified per-version.

In-memory transports for testing:

serverTransport, clientTransport := sdk.NewInMemoryTransports()

Excellent — fast, deterministic, no I/O in unit tests.

Recent Updates

  • v1.6.1 (latest) vs v1.6.0 (in use) — one patch version behind; likely bug fixes
  • v1.6.0 added DisableStandaloneSSE on StreamableClientTransport (used correctly)
  • v1.5.0 added sdk.ErrSessionMissing (used correctly)

Improvement Opportunities

🏃 Quick Wins

  1. Bump to v1.6.1 — The project is one patch behind. There's an explicit comment in tool_registry.go that registerToolWithoutValidation must be re-verified on every SDK upgrade. A patch bump is low-risk and ensures the latest bug fixes.

    go get github.com/modelcontextprotocol/go-sdk@v1.6.1
    go mod tidy

    After bumping, re-verify the comment at tool_registry.go:53 still holds for v1.6.1.

  2. Add a version canary test for DisableStandaloneSSE — The project already has TestMaxRetriesSentinelCanary to guard against MaxRetries: -1 semantics changing. A similar canary for DisableStandaloneSSE field existence/behavior would prevent silent regressions on future upgrades.

✨ Feature Opportunities

  1. sdk.AddTool[In, Out] typed registration (selective use) — The project uses server.AddTool(tool, handler) everywhere to bypass schema validation (needed for draft-07 backend schemas). However, for internally-defined tools (e.g., DIFC sys tools registered directly by the gateway), using typed sdk.AddTool[In, Out](server, tool, handler) would provide compile-time type safety and auto-validation at no cost. The bypass is only needed for proxied backend tools.

  2. session.Ping() for proactive health checks — If the SDK ClientSession exposes a Ping() method, it could be used proactively to detect stale sessions before tool calls arrive, rather than discovering expiry at call time and reconnecting reactively.

📐 Best Practice Alignment

  1. Duplicate pagination guards — Both paginateAll (internal/mcp/pagination.go) and paginate (internal/testutil/mcptest/validator.go) implement pagination with loop protection. The comment says "keep loop-protection invariants aligned", but divergence could occur over time. Consider exporting paginateAll (or a shared util) for reuse in the validator to eliminate the duplication risk.

  2. JSON round-trip in callParamMethod — unmarshalParams does json.Marshal(params) + json.Unmarshal(...) for every method call. For plain JSON-RPC backends this chains: receive raw JSON → unmarshal to interface{} → re-marshal → unmarshal to typed struct. A future refactor could accept json.RawMessage directly to save one cycle.

🔧 General Improvements

  1. Content type extensibility — convertContentItem handles text, image, audio, resource. As the MCP spec evolves, new content types may appear (e.g., video). The default unknown-type fallback is graceful, but elevating the existing log warning to a structured metric/counter would improve observability for new content types in production.

  2. InitializeResult() nil guards — Both connection.go:ServerInfo() and validator.go:GetServerInfo() correctly guard for nil InitializeResult(). Adding a comment cross-referencing the SDK contract (nil before Connect completes) would improve future maintainability.

Module Summary

Field Value
Module github.com/modelcontextprotocol/go-sdk
Version v1.6.0
Repository https://github.com/modelcontextprotocol/go-sdk
Latest Release v1.6.1
Last Reviewed 2026-06-04

Key Features

  • Official MCP Go SDK from the MCP project
  • Supports stdio, streamable HTTP (2025-03-26), and SSE (2024-11-05) transports
  • Client + server in one package
  • In-memory transport pair for hermetic testing
  • Typed error sentinel ErrSessionMissing for session lifecycle
  • Typed generic AddTool[In, Out] for schema-validated tool registration
  • KeepAlive support via ClientOptions.KeepAlive
  • slog.Logger integration

References

Recommendations

  1. 🔴 [High] Bump go-sdk to v1.6.1 and re-verify registerToolWithoutValidation SDK behavior
  2. 🟡 [Medium] Use typed sdk.AddTool[In, Out] for internally-defined gateway tools (DIFC sys tools)
  3. 🟡 [Medium] Consolidate the two pagination helpers (paginateAll + paginate) to eliminate drift risk
  4. 🟢 [Low] Add a DisableStandaloneSSE behavior canary test alongside TestMaxRetriesSentinelCanary
  5. 🟢 [Low] Investigate session.Ping() availability for proactive session health checks
  6. 🟢 [Low] Consider direct json.RawMessage path in unmarshalParams to reduce marshal overhead

Next Steps

  • Run go get github.com/modelcontextprotocol/go-sdk@v1.6.1 && go mod tidy and verify tests pass
  • Audit tool_registry.go:53 comment validity against v1.6.1 SDK source
  • Check if typed AddTool[In, Out] could replace any registerToolWithoutValidation calls for DIFC sys tools

Generated by Go Fan 🐹 · Run §26940372029

Note

🔒 Integrity filter blocked 36 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 · sonnet46 2M · ◷

  • expires on Jun 11, 2026, 8:36 AM UTC

Activity

  1. github-actions commented on Jun 4, 2026

    @github-actions
    ContributorAuthor

    🤖 This is an automated response from Repo Assist.

    Good analysis from Go Fan. A few notes on the recommendations:

    Rec 1 (bump go-sdk to v1.6.1) — This is the clearest quick win. The existing comment at tool_registry.go:53 explicitly calls out the need to re-verify registerToolWithoutValidation on every SDK upgrade, so a patch bump is exactly the kind of change that should be done promptly with a targeted review of that function against the v1.6.1 source. Worth doing soon.

    Rec 4 (add DisableStandaloneSSE canary test) — The existing TestMaxRetriesSentinelCanary is a good pattern. A companion canary for DisableStandaloneSSE field existence would be a low-effort, high-value addition to prevent silent regressions on future upgrades.

    Rec 3 (consolidate paginateAll + paginate) — The loop-protection drift risk is real but low-frequency. Worth tracking as a future clean-up rather than rushing.

    Rec 6 (direct json.RawMessage in unmarshalParams) — Agreed this is a valid micro-optimisation for the hot path, but the current double-marshal approach is at least correct and obvious. Fine to defer.

    Recs 2 and 5 (typed AddTool[In, Out] for internal tools, session.Ping()) are more speculative — worth investigating but no urgency.

    The SDK bump (Rec 1) is the most actionable item here.

    Warning

    Firewall blocked 1 domain

    The following domain was blocked by the firewall during workflow execution:

    • proxy.golang.org

    To allow these domains, add them to the network.allowed list in your workflow frontmatter:

    network:
      allowed:
        - defaults
        - "proxy.golang.org"

    See Network Configuration for more information.

    Generated by Repo Assist · sonnet46 3.7M · ◷

    Add this agentic workflows to your repo

    To install this agentic workflow, run

    gh aw add githubnext/agentics/workflows/repo-assist.md@851905c06e905bf362a9f6cc54f912e3df747d55
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions