Skip to content

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

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, maintained in collaboration with Google (~4.8k ⭐, pushed today β€” the single most recently updated direct dependency in go.mod). It's foundational to gh-aw: it powers the built-in gh aw mcp server that exposes gh-aw's own tools, and the mcp-inspect client that probes external MCP servers declared in workflows.

Current Usage in gh-aw

  • Files: 11 non-test files (pkg/cli/mcp_*.go, pkg/parser/mcp.go)
  • Import surface: .../go-sdk/mcp and .../go-sdk/jsonrpc
  • Version: v1.6.1 (stable); v1.7.0-pre.2 is available as a pre-release
  • Key APIs Used: NewServer + ServerCapabilities/ToolCapabilities, generic AddTool[In,Out] with typed *Args structs, ToolAnnotations, Icon, AddReceivingMiddleware, NewStreamableHTTPHandler + StreamableHTTPOptions, NewClient, CommandTransport, StreamableClientTransport{DisableStandaloneSSE}, Session.NotifyProgress, jsonrpc.Error codes

The usage is genuinely exemplary and modern β€” per-request ctx.Done() cancellation checks, a receiving middleware that rewrites raw additionalProperties schema errors into "Did you mean?" hints with a reflection-derived param registry (no manual list to keep in sync), best-effort progress notifications guarded on session + token, loopback-only HTTP bind with DNS-rebinding protection left on, and Go 1.26 new(true) for *bool fields. πŸŽ‰

Research Findings

Recent Updates

  • v1.6.0: cross-origin protection no longer on by default (opt-in enableoriginverification MCPGODEBUG); SetError now preserves existing Content; ClientCredentialsHandler OAuth grant; keepalive race fix.
  • v1.6.1: MCPGODEBUG=disablecontenttypecheck=1 escape hatch for the POST Content-Type check.
  • v1.7.0-pre.2 (targets protocol 2026-07-28): request body size limit / OOM protection on the streamable connection; custom JSON-RPC methods; official MCP conformance tests in CI; blocks server-initiated requests (SEP-2322).

Best Practices

Typed AddTool[In, Out] auto-generates and validates both input and output schemas; schema reflection is cached automatically since v1.3.0; Icon.Source is spec'd as a required URI (HTTP/HTTPS or `(redacted)

Improvement Opportunities

πŸƒ Quick Wins

  • Inspector client version is hardcoded to "1.0.0" in connectStdioMCPServer/connectHTTPMCPServer (mcp.Implementation{Name:"gh-aw-inspector", Version:"1.0.0"}), while the server side uses GetVersion(). Report the real gh-aw version for accurate client identity in remote server logs.
  • mcp.Icon.Source should be a URI, not an emoji. The SDK doc states Source (json src) is required to be an HTTP/HTTPS URL or a (redacted) URI, but gh-aw passes raw emoji ("βž•", "πŸ”„", "πŸ”§", ...). Likely harmless with lenient clients today, but not spec-compliant β€” supply a (redacted) URI or drop the Icons field.

✨ Feature Opportunities

  • Adopt structured tool output (the Out type parameter). Every tool returns nil for the handler's second value and emits results only as TextContent. The comment in mcp_tools_management.go calls this "a reserved SDK extension slot [that] must be nil for now" β€” but in this SDK that slot is the structured output: returning a typed Out auto-generates an outputSchema and populates structuredContent, so programmatic clients consume results without scraping text. Tools that already marshal JSON into TextContent (e.g. audit-diff) are prime candidates. (The comment is also worth correcting to avoid misleading future contributors.)
  • Set ServerOptions.KeepAlive on the HTTP transport. The HTTP server sets SessionTimeout: 2h (idle close) but no KeepAlive. KeepAlive sends periodic pings and closes sessions whose peer stops responding, reclaiming resources far sooner than 2h for dropped/half-open connections.
  • v1.7.0 streamable body-size limit (OOM protection) is worth adopting once v1.7.0 is stable β€” lower urgency here since the server binds to loopback only.

πŸ“ Best Practice Alignment

  • Cross-origin handling is correct as-is: loopback bind + DisableLocalhostProtection:false. Note StreamableHTTPOptions.CrossOriginProtection is now deprecated in favor of wrapping the handler with middleware β€” so do not re-introduce that field; the current approach is the right one.

Recommendations

  1. (Quick) Use GetVersion() for the inspector client Implementation.Version.
  2. (Quick) Replace emoji Icon.Source values with (redacted) URIs, or remove Icons`.
  3. (Medium) Pilot structured output (Out) on one JSON-emitting tool (e.g. audit-diff) and fix the misleading "reserved slot" comment.
  4. (Medium) Add ServerOptions.KeepAlive for the HTTP server path.
  5. (Later) Track v1.7.0 stable for the streamable body-size limit and conformance-tested behavior.

Next Steps

  • Open focused PRs for items 1 & 2 (both tiny, self-contained).
  • Prototype structured output on audit-diff to gauge client benefit before rolling it out broadly.
  • Watch the v1.7.0 release; re-evaluate the OOM body-size limit and the SetError content-preservation change (no tool currently relies on the old overwrite semantics).

Generated by Go Fan
Module summary saved to: scratchpad/mods/modelcontextprotocol-go-sdk.md

Generated by 🐹 Go Fan Β· 212.9 AIC Β· βŒ– 13.5 AIC Β· ⊞ 7.3K Β· β—·

  • expires on Jul 15, 2026, 12:48 AM UTC-08:00

Metadata

Metadata

Labels

Type

No type

Fields

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