tmcp 1.1.0 → 1.2.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/package.json +6 -1
- package/src/index.d.ts +13 -10
- package/src/index.js +36 -23
- package/src/internal/internal.d.ts +17 -7
- package/src/internal/uri-template.d.ts +45 -0
package/package.json
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tmcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "The main tmcp library",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [],
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/paoloricciuti/tmcp.git",
|
|
11
|
+
"directory": "packages/tmcp"
|
|
12
|
+
},
|
|
8
13
|
"author": "Paolo Ricciuti",
|
|
9
14
|
"license": "MIT",
|
|
10
15
|
"files": [
|
package/src/index.d.ts
CHANGED
|
@@ -26,34 +26,36 @@ export class McpServer<StandardSchema extends StandardSchemaV1> {
|
|
|
26
26
|
}, execute: TSchema extends undefined ? (() => Promise<unknown> | unknown) : ((input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<unknown> | unknown)): void;
|
|
27
27
|
/**
|
|
28
28
|
* @template {StandardSchema | undefined} [TSchema=undefined]
|
|
29
|
-
* @param {{ name: string; description: string; schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never; complete?: Completion }} options
|
|
29
|
+
* @param {{ name: string; description: string; schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never; complete?: TSchema extends undefined ? never : Partial<Record<keyof (StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>), Completion>> }} options
|
|
30
30
|
* @param {TSchema extends undefined ? (()=>Promise<unknown> | unknown) : (input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<unknown> | unknown} execute
|
|
31
31
|
*/
|
|
32
32
|
prompt<TSchema extends StandardSchema | undefined = undefined>({ name, description, schema, complete }: {
|
|
33
33
|
name: string;
|
|
34
34
|
description: string;
|
|
35
35
|
schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never;
|
|
36
|
-
complete?: Completion
|
|
36
|
+
complete?: TSchema extends undefined ? never : Partial<Record<keyof StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>, Completion>>;
|
|
37
37
|
}, execute: TSchema extends undefined ? (() => Promise<unknown> | unknown) : (input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<unknown> | unknown): void;
|
|
38
38
|
/**
|
|
39
39
|
* @param {{ name: string; description: string; uri: string }} options
|
|
40
|
-
* @param {(uri: string
|
|
40
|
+
* @param {(uri: string) => Promise<unknown> | unknown} execute
|
|
41
41
|
*/
|
|
42
42
|
resource({ name, description, uri }: {
|
|
43
43
|
name: string;
|
|
44
44
|
description: string;
|
|
45
45
|
uri: string;
|
|
46
|
-
}, execute: (uri: string
|
|
46
|
+
}, execute: (uri: string) => Promise<unknown> | unknown): void;
|
|
47
47
|
/**
|
|
48
|
-
* @
|
|
49
|
-
* @
|
|
48
|
+
* @template {string} TUri
|
|
49
|
+
* @template {ExtractURITemplateVariables<TUri>} TVariables
|
|
50
|
+
* @param {{ name: string; description: string; uri: TUri; complete?: TVariables extends never ? never : Partial<Record<TVariables, Completion>> }} options
|
|
51
|
+
* @param {(uri: string, params: Record<TVariables, string | string[]>) => Promise<unknown> | unknown} execute
|
|
50
52
|
*/
|
|
51
|
-
template({ name, description, uri, complete }: {
|
|
53
|
+
template<TUri extends string, TVariables extends ExtractURITemplateVariables<TUri>>({ name, description, uri, complete }: {
|
|
52
54
|
name: string;
|
|
53
55
|
description: string;
|
|
54
|
-
uri:
|
|
55
|
-
complete?: Completion
|
|
56
|
-
}, execute: (uri: string, params
|
|
56
|
+
uri: TUri;
|
|
57
|
+
complete?: TVariables extends never ? never : Partial<Record<TVariables, Completion>>;
|
|
58
|
+
}, execute: (uri: string, params: Record<TVariables, string | string[]>) => Promise<unknown> | unknown): void;
|
|
57
59
|
/**
|
|
58
60
|
* @param {JSONRPCRequest} request
|
|
59
61
|
* @returns {ReturnType<JSONRPCServer['receive']>}
|
|
@@ -70,6 +72,7 @@ export class McpServer<StandardSchema extends StandardSchemaV1> {
|
|
|
70
72
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
71
73
|
import type { McpEvents } from "./internal/internal.js";
|
|
72
74
|
import type { Completion } from "./internal/internal.js";
|
|
75
|
+
import type { ExtractURITemplateVariables } from "./internal/uri-template.js";
|
|
73
76
|
import type { JSONRPCRequest } from "json-rpc-2.0";
|
|
74
77
|
import { JSONRPCServer } from 'json-rpc-2.0';
|
|
75
78
|
import type { SubscriptionsKeys } from "./internal/internal.js";
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
3
|
* @import { JSONRPCRequest, JSONRPCParams } from "json-rpc-2.0";
|
|
4
|
+
* @import { ExtractURITemplateVariables } from "./internal/uri-template.js";
|
|
4
5
|
* @import { Tool, Completion, Prompt, Resource, ServerOptions, ServerInfo, SubscriptionsKeys, McpEvents } from "./internal/internal.js";
|
|
5
6
|
*/
|
|
6
7
|
import { JSONRPCServer, JSONRPCClient } from 'json-rpc-2.0';
|
|
@@ -30,7 +31,7 @@ export class McpServer {
|
|
|
30
31
|
#resources = new Map();
|
|
31
32
|
#templates = new UriTemplateMatcher();
|
|
32
33
|
/**
|
|
33
|
-
* @type {{ [ref: string]: Map<string, Completion
|
|
34
|
+
* @type {{ [ref: string]: Map<string, Partial<Record<string, Completion>>> }}
|
|
34
35
|
*/
|
|
35
36
|
#completions = {
|
|
36
37
|
'ref/prompt': new Map(),
|
|
@@ -277,7 +278,12 @@ export class McpServer {
|
|
|
277
278
|
throw new Error(`Resource ${uri} not found`);
|
|
278
279
|
}
|
|
279
280
|
}
|
|
280
|
-
|
|
281
|
+
if (resource.template) {
|
|
282
|
+
if (!params)
|
|
283
|
+
throw new Error('Missing parameters for template resource');
|
|
284
|
+
return resource.execute(uri, params);
|
|
285
|
+
}
|
|
286
|
+
return resource.execute(uri);
|
|
281
287
|
});
|
|
282
288
|
}
|
|
283
289
|
/**
|
|
@@ -291,9 +297,11 @@ export class McpServer {
|
|
|
291
297
|
if (!completions) return null;
|
|
292
298
|
const complete = completions.get(ref.uri ?? ref.name);
|
|
293
299
|
if (!complete) return null;
|
|
300
|
+
const actual_complete = complete[argument.name];
|
|
301
|
+
if (!actual_complete) return null;
|
|
294
302
|
return {
|
|
295
303
|
completion: {
|
|
296
|
-
values:
|
|
304
|
+
values: actual_complete(argument.value, context),
|
|
297
305
|
hasMore: false,
|
|
298
306
|
},
|
|
299
307
|
};
|
|
@@ -317,7 +325,7 @@ export class McpServer {
|
|
|
317
325
|
}
|
|
318
326
|
/**
|
|
319
327
|
* @template {StandardSchema | undefined} [TSchema=undefined]
|
|
320
|
-
* @param {{ name: string; description: string; schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never; complete?: Completion }} options
|
|
328
|
+
* @param {{ name: string; description: string; schema?: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema> extends Record<string, unknown> ? TSchema : never; complete?: TSchema extends undefined ? never : Partial<Record<keyof (StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>), Completion>> }} options
|
|
321
329
|
* @param {TSchema extends undefined ? (()=>Promise<unknown> | unknown) : (input: StandardSchemaV1.InferInput<TSchema extends undefined ? never : TSchema>) => Promise<unknown> | unknown} execute
|
|
322
330
|
*/
|
|
323
331
|
prompt({ name, description, schema, complete }, execute) {
|
|
@@ -334,43 +342,48 @@ export class McpServer {
|
|
|
334
342
|
});
|
|
335
343
|
}
|
|
336
344
|
/**
|
|
337
|
-
* @
|
|
338
|
-
* @param {string} description
|
|
339
|
-
* @param {string} uri
|
|
340
|
-
* @param {(uri: string, params?: unknown) => Promise<unknown> | unknown} execute
|
|
341
|
-
* @param {Completion} [complete]
|
|
342
|
-
* @param {boolean} [template=false]
|
|
345
|
+
* @type {(resource: Resource & {complete?: Partial<Record<string,Completion>>, uri: string})=> void}
|
|
343
346
|
*/
|
|
344
|
-
#resource(
|
|
347
|
+
#resource({ uri, complete, ...resource }) {
|
|
345
348
|
if (complete) {
|
|
346
349
|
this.#completions['ref/resource'].set(uri, complete);
|
|
347
350
|
}
|
|
348
|
-
if (template) {
|
|
351
|
+
if (resource.template) {
|
|
349
352
|
this.#templates.add(uri);
|
|
350
353
|
}
|
|
351
354
|
if (this.#options.capabilities?.resources?.listChanged) {
|
|
352
355
|
this.#notify('notifications/resources/list_changed', {});
|
|
353
356
|
}
|
|
354
|
-
this.#resources.set(uri,
|
|
355
|
-
description,
|
|
356
|
-
name,
|
|
357
|
-
execute,
|
|
358
|
-
template,
|
|
359
|
-
});
|
|
357
|
+
this.#resources.set(uri, resource);
|
|
360
358
|
}
|
|
361
359
|
/**
|
|
362
360
|
* @param {{ name: string; description: string; uri: string }} options
|
|
363
|
-
* @param {(uri: string
|
|
361
|
+
* @param {(uri: string) => Promise<unknown> | unknown} execute
|
|
364
362
|
*/
|
|
365
363
|
resource({ name, description, uri }, execute) {
|
|
366
|
-
this.#resource(
|
|
364
|
+
this.#resource({
|
|
365
|
+
name,
|
|
366
|
+
description,
|
|
367
|
+
uri,
|
|
368
|
+
execute,
|
|
369
|
+
template: false,
|
|
370
|
+
});
|
|
367
371
|
}
|
|
368
372
|
/**
|
|
369
|
-
* @
|
|
370
|
-
* @
|
|
373
|
+
* @template {string} TUri
|
|
374
|
+
* @template {ExtractURITemplateVariables<TUri>} TVariables
|
|
375
|
+
* @param {{ name: string; description: string; uri: TUri; complete?: TVariables extends never ? never : Partial<Record<TVariables, Completion>> }} options
|
|
376
|
+
* @param {(uri: string, params: Record<TVariables, string | string[]>) => Promise<unknown> | unknown} execute
|
|
371
377
|
*/
|
|
372
378
|
template({ name, description, uri, complete }, execute) {
|
|
373
|
-
this.#resource(
|
|
379
|
+
this.#resource({
|
|
380
|
+
name,
|
|
381
|
+
description,
|
|
382
|
+
uri,
|
|
383
|
+
execute,
|
|
384
|
+
complete,
|
|
385
|
+
template: true,
|
|
386
|
+
});
|
|
374
387
|
}
|
|
375
388
|
/**
|
|
376
389
|
* @param {JSONRPCRequest} request
|
|
@@ -11,7 +11,7 @@ export type Tool<TSchema extends StandardSchemaV1 = StandardSchemaV1<any>> = {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export type Completion = (
|
|
14
|
-
|
|
14
|
+
query: string,
|
|
15
15
|
context: { arguments: Record<string, string> },
|
|
16
16
|
) => string[];
|
|
17
17
|
|
|
@@ -23,12 +23,22 @@ export type Prompt<TSchema extends StandardSchemaV1 = StandardSchemaV1<any>> = {
|
|
|
23
23
|
) => Promise<unknown> | unknown;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
export type Resource =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
export type Resource =
|
|
27
|
+
| {
|
|
28
|
+
description: string;
|
|
29
|
+
name: string;
|
|
30
|
+
template: true;
|
|
31
|
+
execute: (
|
|
32
|
+
uri: string,
|
|
33
|
+
params: Record<string, string | string[]>,
|
|
34
|
+
) => Promise<unknown> | unknown;
|
|
35
|
+
}
|
|
36
|
+
| {
|
|
37
|
+
description: string;
|
|
38
|
+
name: string;
|
|
39
|
+
template: false;
|
|
40
|
+
execute: (uri: string) => Promise<unknown> | unknown;
|
|
41
|
+
};
|
|
32
42
|
|
|
33
43
|
export type ServerOptions<TSchema extends StandardSchemaV1> = {
|
|
34
44
|
capabilities?: {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Helper type to remove whitespace
|
|
2
|
+
type Trim<S extends string> = S extends ` ${infer R}`
|
|
3
|
+
? Trim<R>
|
|
4
|
+
: S extends `${infer L} `
|
|
5
|
+
? Trim<L>
|
|
6
|
+
: S;
|
|
7
|
+
|
|
8
|
+
// Helper type to extract variable name, removing modifiers
|
|
9
|
+
type ExtractVarName<S extends string> = S extends `${infer Name}:${string}`
|
|
10
|
+
? Trim<Name> // Remove prefix modifier
|
|
11
|
+
: S extends `${infer Name}*`
|
|
12
|
+
? Trim<Name> // Remove explode modifier
|
|
13
|
+
: Trim<S>;
|
|
14
|
+
|
|
15
|
+
// Helper type to split comma-separated variables
|
|
16
|
+
type SplitVariables<S extends string> = S extends `${infer First},${infer Rest}`
|
|
17
|
+
? ExtractVarName<First> | SplitVariables<Rest>
|
|
18
|
+
: ExtractVarName<S>;
|
|
19
|
+
|
|
20
|
+
// Helper type to extract content from braces and handle operators
|
|
21
|
+
type ExtractFromExpression<S extends string> = S extends `+${infer Vars}`
|
|
22
|
+
? SplitVariables<Vars> // Reserved {+var}
|
|
23
|
+
: S extends `#${infer Vars}`
|
|
24
|
+
? SplitVariables<Vars> // Fragment {#var}
|
|
25
|
+
: S extends `.${infer Vars}`
|
|
26
|
+
? SplitVariables<Vars> // Label {.var}
|
|
27
|
+
: S extends `/${infer Vars}`
|
|
28
|
+
? SplitVariables<Vars> // Path {/var}
|
|
29
|
+
: S extends `;${infer Vars}`
|
|
30
|
+
? SplitVariables<Vars> // Path-style {;var}
|
|
31
|
+
: S extends `?${infer Vars}`
|
|
32
|
+
? SplitVariables<Vars> // Query {?var}
|
|
33
|
+
: S extends `&${infer Vars}`
|
|
34
|
+
? SplitVariables<Vars> // Query continuation {&var}
|
|
35
|
+
: SplitVariables<S>; // Simple {var}
|
|
36
|
+
|
|
37
|
+
// Main recursive type to extract all variables from URI template
|
|
38
|
+
type ExtractVariablesFromTemplate<S extends string> =
|
|
39
|
+
S extends `${string}{${infer Expression}}${infer Rest}`
|
|
40
|
+
? ExtractFromExpression<Expression> | ExtractVariablesFromTemplate<Rest>
|
|
41
|
+
: never;
|
|
42
|
+
|
|
43
|
+
// Main exported type
|
|
44
|
+
export type ExtractURITemplateVariables<T extends string> =
|
|
45
|
+
ExtractVariablesFromTemplate<T>;
|