mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: migrate coderd MCP server to official MCP Go SDK (#28056)
## Stack Context PR 1 of 6 in a stack that migrates every Coder MCP surface from the archived `github.com/mark3labs/mcp-go` library to the official `github.com/modelcontextprotocol/go-sdk` v1.7.0, adding MCP 2026-07-28 support while keeping compatibility with clients speaking 2024-11-05 through 2025-06-18. Stack: #28056 -> #28057 -> #28058 -> #28059 -> #28060 -> #28061 ## Why The coderd Streamable HTTP MCP server (`/api/experimental/mcp/http`) is the foundation layer: it introduces the official SDK dependency and the shared `RegisterSDKTool` helper the CLI server reuses. - The server runs the SDK handler in stateless mode with `JSONResponse: true`, preserving the previous `application/json` POST wire format. GET and DELETE return 405, and no `Mcp-Session-Id` is issued, both permitted by the Streamable HTTP spec. - `DisableLocalhostProtection` is set because coderd commonly listens on loopback behind a reverse proxy with a public Host header; the endpoint's bearer authentication is the relevant access control. - Tool registration builds raw JSON object schemas and omits empty `required`, keeping `tools/list` output byte-identical to the previous server (verified with a golden comparison). - SDK logs are adapted to `cdr.dev/slog/v3`; only warnings and errors are forwarded because the SDK logs several INFO lines per stateless request. - Tests cover the modern 2026-07-28 flow, legacy 2025-06-18 initialize, unsupported protocol version rejection (`-32022`), and non-POST method behavior. ## Known behavior deltas vs the old endpoint Both deltas come from the SDK enforcing the Streamable HTTP spec where mark3labs was lenient, on an experimental endpoint: - POST requests whose `Accept` header lists `application/json` without `text/event-stream` are now rejected with 400 (the spec requires clients to list both; a missing `Accept` header is still tolerated). mark3labs did not validate `Accept` at all. - The old server generated an unvalidated `Mcp-Session-Id` response header; the stateless SDK handler issues none. Clients that merely echo the header back are unaffected. ## Validation Beyond unit/integration tests, a remote dogfood UAT ran protocol conformance against a live dev server built from the stack tip: version negotiation matrix (2024-11-05 through bogus/omitted values), auth, session/method semantics, tool schema sanity, tools/call happy and error paths (unknown tool, schema-violating args, malformed JSON, jsonrpc "1.0"), and a concurrency smoke test. No 500s or connection drops; error shapes are clean JSON-RPC/HTTP errors. > Mux created this PR on Mike's behalf.
This commit is contained in:
@@ -514,10 +514,12 @@ require (
|
||||
github.com/charmbracelet/x/exp/strings v0.1.0 // indirect
|
||||
github.com/go-json-experiment/json v0.0.0-20260623181947-01eb4420fa68 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
||||
github.com/google/jsonschema-go v0.4.3 // indirect
|
||||
github.com/linkdata/deadlock v0.5.5 // indirect
|
||||
github.com/minio/simdjson-go v0.4.5 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20260226131333-17d1149c6ac6 // indirect
|
||||
github.com/q-uint/parser v0.3.1 // indirect
|
||||
github.com/segmentio/encoding v0.5.4 // indirect
|
||||
github.com/trailofbits/go-mutexasserts v0.0.0-20250514102930-c1f3d2e37561 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.opentelemetry.io/collector/featuregate v1.51.1-0.20260205185216-81bc641f26c0 // indirect
|
||||
@@ -541,6 +543,7 @@ require (
|
||||
github.com/go-git/go-git/v5 v5.19.2
|
||||
github.com/invopop/jsonschema v0.14.0
|
||||
github.com/mark3labs/mcp-go v0.38.0
|
||||
github.com/modelcontextprotocol/go-sdk v1.7.0
|
||||
github.com/nats-io/nats-server/v2 v2.14.2
|
||||
github.com/nats-io/nats.go v1.52.0
|
||||
github.com/openai/openai-go/v3 v3.50.0
|
||||
|
||||
Reference in New Issue
Block a user