Use case
We run a multi-tenant MCP gateway (Arcade) on v1.7.0-pre.2, stateless StreamableHTTP, one logical server per gateway. Two things we cannot do today:
- Customize the
server/discover payload beyond what ServerOptions statics allow (e.g. tenant-specific supportedVersions, augmenting the result at build time rather than post-hoc).
- Invoke discover from the host (for health/introspection: "what would this session advertise right now?") without synthesizing an HTTP request against ourselves.
Current behavior
server/discover is handled entirely internally: unexported Server.discover (server.go), registered in serverMethodInfos, special-cased in dispatch. It builds DiscoverResult from s.capabilities(), s.impl, s.opts.Instructions, and the session version list.
- No
ServerOptions field touches discover (checked the full option set on pre.2), and there is no exported Discover(...) on Server/ServerSession.
Why middleware isn't a workaround
Receiving middleware can type-assert *DiscoverResult and mutate it post-hoc, keyed off the method string — reactive, fragile, and only for inbound requests. It cannot let the host invoke discover, and it runs strictly after the SDK computed the payload.
Per the maintainers' stance in #565 (keep the API small), the concrete need here is not "export the internals" but a supported seam:
Proposal (either would do)
type ServerOptions struct {
// DiscoverHandler, if non-nil, can augment the server/discover
// response after the SDK builds it.
DiscoverHandler func(context.Context, *DiscoverRequest, *DiscoverResult) (*DiscoverResult, error)
}
or an exported, host-callable form:
func (ss *ServerSession) Discover(ctx context.Context) (*DiscoverResult, error)
Related but distinct: #1034 fixed a discover/initialize parity bug; this asks for a customization/introspection seam.
🐕 Written by Kyoto, an AI agent, on Pascal's behalf —
Use case
We run a multi-tenant MCP gateway (Arcade) on
v1.7.0-pre.2, stateless StreamableHTTP, one logical server per gateway. Two things we cannot do today:server/discoverpayload beyond whatServerOptionsstatics allow (e.g. tenant-specificsupportedVersions, augmenting the result at build time rather than post-hoc).Current behavior
server/discoveris handled entirely internally: unexportedServer.discover(server.go), registered inserverMethodInfos, special-cased in dispatch. It buildsDiscoverResultfroms.capabilities(),s.impl,s.opts.Instructions, and the session version list.ServerOptionsfield touches discover (checked the full option set on pre.2), and there is no exportedDiscover(...)onServer/ServerSession.Why middleware isn't a workaround
Receiving middleware can type-assert
*DiscoverResultand mutate it post-hoc, keyed off the method string — reactive, fragile, and only for inbound requests. It cannot let the host invoke discover, and it runs strictly after the SDK computed the payload.Per the maintainers' stance in #565 (keep the API small), the concrete need here is not "export the internals" but a supported seam:
Proposal (either would do)
or an exported, host-callable form:
Related but distinct: #1034 fixed a discover/initialize parity bug; this asks for a customization/introspection seam.
🐕 Written by Kyoto, an AI agent, on Pascal's behalf —