Skip to content

proposal: mcp: add ClientSession.Discover to send server/discover on demand #1424

Closed

Description

@clearly

Is your feature request related to a problem? Please describe.

In 2026-07-28 ping is removed, and server/discover is the spec's lightweight way to learn a server's identity, capabilities, supported versions and cache hints (ttlMs/cacheScope). Servers MUST implement it, and clients MAY call it at any time. go-sdk sends it only inside Client.Connect, and there's no public way to send it afterwards:

  • ClientSession has no Discover method. The result is folded into InitializeResult(), and the DiscoverResult cache fields are dropped.
  • mcp.AddSendingCustomMethod refuses the method:
package main

import (
	"fmt"

	"github.com/modelcontextprotocol/go-sdk/mcp"
)

type discoverParams struct{ mcp.ParamsBase }
type discoverResult struct {
	mcp.ResultBase
	SupportedVersions []string `json:"supportedVersions"`
}

func main() {
	c := mcp.NewClient(&mcp.Implementation{Name: "repro", Version: "0.0.1"}, nil)
	err := mcp.AddSendingCustomMethod[*discoverParams, *discoverResult](c, "server/discover")
	fmt.Println("AddSendingCustomMethod(server/discover):", err)
}

Output (v1.8.0 and main @ 3ebc6d1):

AddSendingCustomMethod(server/discover): mcp: AddSendingCustomMethod: "server/discover" shadows a standard MCP method

Concrete uses we have:

  1. Health and liveness on a modern session. Ping is gone on 2026-07-28 sessions (and after mcp: fail Ping fast on 2026-07-28 sessions #1378 it fails fast there). ListTools isn't a substitute, because the SDK answers it from its own ttlMs cache without contacting the server. Today we open a second transport connection and write raw JSON-RPC, which for stdio means spawning a second server process.
  2. Refreshing server metadata (capabilities, instructions, serverInfo) after the DiscoverResult ttlMs expires, without reconnecting.
  3. Diagnostics, such as "which versions does this server support?", in an integration test-style command.

Describe the solution you'd like

// Discover sends a server/discover request on the session's transport and
// returns the server's result, including Cacheable fields. It is valid on
// sessions negotiated at 2026-07-28 or later.
func (cs *ClientSession) Discover(ctx context.Context, params *DiscoverParams) (*DiscoverResult, error)
  • It uses the session's negotiated version and _meta triple, like other requests.
  • On a legacy (≤ 2025-11-25) session it returns an error without sending anything, the way Ping is handled on modern sessions in mcp: fail Ping fast on 2026-07-28 sessions #1378.
  • It returns *DiscoverResult unchanged, so callers see SupportedVersions, Capabilities, Instructions, TTLMs/CacheScope and serverInfo in _meta.
  • Optionally, Client.Connect could use the same internal path, so behavior stays identical.

Describe alternatives you've considered

  • Allow AddSendingCustomMethod for server/discover only. It's untyped and contradicts the "standard method" guard, so it's worse than a typed method.
  • Keep using a second raw connection. That works, but costs a process spawn per probe on stdio and duplicates _meta construction outside the SDK.

Additional context

Activity

  1. added a commit that references this issue on Oct 21, 2026
    2afd3b6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions