Skip to content

Commit be5ae01

Browse files
committed
docs: document resources
1 parent 5985a7c commit be5ae01

File tree

3 files changed

+245
-2
lines changed

3 files changed

+245
-2
lines changed

docs/server.md

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

110110
## Resources
111111

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

114234
## Tools
115235

internal/docs/server.src.md

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

3636
## Resources
3737

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

4090
## Tools
4191

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)