tmcp 1.15.4 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -35
- package/package.json +1 -1
- package/src/index.js +75 -148
- package/src/internal/internal.d.ts +6 -3
- package/src/types/index.d.ts +22 -5
- package/src/types/index.d.ts.map +4 -1
- package/src/validation/index.js +1 -2
package/README.md
CHANGED
|
@@ -129,6 +129,8 @@ server.tool(
|
|
|
129
129
|
);
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
`sessionInfo` contains the latest `clientCapabilities`, `clientInfo`, and `logLevel` reported by the connected client. Built-in transports populate it automatically, so every handler can branch on client features without additional bookkeeping.
|
|
133
|
+
|
|
132
134
|
##### `prompt(definition, handler)`
|
|
133
135
|
|
|
134
136
|
Register a prompt template with optional schema validation.
|
|
@@ -232,30 +234,34 @@ server.tool(
|
|
|
232
234
|
|
|
233
235
|
##### `ctx`
|
|
234
236
|
|
|
235
|
-
Access the current request context, including session ID, auth info, and custom context.
|
|
237
|
+
Access the current request context, including session ID, auth info, client metadata, and custom context.
|
|
236
238
|
|
|
237
239
|
```javascript
|
|
238
240
|
server.tool(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
241
|
+
{
|
|
242
|
+
name: 'context-aware-tool',
|
|
243
|
+
description: 'Tool that uses request context',
|
|
244
|
+
},
|
|
245
|
+
async () => {
|
|
246
|
+
const { sessionId, auth, sessionInfo, custom } = server.ctx;
|
|
247
|
+
|
|
248
|
+
if (!custom?.userId) {
|
|
249
|
+
throw new Error('User authentication required');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (sessionInfo?.clientInfo) {
|
|
253
|
+
console.log(`Serving ${sessionInfo.clientInfo.name}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
content: [
|
|
258
|
+
{
|
|
259
|
+
type: 'text',
|
|
260
|
+
text: `Hello user ${custom.userId} in session ${sessionId}`,
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
};
|
|
264
|
+
},
|
|
259
265
|
);
|
|
260
266
|
```
|
|
261
267
|
|
|
@@ -269,9 +275,14 @@ const response = server.receive(jsonRpcRequest);
|
|
|
269
275
|
|
|
270
276
|
// With custom context (typically used by transports)
|
|
271
277
|
const response = server.receive(jsonRpcRequest, {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
278
|
+
sessionId: 'session-123',
|
|
279
|
+
auth: authInfo,
|
|
280
|
+
sessionInfo: {
|
|
281
|
+
clientCapabilities,
|
|
282
|
+
clientInfo,
|
|
283
|
+
logLevel,
|
|
284
|
+
},
|
|
285
|
+
custom: customContextData,
|
|
275
286
|
});
|
|
276
287
|
```
|
|
277
288
|
|
|
@@ -309,7 +320,7 @@ console.log(server.roots); // Access current roots
|
|
|
309
320
|
|
|
310
321
|
##### `changed(type, id)`
|
|
311
322
|
|
|
312
|
-
Send notifications for subscriptions.
|
|
323
|
+
Send notifications for subscriptions. When you call `changed('resource', uri)` the server now emits a broadcast notification, and the built-in transports look up which sessions subscribed to that URI before delivering it.
|
|
313
324
|
|
|
314
325
|
```javascript
|
|
315
326
|
server.changed('resource', 'file://path/to/resource');
|
|
@@ -380,13 +391,25 @@ server.log('error', 'Failed to connect to database', 'database-logger');
|
|
|
380
391
|
|
|
381
392
|
Listen to server events.
|
|
382
393
|
|
|
394
|
+
Available events:
|
|
395
|
+
|
|
396
|
+
- `initialize` – fired after the client handshake with the parsed initialize payload
|
|
397
|
+
- `send` – emitted for point-to-point responses/notifications destined for the active session
|
|
398
|
+
- `broadcast` – emitted for fan-out notifications (for example `notifications/resources/updated`)
|
|
399
|
+
- `subscription` – raised when the client subscribes to a resource URI
|
|
400
|
+
- `loglevelchange` – fired when the client requests a different log level
|
|
401
|
+
|
|
383
402
|
```javascript
|
|
384
|
-
server.on('initialize', (
|
|
385
|
-
console.log('Client initialized:',
|
|
403
|
+
server.on('initialize', ({ clientInfo }) => {
|
|
404
|
+
console.log('Client initialized:', clientInfo?.name);
|
|
386
405
|
});
|
|
387
406
|
|
|
388
|
-
server.on('send', ({ request
|
|
389
|
-
console.log('Sending
|
|
407
|
+
server.on('send', ({ request }) => {
|
|
408
|
+
console.log('Sending message:', request);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
server.on('broadcast', ({ request }) => {
|
|
412
|
+
console.log('Broadcasting:', request.method);
|
|
390
413
|
});
|
|
391
414
|
```
|
|
392
415
|
|
|
@@ -516,9 +539,15 @@ server.on('initialize', (data) => {
|
|
|
516
539
|
console.log('Client capabilities:', data.capabilities);
|
|
517
540
|
});
|
|
518
541
|
|
|
519
|
-
server.on('send', ({ request
|
|
542
|
+
server.on('send', ({ request }) => {
|
|
520
543
|
console.log('Outgoing request:', request.method);
|
|
521
544
|
});
|
|
545
|
+
|
|
546
|
+
server.on('broadcast', ({ request }) => {
|
|
547
|
+
if (request.method === 'notifications/resources/updated') {
|
|
548
|
+
console.log('Resource updated:', request.params.uri);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
522
551
|
```
|
|
523
552
|
|
|
524
553
|
### Resource Subscriptions
|
|
@@ -923,7 +952,7 @@ server.prompt(
|
|
|
923
952
|
);
|
|
924
953
|
```
|
|
925
954
|
|
|
926
|
-
or enable
|
|
955
|
+
or enable something based on client capabilities or info
|
|
927
956
|
|
|
928
957
|
```javascript
|
|
929
958
|
server.prompt(
|
|
@@ -932,8 +961,8 @@ server.prompt(
|
|
|
932
961
|
description: 'Claude Code prompt',
|
|
933
962
|
enabled: () => {
|
|
934
963
|
// Access session information
|
|
935
|
-
const clientInfo = server.
|
|
936
|
-
return clientInfo
|
|
964
|
+
const clientInfo = server.ctx.sessionInfo?.clientInfo;
|
|
965
|
+
return clientInfo?.name === 'Claude Code';
|
|
937
966
|
},
|
|
938
967
|
},
|
|
939
968
|
async (input) => {
|
|
@@ -958,8 +987,9 @@ server.prompt(
|
|
|
958
987
|
description: 'fetch the repositories of the user',
|
|
959
988
|
enabled: () => {
|
|
960
989
|
// Access session information
|
|
961
|
-
const
|
|
962
|
-
|
|
990
|
+
const clientCapabilities =
|
|
991
|
+
server.ctx.sessionInfo?.clientCapabilities;
|
|
992
|
+
return clientCapabilities?.elicitation != null;
|
|
963
993
|
},
|
|
964
994
|
},
|
|
965
995
|
async (input) => {
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -49,6 +49,7 @@ import { should_version_negotiation_fail } from './validation/version.js';
|
|
|
49
49
|
* @template {Record<string, unknown> | undefined} [TCustom=undefined]
|
|
50
50
|
* @typedef {Object} Context
|
|
51
51
|
* @property {string} [sessionId]
|
|
52
|
+
* @property {{ clientCapabilities?: ClientCapabilitiesType, clientInfo?: ClientInfoType, logLevel?: LoggingLevel }} [sessionInfo]
|
|
52
53
|
* @property {AuthInfo} [auth]
|
|
53
54
|
* @property {TCustom} [custom]
|
|
54
55
|
*/
|
|
@@ -57,6 +58,10 @@ import { should_version_negotiation_fail } from './validation/version.js';
|
|
|
57
58
|
* @typedef {IconsType} Icons
|
|
58
59
|
*/
|
|
59
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {Record<SubscriptionsKeys, string[]>} Subscriptions
|
|
63
|
+
*/
|
|
64
|
+
|
|
60
65
|
/**
|
|
61
66
|
* @template {Record<string, unknown> | undefined} TStructuredContent
|
|
62
67
|
* @typedef {CallToolResultType<TStructuredContent>} CallToolResult
|
|
@@ -149,7 +154,7 @@ async function safe_enabled(enabled) {
|
|
|
149
154
|
export class McpServer {
|
|
150
155
|
#server = new JSONRPCServer();
|
|
151
156
|
/**
|
|
152
|
-
* @type {JSONRPCClient<
|
|
157
|
+
* @type {JSONRPCClient<"broadcast" | "standalone"> | undefined}
|
|
153
158
|
*/
|
|
154
159
|
#client;
|
|
155
160
|
#options;
|
|
@@ -180,41 +185,11 @@ export class McpServer {
|
|
|
180
185
|
|
|
181
186
|
#event_target = new EventTarget();
|
|
182
187
|
|
|
183
|
-
/**
|
|
184
|
-
* @type {Record<SubscriptionsKeys, Map<string, Set<string | undefined>>>}
|
|
185
|
-
*/
|
|
186
|
-
#subscriptions = {
|
|
187
|
-
/**
|
|
188
|
-
* @type {Map<string, Set<string>>}
|
|
189
|
-
*/
|
|
190
|
-
resource: new Map(),
|
|
191
|
-
};
|
|
192
|
-
|
|
193
188
|
/**
|
|
194
189
|
* @type {AsyncLocalStorage<Context<CustomContext> & { progress_token?: string }>}
|
|
195
190
|
*/
|
|
196
191
|
#ctx_storage = new AsyncLocalStorage();
|
|
197
192
|
|
|
198
|
-
/**
|
|
199
|
-
* @type {Map<string|undefined, ClientCapabilities>}
|
|
200
|
-
*/
|
|
201
|
-
#client_capabilities_map = new Map();
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* @type {Map<string|undefined, ClientInfo>}
|
|
205
|
-
*/
|
|
206
|
-
#client_info_map = new Map();
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* @type {Map<string|undefined, string>}
|
|
210
|
-
*/
|
|
211
|
-
#negotiated_protocol_versions = new Map();
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* @type {Map<string|undefined, LoggingLevel>}
|
|
215
|
-
*/
|
|
216
|
-
#session_log_levels = new Map();
|
|
217
|
-
|
|
218
193
|
/**
|
|
219
194
|
* @param {ServerInfo} server_info
|
|
220
195
|
* @param {ServerOptions<StandardSchema>} options
|
|
@@ -229,8 +204,6 @@ export class McpServer {
|
|
|
229
204
|
initialize_request,
|
|
230
205
|
);
|
|
231
206
|
|
|
232
|
-
const session_id = this.#session_id;
|
|
233
|
-
|
|
234
207
|
// Validate protocol version format
|
|
235
208
|
if (
|
|
236
209
|
should_version_negotiation_fail(
|
|
@@ -250,24 +223,6 @@ export class McpServer {
|
|
|
250
223
|
validated_initialize.protocolVersion,
|
|
251
224
|
);
|
|
252
225
|
|
|
253
|
-
// Store negotiated protocol version
|
|
254
|
-
this.#negotiated_protocol_versions.set(
|
|
255
|
-
session_id,
|
|
256
|
-
negotiated_version,
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
// Store client capabilities
|
|
260
|
-
this.#client_capabilities_map.set(
|
|
261
|
-
session_id,
|
|
262
|
-
validated_initialize.capabilities,
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
// Store client info
|
|
266
|
-
this.#client_info_map.set(
|
|
267
|
-
session_id,
|
|
268
|
-
validated_initialize.clientInfo,
|
|
269
|
-
);
|
|
270
|
-
|
|
271
226
|
// Dispatch initialization event
|
|
272
227
|
this.#event_target.dispatchEvent(
|
|
273
228
|
new CustomEvent('initialize', {
|
|
@@ -335,10 +290,6 @@ export class McpServer {
|
|
|
335
290
|
);
|
|
336
291
|
}
|
|
337
292
|
|
|
338
|
-
get #session_id() {
|
|
339
|
-
return this.#ctx_storage.getStore()?.sessionId;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
293
|
get #progress_token() {
|
|
343
294
|
return this.#ctx_storage.getStore()?.progress_token;
|
|
344
295
|
}
|
|
@@ -354,18 +305,20 @@ export class McpServer {
|
|
|
354
305
|
}
|
|
355
306
|
|
|
356
307
|
get #client_capabilities() {
|
|
357
|
-
return this.#
|
|
308
|
+
return this.#ctx_storage.getStore()?.sessionInfo?.clientCapabilities;
|
|
358
309
|
}
|
|
359
310
|
|
|
360
311
|
/**
|
|
361
312
|
* Get the client information (name, version, etc.) of the client that initiated the current request...useful if you want to do something different based on the client.
|
|
313
|
+
* @deprecated Use `server.ctx.sessionInfo.clientInfo` instead.
|
|
362
314
|
*/
|
|
363
315
|
currentClientInfo() {
|
|
364
|
-
return this.#
|
|
316
|
+
return this.#ctx_storage.getStore()?.sessionInfo?.clientInfo;
|
|
365
317
|
}
|
|
366
318
|
|
|
367
319
|
/**
|
|
368
320
|
* Get the client capabilities of the client that initiated the current request, you can use this to verify the client support something before invoking the respective method.
|
|
321
|
+
* @deprecated Use `server.ctx.sessionInfo.clientCapabilities` instead.
|
|
369
322
|
*/
|
|
370
323
|
currentClientCapabilities() {
|
|
371
324
|
return this.#client_capabilities;
|
|
@@ -373,10 +326,18 @@ export class McpServer {
|
|
|
373
326
|
|
|
374
327
|
#lazyily_create_client() {
|
|
375
328
|
if (!this.#client) {
|
|
376
|
-
this.#client = new JSONRPCClient((payload,
|
|
329
|
+
this.#client = new JSONRPCClient((payload, kind) => {
|
|
330
|
+
if (kind === 'broadcast') {
|
|
331
|
+
this.#event_target.dispatchEvent(
|
|
332
|
+
new CustomEvent('broadcast', {
|
|
333
|
+
detail: { request: payload },
|
|
334
|
+
}),
|
|
335
|
+
);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
377
338
|
this.#event_target.dispatchEvent(
|
|
378
339
|
new CustomEvent('send', {
|
|
379
|
-
detail: { request: payload
|
|
340
|
+
detail: { request: payload },
|
|
380
341
|
}),
|
|
381
342
|
);
|
|
382
343
|
});
|
|
@@ -390,7 +351,7 @@ export class McpServer {
|
|
|
390
351
|
* @param {AddEventListenerOptions} [options]
|
|
391
352
|
*/
|
|
392
353
|
on(event, callback, options) {
|
|
393
|
-
if (event === 'send') {
|
|
354
|
+
if (event === 'send' || event === 'broadcast') {
|
|
394
355
|
this.#lazyily_create_client();
|
|
395
356
|
}
|
|
396
357
|
|
|
@@ -411,10 +372,10 @@ export class McpServer {
|
|
|
411
372
|
/**
|
|
412
373
|
* @param {string} method
|
|
413
374
|
* @param {JSONRPCParams} [params]
|
|
414
|
-
* @param {
|
|
375
|
+
* @param {"broadcast" | "standalone"} [kind]
|
|
415
376
|
*/
|
|
416
|
-
#notify(method, params,
|
|
417
|
-
this.#client?.notify(method, params,
|
|
377
|
+
#notify(method, params, kind = 'standalone') {
|
|
378
|
+
this.#client?.notify(method, params, kind);
|
|
418
379
|
}
|
|
419
380
|
|
|
420
381
|
/**
|
|
@@ -436,6 +397,7 @@ export class McpServer {
|
|
|
436
397
|
title: tool.title || tool.description,
|
|
437
398
|
description: tool.description,
|
|
438
399
|
icons: tool.icons,
|
|
400
|
+
_meta: tool._meta,
|
|
439
401
|
inputSchema: tool.schema
|
|
440
402
|
? await this.#options.adapter.toJsonSchema(
|
|
441
403
|
tool.schema,
|
|
@@ -648,12 +610,11 @@ export class McpServer {
|
|
|
648
610
|
|
|
649
611
|
if (this.#options.capabilities?.resources?.subscribe) {
|
|
650
612
|
this.#server.addMethod('resources/subscribe', async ({ uri }) => {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
subscriptions.add(this.#session_id);
|
|
613
|
+
this.#event_target.dispatchEvent(
|
|
614
|
+
new CustomEvent('subscription', {
|
|
615
|
+
detail: { uri },
|
|
616
|
+
}),
|
|
617
|
+
);
|
|
657
618
|
return {};
|
|
658
619
|
});
|
|
659
620
|
}
|
|
@@ -797,9 +758,7 @@ export class McpServer {
|
|
|
797
758
|
const response = await this.#client?.request(
|
|
798
759
|
'roots/list',
|
|
799
760
|
undefined,
|
|
800
|
-
|
|
801
|
-
sessions: [this.#session_id],
|
|
802
|
-
},
|
|
761
|
+
'standalone',
|
|
803
762
|
);
|
|
804
763
|
this.roots = response?.roots || [];
|
|
805
764
|
} catch {
|
|
@@ -830,26 +789,34 @@ export class McpServer {
|
|
|
830
789
|
if (!this.#options.capabilities?.logging) return;
|
|
831
790
|
|
|
832
791
|
this.#server.addMethod('logging/setLevel', ({ level }) => {
|
|
833
|
-
this.#
|
|
792
|
+
this.#event_target.dispatchEvent(
|
|
793
|
+
new CustomEvent('loglevelchange', {
|
|
794
|
+
detail: { level },
|
|
795
|
+
}),
|
|
796
|
+
);
|
|
834
797
|
return {};
|
|
835
798
|
});
|
|
836
799
|
}
|
|
837
800
|
|
|
838
801
|
#notify_tools_list_changed() {
|
|
839
802
|
if (this.#options.capabilities?.tools?.listChanged) {
|
|
840
|
-
this.#notify('notifications/tools/list_changed', {});
|
|
803
|
+
this.#notify('notifications/tools/list_changed', {}, 'broadcast');
|
|
841
804
|
}
|
|
842
805
|
}
|
|
843
806
|
|
|
844
807
|
#notify_prompts_list_changed() {
|
|
845
808
|
if (this.#options.capabilities?.prompts?.listChanged) {
|
|
846
|
-
this.#notify('notifications/prompts/list_changed', {});
|
|
809
|
+
this.#notify('notifications/prompts/list_changed', {}, 'broadcast');
|
|
847
810
|
}
|
|
848
811
|
}
|
|
849
812
|
|
|
850
813
|
#notify_resources_list_changed() {
|
|
851
814
|
if (this.#options.capabilities?.resources?.listChanged) {
|
|
852
|
-
this.#notify(
|
|
815
|
+
this.#notify(
|
|
816
|
+
'notifications/resources/list_changed',
|
|
817
|
+
{},
|
|
818
|
+
'broadcast',
|
|
819
|
+
);
|
|
853
820
|
}
|
|
854
821
|
}
|
|
855
822
|
|
|
@@ -860,7 +827,7 @@ export class McpServer {
|
|
|
860
827
|
* Tools will be invoked by the LLM when it thinks it needs to use them, you can use the annotations to provide additional information about the tool, like what it does, how to use it, etc.
|
|
861
828
|
* @template {StandardSchema | undefined} [TSchema=undefined]
|
|
862
829
|
* @template {StandardSchema | undefined} [TOutputSchema=undefined]
|
|
863
|
-
* @param {{ name: string; description: string; title?: string; enabled?: ()=>boolean | Promise<boolean>; schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never; outputSchema?: StandardSchemaV1.InferOutput<TOutputSchema extends undefined ? never : TOutputSchema> extends Record<string, unknown> ? TOutputSchema : never; annotations?: ToolAnnotations } & Icons} options
|
|
830
|
+
* @param {{ name: string; _meta?: Record<string, any>; description: string; title?: string; enabled?: ()=>boolean | Promise<boolean>; schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never; outputSchema?: StandardSchemaV1.InferOutput<TOutputSchema extends undefined ? never : TOutputSchema> extends Record<string, unknown> ? TOutputSchema : never; annotations?: ToolAnnotations } & Icons} options
|
|
864
831
|
* @param {TSchema extends undefined ? (()=>Promise<CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>> | CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>) : ((input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>> | CallToolResult<TOutputSchema extends undefined ? undefined : StandardSchemaV1.InferInput<TOutputSchema extends undefined ? never : TOutputSchema>>)} execute
|
|
865
832
|
*/
|
|
866
833
|
tool(
|
|
@@ -873,6 +840,7 @@ export class McpServer {
|
|
|
873
840
|
annotations,
|
|
874
841
|
enabled,
|
|
875
842
|
icons,
|
|
843
|
+
_meta,
|
|
876
844
|
},
|
|
877
845
|
execute,
|
|
878
846
|
) {
|
|
@@ -886,6 +854,7 @@ export class McpServer {
|
|
|
886
854
|
execute,
|
|
887
855
|
annotations,
|
|
888
856
|
icons,
|
|
857
|
+
_meta,
|
|
889
858
|
});
|
|
890
859
|
}
|
|
891
860
|
/**
|
|
@@ -1000,18 +969,6 @@ export class McpServer {
|
|
|
1000
969
|
|
|
1001
970
|
// Check if it's a request or response
|
|
1002
971
|
if (validated_message.success) {
|
|
1003
|
-
// we want to set a default log level for each session
|
|
1004
|
-
// so that if the user calls `log` it can send a notification
|
|
1005
|
-
// to each client that didn't explicitly set a log level too
|
|
1006
|
-
if (
|
|
1007
|
-
!!this.#options.capabilities?.logging &&
|
|
1008
|
-
!this.#session_log_levels.has(ctx?.sessionId)
|
|
1009
|
-
) {
|
|
1010
|
-
this.#session_log_levels.set(
|
|
1011
|
-
ctx?.sessionId,
|
|
1012
|
-
this.#options.logging?.default ?? 'info',
|
|
1013
|
-
);
|
|
1014
|
-
}
|
|
1015
972
|
const progress_token = /** @type {string | undefined} */ (
|
|
1016
973
|
validated_message.output.params?._meta?.progressToken
|
|
1017
974
|
);
|
|
@@ -1046,28 +1003,16 @@ export class McpServer {
|
|
|
1046
1003
|
} else if (what === 'resources') {
|
|
1047
1004
|
this.#notify_resources_list_changed();
|
|
1048
1005
|
} else {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
].get(id);
|
|
1060
|
-
this.#notify(
|
|
1061
|
-
`notifications/resources/updated`,
|
|
1062
|
-
{
|
|
1063
|
-
uri: id,
|
|
1064
|
-
title: resource.name,
|
|
1065
|
-
},
|
|
1066
|
-
{
|
|
1067
|
-
sessions: sessions ? [...sessions] : undefined,
|
|
1068
|
-
},
|
|
1069
|
-
);
|
|
1070
|
-
}
|
|
1006
|
+
const resource = this.#resources.get(id);
|
|
1007
|
+
if (!resource) return;
|
|
1008
|
+
this.#notify(
|
|
1009
|
+
`notifications/resources/updated`,
|
|
1010
|
+
{
|
|
1011
|
+
uri: id,
|
|
1012
|
+
title: resource.name,
|
|
1013
|
+
},
|
|
1014
|
+
'broadcast',
|
|
1015
|
+
);
|
|
1071
1016
|
}
|
|
1072
1017
|
}
|
|
1073
1018
|
|
|
@@ -1102,9 +1047,7 @@ export class McpServer {
|
|
|
1102
1047
|
requestedSchema:
|
|
1103
1048
|
await this.#options.adapter.toJsonSchema(schema),
|
|
1104
1049
|
},
|
|
1105
|
-
|
|
1106
|
-
sessions: [this.#session_id],
|
|
1107
|
-
},
|
|
1050
|
+
'standalone',
|
|
1108
1051
|
);
|
|
1109
1052
|
const elicit_result = v.parse(ElicitResultSchema, result);
|
|
1110
1053
|
let validated_result = schema['~standard'].validate(
|
|
@@ -1142,9 +1085,7 @@ export class McpServer {
|
|
|
1142
1085
|
const response = await this.#client?.request(
|
|
1143
1086
|
'sampling/createMessage',
|
|
1144
1087
|
validated_request,
|
|
1145
|
-
|
|
1146
|
-
sessions: [this.#session_id],
|
|
1147
|
-
},
|
|
1088
|
+
'standalone',
|
|
1148
1089
|
);
|
|
1149
1090
|
|
|
1150
1091
|
// Validate and return the response
|
|
@@ -1160,18 +1101,12 @@ export class McpServer {
|
|
|
1160
1101
|
*/
|
|
1161
1102
|
progress(progress, total = 1, message = undefined) {
|
|
1162
1103
|
if (this.#progress_token != null) {
|
|
1163
|
-
this.#notify(
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
progressToken: this.#progress_token,
|
|
1170
|
-
},
|
|
1171
|
-
{
|
|
1172
|
-
sessions: this.#session_id ? [this.#session_id] : undefined,
|
|
1173
|
-
},
|
|
1174
|
-
);
|
|
1104
|
+
this.#notify('notifications/progress', {
|
|
1105
|
+
progress,
|
|
1106
|
+
total,
|
|
1107
|
+
message,
|
|
1108
|
+
progressToken: this.#progress_token,
|
|
1109
|
+
});
|
|
1175
1110
|
}
|
|
1176
1111
|
}
|
|
1177
1112
|
|
|
@@ -1190,29 +1125,21 @@ export class McpServer {
|
|
|
1190
1125
|
);
|
|
1191
1126
|
}
|
|
1192
1127
|
|
|
1193
|
-
const
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
if (this.#should_log(level, session_log_level)) {
|
|
1198
|
-
sessions.push(session_id);
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
if (sessions.length === 0) return;
|
|
1128
|
+
const current_session_level =
|
|
1129
|
+
this.#ctx_storage.getStore()?.sessionInfo?.logLevel ??
|
|
1130
|
+
this.#options.logging?.default ??
|
|
1131
|
+
'info';
|
|
1203
1132
|
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1133
|
+
if (
|
|
1134
|
+
current_session_level &&
|
|
1135
|
+
this.#should_log(level, current_session_level)
|
|
1136
|
+
) {
|
|
1137
|
+
this.#notify('notifications/message', {
|
|
1208
1138
|
level,
|
|
1209
1139
|
data,
|
|
1210
1140
|
logger,
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
sessions,
|
|
1214
|
-
},
|
|
1215
|
-
);
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1216
1143
|
}
|
|
1217
1144
|
|
|
1218
1145
|
/**
|
|
@@ -20,6 +20,7 @@ export type Tool<TSchema extends StandardSchemaV1 = StandardSchemaV1<any>, TOutp
|
|
|
20
20
|
outputSchema?: TOutputSchema;
|
|
21
21
|
title?: string;
|
|
22
22
|
annotations?: ToolAnnotations;
|
|
23
|
+
_meta?: Record<string, unknown>;
|
|
23
24
|
enabled?: () => boolean | Promise<boolean>;
|
|
24
25
|
execute: (
|
|
25
26
|
input?: StandardSchemaV1.InferInput<TSchema>,
|
|
@@ -96,9 +97,11 @@ export type SubscriptionsKeys = SubscriptionsKeysObj["with_args"];
|
|
|
96
97
|
export type McpEvents = {
|
|
97
98
|
send: (message: {
|
|
98
99
|
request: JSONRPCRequest;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
}) => void;
|
|
101
|
+
broadcast: (message: {
|
|
102
|
+
request: JSONRPCRequest;
|
|
102
103
|
}) => void;
|
|
103
104
|
initialize: (initialize_request: InitializeRequestParams) => void;
|
|
105
|
+
subscription: (subscriptions_request: { uri: string }) => void;
|
|
106
|
+
loglevelchange: (change: { level: LoggingLevel }) => void;
|
|
104
107
|
};
|
package/src/types/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ declare module 'tmcp' {
|
|
|
23
23
|
get ctx(): Context<CustomContext>;
|
|
24
24
|
/**
|
|
25
25
|
* Get the client information (name, version, etc.) of the client that initiated the current request...useful if you want to do something different based on the client.
|
|
26
|
+
* @deprecated Use `server.ctx.sessionInfo.clientInfo` instead.
|
|
26
27
|
*/
|
|
27
28
|
currentClientInfo(): {
|
|
28
29
|
icons?: {
|
|
@@ -37,6 +38,7 @@ declare module 'tmcp' {
|
|
|
37
38
|
} | undefined;
|
|
38
39
|
/**
|
|
39
40
|
* Get the client capabilities of the client that initiated the current request, you can use this to verify the client support something before invoking the respective method.
|
|
41
|
+
* @deprecated Use `server.ctx.sessionInfo.clientCapabilities` instead.
|
|
40
42
|
*/
|
|
41
43
|
currentClientCapabilities(): {
|
|
42
44
|
experimental?: {} | undefined;
|
|
@@ -54,8 +56,9 @@ declare module 'tmcp' {
|
|
|
54
56
|
*
|
|
55
57
|
* Tools will be invoked by the LLM when it thinks it needs to use them, you can use the annotations to provide additional information about the tool, like what it does, how to use it, etc.
|
|
56
58
|
* */
|
|
57
|
-
tool<TSchema extends StandardSchema | undefined = undefined, TOutputSchema extends StandardSchema | undefined = undefined>({ name, description, title, schema, outputSchema, annotations, enabled, icons, }: {
|
|
59
|
+
tool<TSchema extends StandardSchema | undefined = undefined, TOutputSchema extends StandardSchema | undefined = undefined>({ name, description, title, schema, outputSchema, annotations, enabled, icons, _meta, }: {
|
|
58
60
|
name: string;
|
|
61
|
+
_meta?: Record<string, any>;
|
|
59
62
|
description: string;
|
|
60
63
|
title?: string;
|
|
61
64
|
enabled?: () => boolean | Promise<boolean>;
|
|
@@ -182,10 +185,16 @@ declare module 'tmcp' {
|
|
|
182
185
|
};
|
|
183
186
|
export type Context<TCustom extends Record<string, unknown> | undefined = undefined> = {
|
|
184
187
|
sessionId?: string | undefined;
|
|
188
|
+
sessionInfo?: {
|
|
189
|
+
clientCapabilities?: ClientCapabilities_1;
|
|
190
|
+
clientInfo?: ClientInfo_1;
|
|
191
|
+
logLevel?: LoggingLevel;
|
|
192
|
+
} | undefined;
|
|
185
193
|
auth?: AuthInfo | undefined;
|
|
186
194
|
custom?: TCustom | undefined;
|
|
187
195
|
};
|
|
188
196
|
export type Icons = Icons_1;
|
|
197
|
+
export type Subscriptions = Record<SubscriptionsKeys, string[]>;
|
|
189
198
|
export type CallToolResult<TStructuredContent extends Record<string, unknown> | undefined> = CallToolResult_1<TStructuredContent>;
|
|
190
199
|
export type ReadResourceResult = ReadResourceResult_1;
|
|
191
200
|
export type GetPromptResult = GetPromptResult_1;
|
|
@@ -222,14 +231,22 @@ declare module 'tmcp' {
|
|
|
222
231
|
'resources': [];
|
|
223
232
|
}
|
|
224
233
|
|
|
234
|
+
type SubscriptionsKeysObj = {
|
|
235
|
+
[K in keyof ChangedArgs as ChangedArgs[K]["length"] extends 0 ? "without_args" : "with_args"]: K
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
type SubscriptionsKeys = SubscriptionsKeysObj["with_args"];
|
|
239
|
+
|
|
225
240
|
type McpEvents = {
|
|
226
241
|
send: (message: {
|
|
227
242
|
request: JSONRPCRequest;
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
243
|
+
}) => void;
|
|
244
|
+
broadcast: (message: {
|
|
245
|
+
request: JSONRPCRequest;
|
|
231
246
|
}) => void;
|
|
232
247
|
initialize: (initialize_request: InitializeRequestParams) => void;
|
|
248
|
+
subscription: (subscriptions_request: { uri: string }) => void;
|
|
249
|
+
loglevelchange: (change: { level: LoggingLevel_1 }) => void;
|
|
233
250
|
};
|
|
234
251
|
/**
|
|
235
252
|
* A successful (non-error) response to a request.
|
|
@@ -237,7 +254,7 @@ declare module 'tmcp' {
|
|
|
237
254
|
const JSONRPCResponseSchema: v.StrictObjectSchema<{
|
|
238
255
|
readonly jsonrpc: v.LiteralSchema<"2.0", undefined>;
|
|
239
256
|
readonly id: v.UnionSchema<[v.StringSchema<undefined>, v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>]>], undefined>;
|
|
240
|
-
readonly result: v.
|
|
257
|
+
readonly result: v.LooseObjectSchema<{
|
|
241
258
|
/**
|
|
242
259
|
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
|
|
243
260
|
* for notes on _meta usage.
|
package/src/types/index.d.ts.map
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"names": [
|
|
5
5
|
"McpServer",
|
|
6
6
|
"Icons",
|
|
7
|
+
"Subscriptions",
|
|
7
8
|
"ReadResourceResult",
|
|
8
9
|
"GetPromptResult",
|
|
9
10
|
"ClientCapabilities",
|
|
@@ -17,6 +18,8 @@
|
|
|
17
18
|
"Completion",
|
|
18
19
|
"ServerOptions",
|
|
19
20
|
"ChangedArgs",
|
|
21
|
+
"SubscriptionsKeysObj",
|
|
22
|
+
"SubscriptionsKeys",
|
|
20
23
|
"McpEvents",
|
|
21
24
|
"JSONRPCResponseSchema",
|
|
22
25
|
"IconsSchema",
|
|
@@ -61,6 +64,6 @@
|
|
|
61
64
|
null,
|
|
62
65
|
null
|
|
63
66
|
],
|
|
64
|
-
"mappings": ";;;;;
|
|
67
|
+
"mappings": ";;;;;cAyJaA,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCw1CyBC,KAAKA;aDp7CFC,aAAaA;;aC28CHC,kBAAkBA;aAGrBC,eAAeA;aAvBZC,kBAAkBA;aAUKC,UAAUA;aAmBzBC,0BAA0BA;aAGjCC,mBAAmBA;aAY9BC,QAAQA;aASJC,YAAYA;aA/CVC,UAAUA;aAqDZC,YAAYA;MClhDtDC,UAAUA;;;;;MAyCVC,aAAaA;;;;;;;;;;;;;MAabC,WAAWA;;;;;;;MAOlBC,oBAAoBA;;;;MAIbC,iBAAiBA;;MAEjBC,SAASA;;;;;;;;;;;;;;ODGRC,qBAAqBA;;;;;;;;;;;OAgHrBC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoBXC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAUpBC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;OA6BxBC,6BAA6BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuB7BC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmMxBC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8GdC,wBAAwBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+PxBC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BrBC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4GrBC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoEpBC,kBAAkBA;OAuGlBC,gCAAgCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8ChCC,yBAAyBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6GzBC,kBAAkBA;;;;;;;;;;;;;;;;;;OAkFlBC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;MAiI2BC,kBAAkBA;;;;;MAUbC,uBAAuBA;;;;;;;;;;;;;MAahCC,cAAcA;;;;MAwBbC,eAAeA;;MAMfC,eAAeA;;;ME3iDnEC,IAAIA;;;;;;;MAOJC,cAAcA;;;;;;;MAOdC,cAAcA;;;;;MAKdC,qBAAqBA;;;;;;;;;;;;;;;;;MAiBrBC,4BAA4BA;;;;;;MAMrBC,2BAA2BA;;;;;;;OCjC1BC,iBAAiBA;;;;;;;;;;;;;;;;cAAjBA,iBAAiBA",
|
|
65
68
|
"ignoreList": []
|
|
66
69
|
}
|
package/src/validation/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable jsdoc/no-undefined-types */
|
|
2
1
|
import * as v from 'valibot';
|
|
3
2
|
export const LATEST_PROTOCOL_VERSION = '2025-06-18';
|
|
4
3
|
export const DEFAULT_NEGOTIATED_PROTOCOL_VERSION = '2025-03-26';
|
|
@@ -62,7 +61,7 @@ export const NotificationSchema = v.object({
|
|
|
62
61
|
method: v.string(),
|
|
63
62
|
params: v.optional(BaseNotificationParamsSchema),
|
|
64
63
|
});
|
|
65
|
-
export const ResultSchema = v.
|
|
64
|
+
export const ResultSchema = v.looseObject({
|
|
66
65
|
/**
|
|
67
66
|
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
|
|
68
67
|
* for notes on _meta usage.
|