Skip to content

Commit 4fa7258

Browse files
authored
docs: document resources (#505)
1 parent 5985a7c commit 4fa7258

File tree

3 files changed

+249
-2
lines changed

3 files changed

+249
-2
lines changed

docs/server.md

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,129 @@ func Example_prompts() {
109109

110110
## Resources
111111

112-
<!-- TODO -->
112+
In MCP terms, a _resource_ is some data referenced by a URI.
113+
MCP servers can serve resources to clients.
114+
They can register resources individually, or register a _resource template_
115+
that uses a URI pattern to describe a collection of resources.
116+
117+
118+
**Client-side**:
119+
Call [`ClientSession.ReadResource`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.ReadResource)
120+
to read a resource.
121+
The SDK ensures that a read succeeds only if the URI matches a registered resource exactly,
122+
or matches the URI pattern of a resource template.
123+
124+
To list a server's resources and resource templates, use the
125+
[`ClientSession.Resources`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Resources)
126+
and
127+
[`ClientSession.ResourceTemplates`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.ResourceTemplates)
128+
iterators, or the lower-level `ListXXX` calls (see [pagination](#pagination)).
129+
Set
130+
[`ClientOptions.ResourceListChangedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions.ResourceListChangedHandler)
131+
to be notified of changes in the lists of resources or resource templates.
132+
133+
Clients can be notified when the contents of a resource changes by subscribing to the resource's URI.
134+
Call
135+
[`ClientSession.Subscribe`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Subscribe)
136+
to subscribe to a resource
137+
and
138+
[`ClientSession.Unsubscribe`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Unsubscribe)
139+
to unsubscribe.
140+
Set
141+
[`ClientOptions.ResourceUpdatedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions.ResourceUpdatedHandler)
142+
to be notified of changes to subscribed resources.
143+
144+
**Server-side**:
145+
Use
146+
[`Server.AddResource`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.AddResource)
147+
or
148+
[`Server.AddResourceTemplate`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.AddResourceTemplate)
149+
to add a resource or resource template to the server along with its handler.
150+
A
151+
[`ResourceHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ResourceHandler)
152+
maps a URI to the contents of a resource, which can include text, binary data,
153+
or both.
154+
If `AddResource` or `AddResourceTemplate` is called before a server is connected, the server will have the
155+
`resources` capability.
156+
The server will have the `resources` capability if any resource or resource template is added before the
157+
server is connected to a client, or if
158+
[`ServerOptions.HasResources`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.HasResources)
159+
is explicitly set. When a prompt is added, any clients already connected to the
160+
server will be notified via a `notifications/resources/list_changed`
161+
notification.
162+
163+
164+
```go
165+
func Example_resources() {
166+
ctx := context.Background()
167+
168+
resources := map[string]string{
169+
"file:///a": "a",
170+
"file:///dir/x": "x",
171+
"file:///dir/y": "y",
172+
}
173+
174+
handler := func(_ context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
175+
uri := req.Params.URI
176+
c, ok := resources[uri]
177+
if !ok {
178+
return nil, mcp.ResourceNotFoundError(uri)
179+
}
180+
return &mcp.ReadResourceResult{
181+
Contents: []*mcp.ResourceContents{{URI: uri, Text: c}},
182+
}, nil
183+
}
184+
185+
// Create a server with a single resource.
186+
s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil)
187+
s.AddResource(&mcp.Resource{URI: "file:///a"}, handler)
188+
s.AddResourceTemplate(&mcp.ResourceTemplate{URITemplate: "file:///dir/{f}"}, handler)
189+
190+
// Create a client.
191+
c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil)
192+
193+
// Connect the server and client.
194+
t1, t2 := mcp.NewInMemoryTransports()
195+
if _, err := s.Connect(ctx, t1, nil); err != nil {
196+
log.Fatal(err)
197+
}
198+
cs, err := c.Connect(ctx, t2, nil)
199+
if err != nil {
200+
log.Fatal(err)
201+
}
202+
defer cs.Close()
203+
204+
// List resources and resource templates.
205+
for r, err := range cs.Resources(ctx, nil) {
206+
if err != nil {
207+
log.Fatal(err)
208+
}
209+
fmt.Println(r.URI)
210+
}
211+
for r, err := range cs.ResourceTemplates(ctx, nil) {
212+
if err != nil {
213+
log.Fatal(err)
214+
}
215+
fmt.Println(r.URITemplate)
216+
}
217+
218+
// Read resources.
219+
for _, path := range []string{"a", "dir/x", "b"} {
220+
res, err := cs.ReadResource(ctx, &mcp.ReadResourceParams{URI: "file:///" + path})
221+
if err != nil {
222+
fmt.Println(err)
223+
} else {
224+
fmt.Println(res.Contents[0].Text)
225+
}
226+
}
227+
// Output:
228+
// file:///a
229+
// file:///dir/{f}
230+
// a
231+
// x
232+
// calling "resources/read": Resource not found
233+
}
234+
```
113235

114236
## Tools
115237

internal/docs/server.src.md

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,59 @@ notification.
3535

3636
## Resources
3737

38-
<!-- TODO -->
38+
In MCP terms, a _resource_ is some data referenced by a URI.
39+
MCP servers can serve resources to clients.
40+
They can register resources individually, or register a _resource template_
41+
that uses a URI pattern to describe a collection of resources.
42+
43+
44+
**Client-side**:
45+
Call [`ClientSession.ReadResource`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.ReadResource)
46+
to read a resource.
47+
The SDK ensures that a read succeeds only if the URI matches a registered resource exactly,
48+
or matches the URI pattern of a resource template.
49+
50+
To list a server's resources and resource templates, use the
51+
[`ClientSession.Resources`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Resources)
52+
and
53+
[`ClientSession.ResourceTemplates`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.ResourceTemplates)
54+
iterators, or the lower-level `ListXXX` calls (see [pagination](#pagination)).
55+
Set
56+
[`ClientOptions.ResourceListChangedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions.ResourceListChangedHandler)
57+
to be notified of changes in the lists of resources or resource templates.
58+
59+
Clients can be notified when the contents of a resource changes by subscribing to the resource's URI.
60+
Call
61+
[`ClientSession.Subscribe`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Subscribe)
62+
to subscribe to a resource
63+
and
64+
[`ClientSession.Unsubscribe`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientSession.Unsubscribe)
65+
to unsubscribe.
66+
Set
67+
[`ClientOptions.ResourceUpdatedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions.ResourceUpdatedHandler)
68+
to be notified of changes to subscribed resources.
69+
70+
**Server-side**:
71+
Use
72+
[`Server.AddResource`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.AddResource)
73+
or
74+
[`Server.AddResourceTemplate`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.AddResourceTemplate)
75+
to add a resource or resource template to the server along with its handler.
76+
A
77+
[`ResourceHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ResourceHandler)
78+
maps a URI to the contents of a resource, which can include text, binary data,
79+
or both.
80+
If `AddResource` or `AddResourceTemplate` is called before a server is connected, the server will have the
81+
`resources` capability.
82+
The server will have the `resources` capability if any resource or resource template is added before the
83+
server is connected to a client, or if
84+
[`ServerOptions.HasResources`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.HasResources)
85+
is explicitly set. When a prompt is added, any clients already connected to the
86+
server will be notified via a `notifications/resources/list_changed`
87+
notification.
88+
89+
90+
%include ../../mcp/server_example_test.go resources -
3991

4092
## Tools
4193

mcp/server_example_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,76 @@ func Example_prompts() {
8282
}
8383

8484
// !-prompts
85+
86+
// !+resources
87+
func Example_resources() {
88+
ctx := context.Background()
89+
90+
resources := map[string]string{
91+
"file:///a": "a",
92+
"file:///dir/x": "x",
93+
"file:///dir/y": "y",
94+
}
95+
96+
handler := func(_ context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
97+
uri := req.Params.URI
98+
c, ok := resources[uri]
99+
if !ok {
100+
return nil, mcp.ResourceNotFoundError(uri)
101+
}
102+
return &mcp.ReadResourceResult{
103+
Contents: []*mcp.ResourceContents{{URI: uri, Text: c}},
104+
}, nil
105+
}
106+
107+
// Create a server with a single resource.
108+
s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil)
109+
s.AddResource(&mcp.Resource{URI: "file:///a"}, handler)
110+
s.AddResourceTemplate(&mcp.ResourceTemplate{URITemplate: "file:///dir/{f}"}, handler)
111+
112+
// Create a client.
113+
c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil)
114+
115+
// Connect the server and client.
116+
t1, t2 := mcp.NewInMemoryTransports()
117+
if _, err := s.Connect(ctx, t1, nil); err != nil {
118+
log.Fatal(err)
119+
}
120+
cs, err := c.Connect(ctx, t2, nil)
121+
if err != nil {
122+
log.Fatal(err)
123+
}
124+
defer cs.Close()
125+
126+
// List resources and resource templates.
127+
for r, err := range cs.Resources(ctx, nil) {
128+
if err != nil {
129+
log.Fatal(err)
130+
}
131+
fmt.Println(r.URI)
132+
}
133+
for r, err := range cs.ResourceTemplates(ctx, nil) {
134+
if err != nil {
135+
log.Fatal(err)
136+
}
137+
fmt.Println(r.URITemplate)
138+
}
139+
140+
// Read resources.
141+
for _, path := range []string{"a", "dir/x", "b"} {
142+
res, err := cs.ReadResource(ctx, &mcp.ReadResourceParams{URI: "file:///" + path})
143+
if err != nil {
144+
fmt.Println(err)
145+
} else {
146+
fmt.Println(res.Contents[0].Text)
147+
}
148+
}
149+
// Output:
150+
// file:///a
151+
// file:///dir/{f}
152+
// a
153+
// x
154+
// calling "resources/read": Resource not found
155+
}
156+
157+
// !-resources

0 commit comments

Comments
 (0)