Skip to content

How to check client capabilities and handle unsupported capability errors? #607

@robbyt

Description

@robbyt

Is your feature request related to a problem? Please describe.
I have two semi-related questions, caused by uncertainty of how to check client capabilities from an MCP server.

  1. How can I checking the client capabilities before using them?
  2. Can you expos the errors from internal/jsonrpc so I can check for them? (is this a possible solution?)

re 1: How to check Capabilities
I'd like to figure out if a MCP client supports a specific MCP server capability (e.g., ListRoots). I'm assuming client capabilities by reading the fields in the mcp.ClientCapabilities struct- Is this advisable?

Also, the Roots field is a value struct, so I can't check for nil on that like I can with the other capabilities fields Sampling or Elicitation:

go-sdk/mcp/protocol.go

Lines 183 to 195 in d256a9c

type ClientCapabilities struct {
// Experimental, non-standard capabilities that the client supports.
Experimental map[string]any `json:"experimental,omitempty"`
// Present if the client supports listing roots.
Roots struct {
// Whether the client supports notifications for changes to the roots list.
ListChanged bool `json:"listChanged,omitempty"`
} `json:"roots,omitempty"`
// Present if the client supports sampling from an LLM.
Sampling *SamplingCapabilities `json:"sampling,omitempty"`
// Present if the client supports elicitation from the server.
Elicitation *ElicitationCapabilities `json:"elicitation,omitempty"`
}

re 2: Error types from internal/jsonrpc
When using the elicitation/sampleing/logging capabilities, the examples just return an error to the client. The don't differentiate between the different types, or use any errors.Is(). So when a client doesn't support a capability (e.g., roots), the SDK returns a JSON-RPC error code -32601 (Method Not Found). However, ErrMethodNotFound is in the internal jsonrpc2 package and cannot be imported by my project, so I can't use errors.Is() to check if an error from ListRoots(), CreateMessage(), or Elicit() is due to an unsupported client capability.

Describe the solution you'd like

  1. Consistent capability structure: Make Roots a pointer type like the other capabilities:
type ClientCapabilities struct {
	Roots       *RootsCapabilities       `json:"roots,omitempty"`  // Changed from inline struct
	Sampling    *SamplingCapabilities    `json:"sampling,omitempty"`
	Elicitation *ElicitationCapabilities `json:"elicitation,omitempty"`
}

type RootsCapabilities struct {
	ListChanged bool `json:"listChanged,omitempty"`
}

This would allow checking Capabilities.Roots != nil to determine if roots are supported at all.

  1. Export JSON-RPC errors: Export common JSON-RPC errors from the public jsonrpc package:
// jsonrpc/jsonrpc.go
var (
	ErrMethodNotFound = internal.ErrMethodNotFound
	ErrInvalidParams  = internal.ErrInvalidParams
	// etc.
)

This would enable library authors to use errors.Is(err, jsonrpc.ErrMethodNotFound) to detect specific error conditions.

Describe alternatives you've considered

Right now I need to do string matching on the error, or infer client capabilities from reading the ClientCapabilities.

Additional context
Possibly related to #166
Thank you for reading, and designing such a useful library!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions