0
# Server Resources API
1
2
Resources expose data to LLMs without side effects. Resources are application-driven or user-driven (not model-controlled). Can be static (fixed URIs) or dynamic (URI templates).
3
4
## Static Resources
5
6
```typescript { .api }
7
server.registerResource(
8
name: string,
9
uri: string,
10
config: {
11
title?: string;
12
description?: string;
13
mimeType?: string;
14
icons?: Icons;
15
_meta?: Record<string, unknown>;
16
},
17
readCallback: (uri: URL) => Promise<ReadResourceResult> | ReadResourceResult
18
): RegisteredResource;
19
```
20
21
### Examples
22
23
```typescript
24
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
25
import fs from 'fs/promises';
26
27
const server = new McpServer({ name: 'resources-server', version: '1.0.0' });
28
29
// Config resource
30
server.registerResource('config', 'config://app', {
31
title: 'Application Config',
32
description: 'Application configuration data',
33
mimeType: 'application/json'
34
}, async (uri) => ({
35
contents: [{
36
uri: uri.href,
37
mimeType: 'application/json',
38
text: JSON.stringify({ setting1: 'value1', setting2: 'value2' })
39
}]
40
}));
41
42
// File resource
43
server.registerResource('readme', 'file:///project/README.md', {
44
title: 'Project README',
45
description: 'Project documentation',
46
mimeType: 'text/markdown'
47
}, async (uri) => ({
48
contents: [{
49
uri: uri.href,
50
mimeType: 'text/markdown',
51
text: await fs.readFile('/project/README.md', 'utf-8')
52
}]
53
}));
54
```
55
56
## Dynamic Resources (URI Templates)
57
58
```typescript { .api }
59
server.registerResource(
60
name: string,
61
template: ResourceTemplate,
62
config: { title?: string; description?: string; mimeType?: string; icons?: Icons; _meta?: Record<string, unknown>; },
63
readCallback: (uri: URL, variables: Variables) => Promise<ReadResourceResult> | ReadResourceResult
64
): RegisteredResourceTemplate;
65
```
66
67
### ResourceTemplate Class
68
69
```typescript { .api }
70
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
71
import { UriTemplate, Variables } from '@modelcontextprotocol/sdk/shared/uriTemplate.js';
72
73
class ResourceTemplate {
74
constructor(
75
uriTemplate: string | UriTemplate,
76
callbacks: {
77
list?: (cursor?: string) => Promise<Resource[]> | Resource[];
78
complete?: {
79
[variable: string]: (value: string, context?: { arguments?: Record<string, unknown> }) => Promise<string[]> | string[];
80
};
81
}
82
);
83
get uriTemplate(): UriTemplate;
84
get listCallback(): ListResourcesCallback | undefined;
85
completeCallback(variable: string): CompleteResourceTemplateCallback | undefined;
86
}
87
88
// UriTemplate (RFC 6570)
89
class UriTemplate {
90
constructor(template: string);
91
match(uri: string): Variables | undefined; // Extract variables
92
expand(variables: Variables): string; // Expand template
93
toString(): string;
94
}
95
96
type Variables = Record<string, string>;
97
```
98
99
### Examples
100
101
```typescript
102
// User profile with template
103
server.registerResource('user-profile',
104
new ResourceTemplate('users://{userId}/profile', { list: undefined }),
105
{ title: 'User Profile' },
106
async (uri, { userId }) => {
107
const profile = await db.getUserProfile(userId);
108
return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(profile) }] };
109
}
110
);
111
112
// Repository files with template
113
server.registerResource('repo-file',
114
new ResourceTemplate('github://repos/{owner}/{repo}/files/{path}', { list: undefined }),
115
{ title: 'GitHub Repository File' },
116
async (uri, { owner, repo, path }) => {
117
const content = await github.getFile(owner, repo, path);
118
return { contents: [{ uri: uri.href, mimeType: 'text/plain', text: content }] };
119
}
120
);
121
122
// Template with listing
123
server.registerResource('project-files',
124
new ResourceTemplate('file:///project/{path}', {
125
list: async (cursor) => {
126
const files = await listProjectFiles(cursor);
127
return files.map(file => ({
128
uri: `file:///project/${file.path}`,
129
name: file.name,
130
description: file.description,
131
mimeType: file.mimeType
132
}));
133
}
134
}),
135
{ title: 'Project Files' },
136
async (uri, { path }) => {
137
const content = await fs.readFile(`/project/${path}`, 'utf-8');
138
return { contents: [{ uri: uri.href, text: content }] };
139
}
140
);
141
142
// Template with completion
143
server.registerResource('repository',
144
new ResourceTemplate('github://repos/{owner}/{repo}', {
145
list: undefined,
146
complete: {
147
repo: (value, context) => {
148
const owner = context?.arguments?.['owner'];
149
if (owner === 'anthropics') {
150
return ['claude-sdk', 'typescript-sdk', 'python-sdk'].filter(r => r.startsWith(value));
151
}
152
return ['default-repo'].filter(r => r.startsWith(value));
153
}
154
}
155
}),
156
{ title: 'GitHub Repository' },
157
async (uri, { owner, repo }) => ({
158
contents: [{ uri: uri.href, text: `Repository: ${owner}/${repo}` }]
159
})
160
);
161
```
162
163
## Return Values
164
165
```typescript { .api }
166
interface ReadResourceResult {
167
contents: ResourceContents[];
168
_meta?: Record<string, unknown>;
169
}
170
171
type ResourceContents = TextResourceContents | BlobResourceContents;
172
173
interface TextResourceContents {
174
uri: string;
175
mimeType?: string;
176
text: string;
177
}
178
179
interface BlobResourceContents {
180
uri: string;
181
mimeType?: string;
182
blob: string; // Base64 encoded
183
}
184
```
185
186
### Examples
187
188
```typescript
189
// Text resource
190
return {
191
contents: [{ uri: uri.href, mimeType: 'text/plain', text: 'Resource content here' }]
192
};
193
194
// JSON resource
195
return {
196
contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify({ key: 'value' }) }]
197
};
198
199
// Binary resource (image)
200
return {
201
contents: [{ uri: uri.href, mimeType: 'image/png', blob: base64EncodedImageData }]
202
};
203
204
// Multiple contents
205
return {
206
contents: [
207
{ uri: 'file:///project/README.md', mimeType: 'text/markdown', text: readmeContent },
208
{ uri: 'file:///project/LICENSE', mimeType: 'text/plain', text: licenseContent }
209
]
210
};
211
```
212
213
## Managing Resources
214
215
```typescript { .api }
216
interface RegisteredResource {
217
enable(): void;
218
disable(): void;
219
remove(): void;
220
}
221
222
interface RegisteredResourceTemplate {
223
enable(): void;
224
disable(): void;
225
remove(): void;
226
}
227
```
228
229
### Example
230
231
```typescript
232
const resource = server.registerResource('data', 'app://data', config, callback);
233
resource.disable();
234
resource.enable();
235
resource.remove();
236
```
237
238
## Subscriptions
239
240
Requires server capability declaration:
241
242
```typescript
243
const server = new McpServer(
244
{ name: 'my-server', version: '1.0.0' },
245
{
246
capabilities: {
247
resources: {
248
subscribe: true, // Enable subscriptions
249
listChanged: true // Enable list change notifications
250
}
251
}
252
}
253
);
254
```
255
256
### Notification Methods
257
258
```typescript { .api }
259
server.sendResourceUpdated(params: { uri: string }): Promise<void>;
260
server.sendResourceListChanged(): Promise<void>;
261
```
262
263
### Example
264
265
```typescript
266
// Notify about specific resource update
267
await server.sendResourceUpdated({ uri: 'config://app' });
268
269
// Notify that resource list changed
270
await server.sendResourceListChanged();
271
```
272
273
## Types Reference
274
275
```typescript { .api }
276
interface Resource {
277
uri: string;
278
name: string;
279
title?: string;
280
description?: string;
281
mimeType?: string;
282
icons?: Icons;
283
_meta?: Record<string, unknown>;
284
}
285
286
interface ResourceTemplate {
287
uriTemplate: string;
288
name: string;
289
title?: string;
290
description?: string;
291
mimeType?: string;
292
icons?: Icons;
293
_meta?: Record<string, unknown>;
294
}
295
296
interface ListResourcesResult {
297
resources: Resource[];
298
nextCursor?: string;
299
}
300
301
interface ListResourceTemplatesResult {
302
resourceTemplates: ResourceTemplate[];
303
nextCursor?: string;
304
}
305
306
interface Icons {
307
icon?: Icon;
308
light?: Icon;
309
dark?: Icon;
310
}
311
312
interface Icon {
313
src: string;
314
mimeType?: string;
315
size?: string;
316
}
317
```
318
319
## Legacy API
320
321
```typescript { .api }
322
server.resource(name: string, uri: string, readCallback: ReadResourceCallback): RegisteredResource;
323
server.resource(name: string, uri: string, metadata: ResourceMetadata, readCallback: ReadResourceCallback): RegisteredResource;
324
server.resource(name: string, template: ResourceTemplate, readCallback: ReadResourceTemplateCallback): RegisteredResourceTemplate;
325
server.resource(name: string, template: ResourceTemplate, metadata: ResourceMetadata, readCallback: ReadResourceTemplateCallback): RegisteredResourceTemplate;
326
```
327
328
Use `registerResource` for new code.
329