internal/mcp: implement resources

Implementation of resources.

This follows the design sketched in design/design.md, except for
Server.FileResourceHandler, which will be in a forthcoming CL.

As the spec recommends, the server verifies an incoming URI from the
client against its list of resources, to make sure the URI came from one
of them.

Some things that aren't in the design doc:
- I provide an exported function that creates a "resource not found"
  jsonrpc2.WireEror error for server authors to return.
  A wrinkle: the MCP spec defines the error code for
  "resource not found" as -32002 [1]. That code is reserved for use
  by implementations of JSON-RPC, not applications. That matters to us
  because our JSON-RPC implementation already uses that code for the
  "server closing" error. I filed a bug against MCP about it [2] and
  chose a different code for the "resource not found" error.

- As a slight convenience, I fill in some fields in the
  ReadResourceResult if the handler doesn't set them.

[1] https://modelcontextprotocol.io/specification/2025-03-26/server/resources#error-handling
[2] https://github.com/modelcontextprotocol/modelcontextprotocol/issues/509

Change-Id: I06153da982ea00748a3691ded923448a880cea2a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/671363
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Jonathan Amsterdam 2025-05-10 09:03:39 -04:00
commit 1ae23e7031

View file

@ -156,6 +156,23 @@ type ListPromptsResult struct {
Prompts []Prompt `json:"prompts"`
}
type ListResourcesParams struct {
// An opaque token representing the current pagination position. If provided,
// the server should return results starting after this cursor.
Cursor string `json:"cursor,omitempty"`
}
// The server's response to a resources/list request from the client.
type ListResourcesResult struct {
// This result property is reserved by the protocol to allow clients and servers
// to attach additional metadata to their responses.
Meta map[string]json.RawMessage `json:"_meta,omitempty"`
// An opaque token representing the pagination position after the last returned
// result. If present, there may be more results available.
NextCursor string `json:"nextCursor,omitempty"`
Resources []Resource `json:"resources"`
}
type ListRootsParams struct {
Meta *struct {
// If specified, the caller is requesting out-of-band progress notifications for
@ -228,6 +245,45 @@ type PromptMessage struct {
Role Role `json:"role"`
}
type ReadResourceParams struct {
// The URI of the resource to read. The URI can use any protocol; it is up to
// the server how to interpret it.
URI string `json:"uri"`
}
// The server's response to a resources/read request from the client.
type ReadResourceResult struct {
// This result property is reserved by the protocol to allow clients and servers
// to attach additional metadata to their responses.
Meta map[string]json.RawMessage `json:"_meta,omitempty"`
Contents *ResourceContents `json:"contents"`
}
// A known resource that the server is capable of reading.
type Resource struct {
// Optional annotations for the client.
Annotations *Annotations `json:"annotations,omitempty"`
// A description of what this resource represents.
//
// This can be used by clients to improve the LLM's understanding of available
// resources. It can be thought of like a "hint" to the model.
Description string `json:"description,omitempty"`
// The MIME type of this resource, if known.
MIMEType string `json:"mimeType,omitempty"`
// A human-readable name for this resource.
//
// This can be used by clients to populate UI elements.
Name string `json:"name"`
// The size of the raw resource content, in bytes (i.e., before base64 encoding
// or any tokenization), if known.
//
// This can be used by Hosts to display file sizes and estimate context window
// usage.
Size int64 `json:"size,omitempty"`
// The URI of this resource.
URI string `json:"uri"`
}
// Present if the server offers any resources to read.
type ResourceCapabilities struct {
// Whether this server supports notifications for changes to the resource list.