You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
πΉ Go Fan Report: github.com/modelcontextprotocol/go-sdk
Module Overview
The official Go SDK for the Model Context Protocol (MCP), maintained by Anthropic in collaboration with Google. It provides typed MCP clients and servers, stdio/command/streamable-HTTP transports, OAuth helpers, JSON-RPC primitives, and middleware hooks.
π¨ Behavior change: Cross-Origin Protection no longer enabled by default when StreamableHTTPOptions.CrossOriginProtection is nil. Restore via MCPGODEBUG=enableoriginverification=1 or by setting the field explicitly.
β¨ New auth.ClientCredentialsHandler β OAuth 2.0 Client Credentials grant (RFC 6749 Β§4.4) for service-to-service authentication.
π Keepalive no longer closes the session when ping returns method-not-found.
β¨ Streamable transport now accepts parameterized Content-Type (e.g. application/json; charset=utf-8).
β¨ OAuth flow no longer re-prompts after a cancelled Authorize.
β‘οΈ CrossOriginProtection field is now deprecated β wrap the handler with http.NewCrossOriginProtection() middleware instead. Removed in v1.8.0.
Best Practices from the README
Tools are added with mcp.AddTool(server, &mcp.Tool{...}, handler) where the handler signature is func(ctx, *CallToolRequest, In) (*CallToolResult, Out, error).
Servers run via server.Run(ctx, transport) for stdio or NewStreamableHTTPHandler for HTTP.
Layer behavior via AddReceivingMiddleware / AddSendingMiddleware.
Improvement Opportunities
π Quick Wins
1. π¨ Restore cross-origin protection on the HTTP MCP server (security regression)
pkg/cli/mcp_server_http.go:64-74 passes CrossOriginProtection: nil in mcp.StreamableHTTPOptions. In v1.4.1βv1.5.0 this meant default protection was enabled. In v1.6.0 it now means NO protection. This regression arrived silently with the dependency bump.
Forward-compatible fix (recommended by the SDK, since the field is deprecated and removed in v1.8.0):
// Wrap the handler with cross-origin protection middlewarehandler:=mcp.NewStreamableHTTPHandler(getServer, &mcp.StreamableHTTPOptions{
SessionTimeout: 2*time.Hour,
Logger: logger.NewSlogLoggerWithHandler(mcpLog),
})
protection:=http.NewCrossOriginProtection()
handlerWithLogging:=loggingHandler(protection.Handler(handler))
2. Audit IdempotentHint: true on tools that mutate state
MCP's IdempotentHint means "calling it again with identical args produces the same result without additional effects". Two current uses don't match that contract:
logs (pkg/cli/mcp_tools_privileged.go:69-73) downloads new artifacts on each call.
Consider dropping IdempotentHint from these tools, or repositioning them as ReadOnlyHint: false.
3. Replace the HTTP loggingHandler with a sending middleware
pkg/cli/mcp_server_http.go:31-61 reimplements request/response logging at the HTTP layer. The SDK already accepts a Logger in StreamableHTTPOptions; an AddSendingMiddleware on the server could log MCP method-level traffic (rather than just HTTP frames).
β¨ Feature Opportunities
1. Expose compiled lock files as MCP Resources
Today the server only exposes tools. The Resource primitive is a natural fit for .lock.yml files: clients could resources/list and resources/read instead of re-running compile. The SDK supports server.AddResource for this.
2. Emit ProgressNotification for long-running tools
compile --zizmor --poutine --actionlint and logs can take minutes. The MCP spec includes progress notifications β clients like Claude Desktop and Cline render them as progress bars. Wiring this up turns opaque blocking calls into interactive feedback.
3. Optional OAuth for the HTTP MCP server
pkg/cli/mcp_server_http.go currently has no auth on the HTTP transport. With v1.6.0's auth.ClientCredentialsHandler (OAuth 2.0 client-credentials grant), gh-aw could optionally require service-to-service auth when serving HTTP β stdio remains naturally guarded by process ownership.
4. DNS rebinding protection if/when SSE is added
PR #891 added DNS rebinding + cross-origin protections to the SSE transport. gh-aw doesn't use SSE today, but it's the right protection for any future long-lived stream.
π Best Practice Alignment
Migrate off the deprecated StreamableHTTPOptions.CrossOriginProtection field (removed in v1.8.0). The SDK docs explicitly recommend wrapping the handler with http.NewCrossOriginProtection() middleware instead.
The mcp-inspect 5-second MCPOperationTimeout (pkg/cli/mcp_inspect_mcp.go:25) is hard-coded β large remote tool lists may time out. Consider a --mcp-timeout flag.
Tool icons use single emoji glyphs (mcp.Icon{Source: "π"}). Icon.Source supports URLs / data URLs β richer artwork would improve discoverability in MCP tool pickers.
Document MCPGODEBUG (the new mechanism for restoring legacy SDK behavior) in docs/ so future debuggers find it.
Re-evaluate the manual *mcp.CallToolParamsRaw extraction in pkg/cli/mcp_argument_validation.go:99-103 on the next SDK release β there may be a typed helper.
Recommendations
Prioritized actions:
P0 (security): Restore cross-origin protection on the HTTP MCP server. Wrap the handler with http.NewCrossOriginProtection() β forward-compatible with v1.8.0.
P1: Correct IdempotentHint annotations on compile and logs.
P2: Adopt ProgressNotification for compile and logs.
P3: Expose .lock.yml files as MCP Resources.
P3: Consider OAuth client-credentials for HTTP-served sessions.
Next Steps
Open a focused PR fixing the cross-origin protection regression (small, scoped, security-flagged).
Add a separate PR auditing IdempotentHint annotations.
πΉ Go Fan Report:
github.com/modelcontextprotocol/go-sdkModule Overview
The official Go SDK for the Model Context Protocol (MCP), maintained by Anthropic in collaboration with Google. It provides typed MCP clients and servers, stdio/command/streamable-HTTP transports, OAuth helpers, JSON-RPC primitives, and middleware hooks.
Current Usage in gh-aw
pkg/cli+pkg/parser)gh aw mcp-server) and acts as an MCP client (gh aw mcp inspect)Key APIs in use
mcp.NewServer/mcp.NewClientpkg/cli/mcp_server.go:47,pkg/cli/mcp_inspect_mcp.go:167,233mcp.AddTool[In, Out](generic typed tools)pkg/cli/mcp_tools_*.go(10 tools)mcp.StdioTransport/CommandTransport/StreamableClientTransportpkg/cli/mcp_server_command.go:171,pkg/cli/mcp_inspect_mcp.go:170,240mcp.NewStreamableHTTPHandler+StreamableHTTPOptionspkg/cli/mcp_server_http.go:68-73server.AddReceivingMiddlewarepkg/cli/mcp_server.go:90(custom "Did you mean?" middleware)mcp.ToolAnnotations{ReadOnlyHint, IdempotentHint, OpenWorldHint, DestructiveHint}mcp.Icon{Source: "π"}jsonrpc.Error+Code{InternalError,InvalidParams,MethodNotFound}pkg/cli/mcp_error.go,mcp_argument_validation.gojsonschema.For[T]+AddSchemaDefault(SEP-1024 elicitation)pkg/cli/mcp_schema.goResearch Findings
Recent Updates (v1.6.0 β 2026-05-08)
StreamableHTTPOptions.CrossOriginProtectionisnil. Restore viaMCPGODEBUG=enableoriginverification=1or by setting the field explicitly.auth.ClientCredentialsHandlerβ OAuth 2.0 Client Credentials grant (RFC 6749 Β§4.4) for service-to-service authentication.SetErrorpreserves existingContent(previously clobbered it). Revert viaMCPGODEBUG=seterroroverwrite=1.ServerSession.startKeepalive(Add agentic workflow run information to step summaryΒ #856).method-not-found.Content-Type(e.g.application/json; charset=utf-8).Authorize.CrossOriginProtectionfield is now deprecated β wrap the handler withhttp.NewCrossOriginProtection()middleware instead. Removed in v1.8.0.Best Practices from the README
mcp.AddTool(server, &mcp.Tool{...}, handler)where the handler signature isfunc(ctx, *CallToolRequest, In) (*CallToolResult, Out, error).server.Run(ctx, transport)for stdio orNewStreamableHTTPHandlerfor HTTP.AddReceivingMiddleware/AddSendingMiddleware.Improvement Opportunities
π Quick Wins
1. π¨ Restore cross-origin protection on the HTTP MCP server (security regression)
pkg/cli/mcp_server_http.go:64-74passesCrossOriginProtection: nilinmcp.StreamableHTTPOptions. In v1.4.1βv1.5.0 this meant default protection was enabled. In v1.6.0 it now means NO protection. This regression arrived silently with the dependency bump.Forward-compatible fix (recommended by the SDK, since the field is deprecated and removed in v1.8.0):
2. Audit
IdempotentHint: trueon tools that mutate stateMCP's
IdempotentHintmeans "calling it again with identical args produces the same result without additional effects". Two current uses don't match that contract:compile(pkg/cli/mcp_tools_readonly.go:104-108) writes.lock.ymlfiles.logs(pkg/cli/mcp_tools_privileged.go:69-73) downloads new artifacts on each call.Consider dropping
IdempotentHintfrom these tools, or repositioning them asReadOnlyHint: false.3. Replace the HTTP
loggingHandlerwith a sending middlewarepkg/cli/mcp_server_http.go:31-61reimplements request/response logging at the HTTP layer. The SDK already accepts aLoggerinStreamableHTTPOptions; anAddSendingMiddlewareon the server could log MCP method-level traffic (rather than just HTTP frames).β¨ Feature Opportunities
1. Expose compiled lock files as MCP
ResourcesToday the server only exposes tools. The
Resourceprimitive is a natural fit for.lock.ymlfiles: clients couldresources/listandresources/readinstead of re-runningcompile. The SDK supportsserver.AddResourcefor this.2. Emit
ProgressNotificationfor long-running toolscompile --zizmor --poutine --actionlintandlogscan take minutes. The MCP spec includes progress notifications β clients like Claude Desktop and Cline render them as progress bars. Wiring this up turns opaque blocking calls into interactive feedback.3. Optional OAuth for the HTTP MCP server
pkg/cli/mcp_server_http.gocurrently has no auth on the HTTP transport. With v1.6.0'sauth.ClientCredentialsHandler(OAuth 2.0 client-credentials grant), gh-aw could optionally require service-to-service auth when serving HTTP β stdio remains naturally guarded by process ownership.4. DNS rebinding protection if/when SSE is added
PR #891 added DNS rebinding + cross-origin protections to the SSE transport. gh-aw doesn't use SSE today, but it's the right protection for any future long-lived stream.
π Best Practice Alignment
StreamableHTTPOptions.CrossOriginProtectionfield (removed in v1.8.0). The SDK docs explicitly recommend wrapping the handler withhttp.NewCrossOriginProtection()middleware instead.mcp-inspect5-secondMCPOperationTimeout(pkg/cli/mcp_inspect_mcp.go:25) is hard-coded β large remote tool lists may time out. Consider a--mcp-timeoutflag.mcp:serverdebug stream via the configuredLogger.π§ General Improvements
mcp.Icon{Source: "π"}).Icon.Sourcesupports URLs / data URLs β richer artwork would improve discoverability in MCP tool pickers.MCPGODEBUG(the new mechanism for restoring legacy SDK behavior) indocs/so future debuggers find it.*mcp.CallToolParamsRawextraction inpkg/cli/mcp_argument_validation.go:99-103on the next SDK release β there may be a typed helper.Recommendations
Prioritized actions:
http.NewCrossOriginProtection()β forward-compatible with v1.8.0.IdempotentHintannotations oncompileandlogs.ProgressNotificationforcompileandlogs..lock.ymlfiles as MCPResources.Next Steps
IdempotentHintannotations.application_type(SEP-837), HTTP header standardization formethod/name(SEP-2243).References:
ClientCredentialsHandlerGenerated by Go Fan
Module summary saved to:
scratchpad/mods/modelcontextprotocol-go-sdk.md