πΉ 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
- (Quick) Use
GetVersion() for the inspector client Implementation.Version.
- (Quick) Replace emoji
Icon.Source values with (redacted) URIs, or remove Icons`.
- (Medium) Pilot structured output (
Out) on one JSON-emitting tool (e.g. audit-diff) and fix the misleading "reserved slot" comment.
- (Medium) Add
ServerOptions.KeepAlive for the HTTP server path.
- (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 Β· β·
πΉ Go Fan Report: modelcontextprotocol/go-sdk
Module Overview
github.com/modelcontextprotocol/go-sdkis 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 ingo.mod). It's foundational to gh-aw: it powers the built-ingh aw mcpserver that exposes gh-aw's own tools, and themcp-inspectclient that probes external MCP servers declared in workflows.Current Usage in gh-aw
pkg/cli/mcp_*.go,pkg/parser/mcp.go).../go-sdk/mcpand.../go-sdk/jsonrpcv1.6.1(stable);v1.7.0-pre.2is available as a pre-releaseNewServer+ServerCapabilities/ToolCapabilities, genericAddTool[In,Out]with typed*Argsstructs,ToolAnnotations,Icon,AddReceivingMiddleware,NewStreamableHTTPHandler+StreamableHTTPOptions,NewClient,CommandTransport,StreamableClientTransport{DisableStandaloneSSE},Session.NotifyProgress,jsonrpc.ErrorcodesThe usage is genuinely exemplary and modern β per-request
ctx.Done()cancellation checks, a receiving middleware that rewrites rawadditionalPropertiesschema 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.26new(true)for*boolfields. πResearch Findings
Recent Updates
enableoriginverificationMCPGODEBUG);SetErrornow preserves existingContent;ClientCredentialsHandlerOAuth grant; keepalive race fix.MCPGODEBUG=disablecontenttypecheck=1escape hatch for the POST Content-Type check.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.Sourceis spec'd as a required URI (HTTP/HTTPS or `(redacted)Improvement Opportunities
π Quick Wins
"1.0.0"inconnectStdioMCPServer/connectHTTPMCPServer(mcp.Implementation{Name:"gh-aw-inspector", Version:"1.0.0"}), while the server side usesGetVersion(). Report the real gh-aw version for accurate client identity in remote server logs.mcp.Icon.Sourceshould be a URI, not an emoji. The SDK doc statesSource(jsonsrc) 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 theIconsfield.β¨ Feature Opportunities
Outtype parameter). Every tool returnsnilfor the handler's second value and emits results only asTextContent. The comment inmcp_tools_management.gocalls this "a reserved SDK extension slot [that] must be nil for now" β but in this SDK that slot is the structured output: returning a typedOutauto-generates anoutputSchemaand populatesstructuredContent, so programmatic clients consume results without scraping text. Tools that already marshal JSON intoTextContent(e.g.audit-diff) are prime candidates. (The comment is also worth correcting to avoid misleading future contributors.)ServerOptions.KeepAliveon the HTTP transport. The HTTP server setsSessionTimeout: 2h(idle close) but noKeepAlive.KeepAlivesends periodic pings and closes sessions whose peer stops responding, reclaiming resources far sooner than 2h for dropped/half-open connections.π Best Practice Alignment
DisableLocalhostProtection:false. NoteStreamableHTTPOptions.CrossOriginProtectionis 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
GetVersion()for the inspector clientImplementation.Version.Icon.Sourcevalues with(redacted) URIs, or removeIcons`.Out) on one JSON-emitting tool (e.g.audit-diff) and fix the misleading "reserved slot" comment.ServerOptions.KeepAlivefor the HTTP server path.v1.7.0stable for the streamable body-size limit and conformance-tested behavior.Next Steps
audit-diffto gauge client benefit before rolling it out broadly.v1.7.0release; re-evaluate the OOM body-size limit and theSetErrorcontent-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