docs: document resources (#505)
This commit is contained in:
parent
5985a7cbba
commit
4fa725857c
3 changed files with 249 additions and 2 deletions
124
docs/server.md
124
docs/server.md
|
|
@ -109,7 +109,129 @@ func Example_prompts() {
|
|||
|
||||
## Resources
|
||||
|
||||
<!-- TODO -->
|
||||
In MCP terms, a _resource_ is some data referenced by a URI.
|
||||
MCP servers can serve resources to clients.
|
||||
They can register resources individually, or register a _resource template_
|
||||
that uses a URI pattern to describe a collection of resources.
|
||||
|
||||
|
||||
**Client-side**:
|
||||
Call [`ClientSession.ReadResource`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.ReadResource)
|
||||
to read a resource.
|
||||
The SDK ensures that a read succeeds only if the URI matches a registered resource exactly,
|
||||
or matches the URI pattern of a resource template.
|
||||
|
||||
To list a server's resources and resource templates, use the
|
||||
[`ClientSession.Resources`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Resources)
|
||||
and
|
||||
[`ClientSession.ResourceTemplates`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.ResourceTemplates)
|
||||
iterators, or the lower-level `ListXXX` calls (see [pagination](#pagination)).
|
||||
Set
|
||||
[`ClientOptions.ResourceListChangedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions.ResourceListChangedHandler)
|
||||
to be notified of changes in the lists of resources or resource templates.
|
||||
|
||||
Clients can be notified when the contents of a resource changes by subscribing to the resource's URI.
|
||||
Call
|
||||
[`ClientSession.Subscribe`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Subscribe)
|
||||
to subscribe to a resource
|
||||
and
|
||||
[`ClientSession.Unsubscribe`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Unsubscribe)
|
||||
to unsubscribe.
|
||||
Set
|
||||
[`ClientOptions.ResourceUpdatedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions.ResourceUpdatedHandler)
|
||||
to be notified of changes to subscribed resources.
|
||||
|
||||
**Server-side**:
|
||||
Use
|
||||
[`Server.AddResource`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.AddResource)
|
||||
or
|
||||
[`Server.AddResourceTemplate`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.AddResourceTemplate)
|
||||
to add a resource or resource template to the server along with its handler.
|
||||
A
|
||||
[`ResourceHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ResourceHandler)
|
||||
maps a URI to the contents of a resource, which can include text, binary data,
|
||||
or both.
|
||||
If `AddResource` or `AddResourceTemplate` is called before a server is connected, the server will have the
|
||||
`resources` capability.
|
||||
The server will have the `resources` capability if any resource or resource template is added before the
|
||||
server is connected to a client, or if
|
||||
[`ServerOptions.HasResources`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.HasResources)
|
||||
is explicitly set. When a prompt is added, any clients already connected to the
|
||||
server will be notified via a `notifications/resources/list_changed`
|
||||
notification.
|
||||
|
||||
|
||||
```go
|
||||
func Example_resources() {
|
||||
ctx := context.Background()
|
||||
|
||||
resources := map[string]string{
|
||||
"file:///a": "a",
|
||||
"file:///dir/x": "x",
|
||||
"file:///dir/y": "y",
|
||||
}
|
||||
|
||||
handler := func(_ context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
|
||||
uri := req.Params.URI
|
||||
c, ok := resources[uri]
|
||||
if !ok {
|
||||
return nil, mcp.ResourceNotFoundError(uri)
|
||||
}
|
||||
return &mcp.ReadResourceResult{
|
||||
Contents: []*mcp.ResourceContents{{URI: uri, Text: c}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Create a server with a single resource.
|
||||
s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil)
|
||||
s.AddResource(&mcp.Resource{URI: "file:///a"}, handler)
|
||||
s.AddResourceTemplate(&mcp.ResourceTemplate{URITemplate: "file:///dir/{f}"}, handler)
|
||||
|
||||
// Create a client.
|
||||
c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil)
|
||||
|
||||
// Connect the server and client.
|
||||
t1, t2 := mcp.NewInMemoryTransports()
|
||||
if _, err := s.Connect(ctx, t1, nil); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
cs, err := c.Connect(ctx, t2, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer cs.Close()
|
||||
|
||||
// List resources and resource templates.
|
||||
for r, err := range cs.Resources(ctx, nil) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(r.URI)
|
||||
}
|
||||
for r, err := range cs.ResourceTemplates(ctx, nil) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(r.URITemplate)
|
||||
}
|
||||
|
||||
// Read resources.
|
||||
for _, path := range []string{"a", "dir/x", "b"} {
|
||||
res, err := cs.ReadResource(ctx, &mcp.ReadResourceParams{URI: "file:///" + path})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println(res.Contents[0].Text)
|
||||
}
|
||||
}
|
||||
// Output:
|
||||
// file:///a
|
||||
// file:///dir/{f}
|
||||
// a
|
||||
// x
|
||||
// calling "resources/read": Resource not found
|
||||
}
|
||||
```
|
||||
|
||||
## Tools
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,59 @@ notification.
|
|||
|
||||
## Resources
|
||||
|
||||
<!-- TODO -->
|
||||
In MCP terms, a _resource_ is some data referenced by a URI.
|
||||
MCP servers can serve resources to clients.
|
||||
They can register resources individually, or register a _resource template_
|
||||
that uses a URI pattern to describe a collection of resources.
|
||||
|
||||
|
||||
**Client-side**:
|
||||
Call [`ClientSession.ReadResource`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.ReadResource)
|
||||
to read a resource.
|
||||
The SDK ensures that a read succeeds only if the URI matches a registered resource exactly,
|
||||
or matches the URI pattern of a resource template.
|
||||
|
||||
To list a server's resources and resource templates, use the
|
||||
[`ClientSession.Resources`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Resources)
|
||||
and
|
||||
[`ClientSession.ResourceTemplates`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.ResourceTemplates)
|
||||
iterators, or the lower-level `ListXXX` calls (see [pagination](#pagination)).
|
||||
Set
|
||||
[`ClientOptions.ResourceListChangedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions.ResourceListChangedHandler)
|
||||
to be notified of changes in the lists of resources or resource templates.
|
||||
|
||||
Clients can be notified when the contents of a resource changes by subscribing to the resource's URI.
|
||||
Call
|
||||
[`ClientSession.Subscribe`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Subscribe)
|
||||
to subscribe to a resource
|
||||
and
|
||||
[`ClientSession.Unsubscribe`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Unsubscribe)
|
||||
to unsubscribe.
|
||||
Set
|
||||
[`ClientOptions.ResourceUpdatedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions.ResourceUpdatedHandler)
|
||||
to be notified of changes to subscribed resources.
|
||||
|
||||
**Server-side**:
|
||||
Use
|
||||
[`Server.AddResource`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.AddResource)
|
||||
or
|
||||
[`Server.AddResourceTemplate`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.AddResourceTemplate)
|
||||
to add a resource or resource template to the server along with its handler.
|
||||
A
|
||||
[`ResourceHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ResourceHandler)
|
||||
maps a URI to the contents of a resource, which can include text, binary data,
|
||||
or both.
|
||||
If `AddResource` or `AddResourceTemplate` is called before a server is connected, the server will have the
|
||||
`resources` capability.
|
||||
The server will have the `resources` capability if any resource or resource template is added before the
|
||||
server is connected to a client, or if
|
||||
[`ServerOptions.HasResources`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.HasResources)
|
||||
is explicitly set. When a prompt is added, any clients already connected to the
|
||||
server will be notified via a `notifications/resources/list_changed`
|
||||
notification.
|
||||
|
||||
|
||||
%include ../../mcp/server_example_test.go resources -
|
||||
|
||||
## Tools
|
||||
|
||||
|
|
|
|||
|
|
@ -82,3 +82,76 @@ func Example_prompts() {
|
|||
}
|
||||
|
||||
// !-prompts
|
||||
|
||||
// !+resources
|
||||
func Example_resources() {
|
||||
ctx := context.Background()
|
||||
|
||||
resources := map[string]string{
|
||||
"file:///a": "a",
|
||||
"file:///dir/x": "x",
|
||||
"file:///dir/y": "y",
|
||||
}
|
||||
|
||||
handler := func(_ context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
|
||||
uri := req.Params.URI
|
||||
c, ok := resources[uri]
|
||||
if !ok {
|
||||
return nil, mcp.ResourceNotFoundError(uri)
|
||||
}
|
||||
return &mcp.ReadResourceResult{
|
||||
Contents: []*mcp.ResourceContents{{URI: uri, Text: c}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Create a server with a single resource.
|
||||
s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil)
|
||||
s.AddResource(&mcp.Resource{URI: "file:///a"}, handler)
|
||||
s.AddResourceTemplate(&mcp.ResourceTemplate{URITemplate: "file:///dir/{f}"}, handler)
|
||||
|
||||
// Create a client.
|
||||
c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil)
|
||||
|
||||
// Connect the server and client.
|
||||
t1, t2 := mcp.NewInMemoryTransports()
|
||||
if _, err := s.Connect(ctx, t1, nil); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
cs, err := c.Connect(ctx, t2, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer cs.Close()
|
||||
|
||||
// List resources and resource templates.
|
||||
for r, err := range cs.Resources(ctx, nil) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(r.URI)
|
||||
}
|
||||
for r, err := range cs.ResourceTemplates(ctx, nil) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(r.URITemplate)
|
||||
}
|
||||
|
||||
// Read resources.
|
||||
for _, path := range []string{"a", "dir/x", "b"} {
|
||||
res, err := cs.ReadResource(ctx, &mcp.ReadResourceParams{URI: "file:///" + path})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println(res.Contents[0].Text)
|
||||
}
|
||||
}
|
||||
// Output:
|
||||
// file:///a
|
||||
// file:///dir/{f}
|
||||
// a
|
||||
// x
|
||||
// calling "resources/read": Resource not found
|
||||
}
|
||||
|
||||
// !-resources
|
||||
|
|
|
|||
Loading…
Reference in a new issue