Summary
server/discover (SEP-2575) omits instructions from its result even when the server was constructed with ServerOptions.Instructions, while initialize returns it. Both handlers read the same s.opts.Instructions, so the two handshakes disagree on the same server.
Observed in
go-sdk v1.7.0-pre.1, server constructed with non-empty ServerOptions.Instructions.
initialize @ 2025-11-25 → instructions present (~1.2KB)
initialize @ 2026-07-28 → instructions present
server/discover @ 2026-07-28 → instructions absent (stdio and streamable-HTTP)
Spec status
Not a conformance violation — DiscoverResult.instructions is optional (draft schema.json required: [capabilities, resultType, serverInfo, supportedVersions]). But it's a behavioral inconsistency: a client adopting server/discover silently loses the server's tool-selection guidance that the same server advertises via initialize.
Code
Both handlers source the same field:
mcp/server.go:876 (discover): Instructions: s.opts.Instructions
mcp/server.go:1884 (initialize): Instructions: s.opts.Instructions
So either the stateless/discover path resolves a server without opts.Instructions populated, or it's stripped before marshal. Worth confirming whether discover runs against a different Server/session instance under stateless transport.
Repro
Construct mcp.Server with ServerOptions{Instructions: "hello"}. Drive server/discover (HTTP: MCP-Protocol-Version: 2026-07-28, Mcp-Method: server/discover, reserved _meta protocolVersion/clientInfo/clientCapabilities). Result has no instructions; an initialize against the same server does.
Testing gap
No test asserts DiscoverResult.Instructions == s.opts.Instructions. Discover/initialize parity (instructions, capabilities, serverInfo) is untested. Suggest a table test asserting both handshakes surface identical server-identity fields for a server configured with instructions.
Summary
server/discover(SEP-2575) omitsinstructionsfrom its result even when the server was constructed withServerOptions.Instructions, whileinitializereturns it. Both handlers read the sames.opts.Instructions, so the two handshakes disagree on the same server.Observed in
go-sdk
v1.7.0-pre.1, server constructed with non-emptyServerOptions.Instructions.initialize@ 2025-11-25 →instructionspresent (~1.2KB)initialize@ 2026-07-28 →instructionspresentserver/discover@ 2026-07-28 →instructionsabsent (stdio and streamable-HTTP)Spec status
Not a conformance violation —
DiscoverResult.instructionsis optional (draftschema.jsonrequired: [capabilities, resultType, serverInfo, supportedVersions]). But it's a behavioral inconsistency: a client adoptingserver/discoversilently loses the server's tool-selection guidance that the same server advertises viainitialize.Code
Both handlers source the same field:
mcp/server.go:876(discover):Instructions: s.opts.Instructionsmcp/server.go:1884(initialize):Instructions: s.opts.InstructionsSo either the stateless/discover path resolves a server without
opts.Instructionspopulated, or it's stripped before marshal. Worth confirming whether discover runs against a different Server/session instance under stateless transport.Repro
Construct
mcp.ServerwithServerOptions{Instructions: "hello"}. Driveserver/discover(HTTP:MCP-Protocol-Version: 2026-07-28,Mcp-Method: server/discover, reserved_metaprotocolVersion/clientInfo/clientCapabilities). Result has noinstructions; aninitializeagainst the same server does.Testing gap
No test asserts
DiscoverResult.Instructions == s.opts.Instructions. Discover/initialize parity (instructions, capabilities, serverInfo) is untested. Suggest a table test asserting both handshakes surface identical server-identity fields for a server configured with instructions.