or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdclient.mdindex.mdserver-advanced.mdserver-prompts.mdserver-resources.mdserver-tools.mdtransports.mdtypes.md

server-resources.mddocs/

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