@nuxtjs/mcp-toolkit 0.2.0 → 0.4.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/dist/module.json +1 -1
- package/dist/module.mjs +11 -18
- package/dist/runtime/server/mcp/definitions/cache.d.ts +39 -0
- package/dist/runtime/server/mcp/definitions/cache.js +35 -0
- package/dist/runtime/server/mcp/definitions/handlers.d.ts +18 -0
- package/dist/runtime/server/mcp/definitions/index.d.ts +2 -0
- package/dist/runtime/server/mcp/definitions/index.js +2 -0
- package/dist/runtime/server/mcp/definitions/prompts.d.ts +8 -44
- package/dist/runtime/server/mcp/definitions/resources.d.ts +26 -64
- package/dist/runtime/server/mcp/definitions/resources.js +9 -0
- package/dist/runtime/server/mcp/definitions/results.d.ts +55 -0
- package/dist/runtime/server/mcp/definitions/results.js +13 -0
- package/dist/runtime/server/mcp/definitions/tools.d.ts +26 -31
- package/dist/runtime/server/mcp/definitions/tools.js +15 -2
- package/package.json +2 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { ROUTES } from '../dist/runtime/server/mcp/constants.js';
|
|
|
6
6
|
import { addDevToolsCustomTabs } from '../dist/runtime/server/mcp/devtools/index.js';
|
|
7
7
|
|
|
8
8
|
const name = "@nuxtjs/mcp-toolkit";
|
|
9
|
-
const version = "0.
|
|
9
|
+
const version = "0.4.0";
|
|
10
10
|
|
|
11
11
|
const log = logger.withTag("@nuxtjs/mcp-toolkit");
|
|
12
12
|
const { resolve } = createResolver(import.meta.url);
|
|
@@ -87,24 +87,17 @@ const module$1 = defineNuxtModule({
|
|
|
87
87
|
nuxt.options.nitro.typescript.tsConfig ??= {};
|
|
88
88
|
nuxt.options.nitro.typescript.tsConfig.include ??= [];
|
|
89
89
|
nuxt.options.nitro.typescript.tsConfig.include.push(resolver.resolve("runtime/server/types.server.d.ts"));
|
|
90
|
+
const mcpDefinitionsPath = resolver.resolve("runtime/server/mcp/definitions");
|
|
90
91
|
addServerImports([
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
name: "defineMcpPrompt",
|
|
101
|
-
from: resolver.resolve("runtime/server/mcp/definitions")
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
name: "defineMcpHandler",
|
|
105
|
-
from: resolver.resolve("runtime/server/mcp/definitions")
|
|
106
|
-
}
|
|
107
|
-
]);
|
|
92
|
+
"defineMcpTool",
|
|
93
|
+
"defineMcpResource",
|
|
94
|
+
"defineMcpPrompt",
|
|
95
|
+
"defineMcpHandler",
|
|
96
|
+
"textResult",
|
|
97
|
+
"jsonResult",
|
|
98
|
+
"errorResult",
|
|
99
|
+
"imageResult"
|
|
100
|
+
].map((name2) => ({ name: name2, from: mcpDefinitionsPath })));
|
|
108
101
|
addServerHandler({
|
|
109
102
|
route: options.route,
|
|
110
103
|
handler: resolver.resolve("runtime/server/mcp/handler")
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache duration strings supported by the `ms` package
|
|
3
|
+
*/
|
|
4
|
+
export type MsCacheDuration = '1s' | '5s' | '10s' | '15s' | '30s' | '45s' | '1m' | '2m' | '5m' | '10m' | '15m' | '30m' | '45m' | '1h' | '2h' | '3h' | '4h' | '6h' | '8h' | '12h' | '24h' | '1d' | '2d' | '3d' | '7d' | '14d' | '30d' | '1w' | '2w' | '4w' | '1 second' | '1 minute' | '1 hour' | '1 day' | '1 week' | '2 seconds' | '5 seconds' | '10 seconds' | '30 seconds' | '2 minutes' | '5 minutes' | '10 minutes' | '15 minutes' | '30 minutes' | '2 hours' | '3 hours' | '6 hours' | '12 hours' | '24 hours' | '2 days' | '3 days' | '7 days' | '14 days' | '30 days' | '2 weeks' | '4 weeks' | (string & Record<never, never>);
|
|
5
|
+
/**
|
|
6
|
+
* Base cache options using Nitro's caching system
|
|
7
|
+
* @see https://nitro.build/guide/cache#options
|
|
8
|
+
*/
|
|
9
|
+
export interface McpCacheOptions<Args = unknown> {
|
|
10
|
+
/** Cache duration as string (e.g. '1h') or milliseconds (required) */
|
|
11
|
+
maxAge: MsCacheDuration | number;
|
|
12
|
+
/** Duration for stale-while-revalidate */
|
|
13
|
+
staleMaxAge?: number;
|
|
14
|
+
/** Cache name (auto-generated by default) */
|
|
15
|
+
name?: string;
|
|
16
|
+
/** Function to generate cache key */
|
|
17
|
+
getKey?: (args: Args) => string;
|
|
18
|
+
/** Cache group (default: 'mcp') */
|
|
19
|
+
group?: string;
|
|
20
|
+
/** Enable stale-while-revalidate behavior */
|
|
21
|
+
swr?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Cache configuration: string duration, milliseconds, or full options
|
|
25
|
+
* @see https://nitro.build/guide/cache#options
|
|
26
|
+
*/
|
|
27
|
+
export type McpCache<Args = unknown> = MsCacheDuration | number | McpCacheOptions<Args>;
|
|
28
|
+
/**
|
|
29
|
+
* Parse cache duration to milliseconds
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseCacheDuration(duration: MsCacheDuration | number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Create cache options from McpCache config
|
|
34
|
+
*/
|
|
35
|
+
export declare function createCacheOptions<Args>(cache: McpCache<Args>, name: string, defaultGetKey?: (args: Args) => string): Record<string, unknown>;
|
|
36
|
+
/**
|
|
37
|
+
* Wrap a function with caching
|
|
38
|
+
*/
|
|
39
|
+
export declare function wrapWithCache<T extends (...args: unknown[]) => unknown>(fn: T, cacheOptions: Record<string, unknown>): T;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineCachedFunction } from "nitropack/runtime";
|
|
2
|
+
import ms from "ms";
|
|
3
|
+
export function parseCacheDuration(duration) {
|
|
4
|
+
if (typeof duration === "number") {
|
|
5
|
+
return duration;
|
|
6
|
+
}
|
|
7
|
+
const parsed = ms(duration);
|
|
8
|
+
if (parsed === void 0) {
|
|
9
|
+
throw new Error(`Invalid cache duration: ${duration}`);
|
|
10
|
+
}
|
|
11
|
+
return parsed;
|
|
12
|
+
}
|
|
13
|
+
export function createCacheOptions(cache, name, defaultGetKey) {
|
|
14
|
+
if (typeof cache === "object") {
|
|
15
|
+
return {
|
|
16
|
+
getKey: defaultGetKey,
|
|
17
|
+
...cache,
|
|
18
|
+
maxAge: parseCacheDuration(cache.maxAge),
|
|
19
|
+
name: cache.name ?? name,
|
|
20
|
+
group: cache.group ?? "mcp"
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
maxAge: parseCacheDuration(cache),
|
|
25
|
+
name,
|
|
26
|
+
group: "mcp",
|
|
27
|
+
getKey: defaultGetKey
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function wrapWithCache(fn, cacheOptions) {
|
|
31
|
+
return defineCachedFunction(
|
|
32
|
+
fn,
|
|
33
|
+
cacheOptions
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { McpToolDefinition } from './tools.js';
|
|
2
2
|
import type { McpResourceDefinition } from './resources.js';
|
|
3
3
|
import type { McpPromptDefinition } from './prompts.js';
|
|
4
|
+
/**
|
|
5
|
+
* Options for defining a custom MCP handler
|
|
6
|
+
* @see https://mcp-toolkit.nuxt.dev/core-concepts/handlers
|
|
7
|
+
*/
|
|
4
8
|
export interface McpHandlerOptions {
|
|
5
9
|
name: string;
|
|
6
10
|
version?: string;
|
|
@@ -15,4 +19,18 @@ export interface McpHandlerDefinition extends Required<Omit<McpHandlerOptions, '
|
|
|
15
19
|
resources: McpResourceDefinition[];
|
|
16
20
|
prompts: McpPromptDefinition[];
|
|
17
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Define a custom MCP handler with specific tools, resources, and prompts.
|
|
24
|
+
*
|
|
25
|
+
* @see https://mcp-toolkit.nuxt.dev/core-concepts/handlers
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* export default defineMcpHandler({
|
|
30
|
+
* name: 'my-handler',
|
|
31
|
+
* tools: [myTool],
|
|
32
|
+
* resources: [myResource]
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
18
36
|
export declare function defineMcpHandler(options: McpHandlerOptions): McpHandlerOptions;
|
|
@@ -20,60 +20,24 @@ export interface McpPromptDefinition<Args extends ZodRawShape | undefined = unde
|
|
|
20
20
|
handler: McpPromptCallback<Args>;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Register a prompt from a McpPromptDefinition
|
|
24
|
+
* @internal
|
|
24
25
|
*/
|
|
25
26
|
export declare function registerPromptFromDefinition<Args extends ZodRawShape | undefined = undefined>(server: McpServer, prompt: McpPromptDefinition<Args>): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredPrompt;
|
|
26
27
|
/**
|
|
27
|
-
* Define an MCP prompt that will be automatically registered
|
|
28
|
+
* Define an MCP prompt that will be automatically registered.
|
|
28
29
|
*
|
|
29
|
-
*
|
|
30
|
-
* (e.g., `list_documentation.ts` → `name: 'list-documentation'`, `title: 'List Documentation'`).
|
|
30
|
+
* `name` and `title` are auto-generated from filename if not provided.
|
|
31
31
|
*
|
|
32
|
-
* @
|
|
33
|
-
* ```ts
|
|
34
|
-
* // server/mcp/prompts/my-prompt.ts
|
|
35
|
-
* import { z } from 'zod'
|
|
36
|
-
*
|
|
37
|
-
* export default defineMcpPrompt({
|
|
38
|
-
* name: 'summarize',
|
|
39
|
-
* title: 'Text Summarizer',
|
|
40
|
-
* description: 'Summarize any text using an LLM',
|
|
41
|
-
* inputSchema: {
|
|
42
|
-
* text: z.string().describe('The text to summarize'),
|
|
43
|
-
* maxLength: z.string().optional().describe('Maximum length of summary')
|
|
44
|
-
* },
|
|
45
|
-
* handler: async ({ text, maxLength }) => {
|
|
46
|
-
* const summary = await summarizeText(text, maxLength ? parseInt(maxLength) : undefined)
|
|
47
|
-
* return {
|
|
48
|
-
* messages: [{
|
|
49
|
-
* role: 'user',
|
|
50
|
-
* content: {
|
|
51
|
-
* type: 'text',
|
|
52
|
-
* text: summary
|
|
53
|
-
* }
|
|
54
|
-
* }]
|
|
55
|
-
* }
|
|
56
|
-
* }
|
|
57
|
-
* })
|
|
58
|
-
* ```
|
|
32
|
+
* @see https://mcp-toolkit.nuxt.dev/core-concepts/prompts
|
|
59
33
|
*
|
|
60
34
|
* @example
|
|
61
35
|
* ```ts
|
|
62
|
-
* // Simple prompt without arguments
|
|
63
36
|
* export default defineMcpPrompt({
|
|
64
|
-
* name: 'greeting',
|
|
65
37
|
* description: 'Generate a greeting message',
|
|
66
|
-
* handler: async () => {
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* role: 'user',
|
|
70
|
-
* content: {
|
|
71
|
-
* type: 'text',
|
|
72
|
-
* text: 'Hello! How can I help you today?'
|
|
73
|
-
* }
|
|
74
|
-
* }]
|
|
75
|
-
* }
|
|
76
|
-
* }
|
|
38
|
+
* handler: async () => ({
|
|
39
|
+
* messages: [{ role: 'user', content: { type: 'text', text: 'Hello!' } }]
|
|
40
|
+
* })
|
|
77
41
|
* })
|
|
78
42
|
* ```
|
|
79
43
|
*/
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { McpServer, ResourceTemplate, ReadResourceCallback, ReadResourceTemplateCallback, ResourceMetadata } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { type McpCacheOptions, type McpCache } from './cache.js';
|
|
3
|
+
export type McpResourceCacheOptions = McpCacheOptions<URL>;
|
|
4
|
+
export type McpResourceCache = McpCache<URL>;
|
|
2
5
|
/**
|
|
3
6
|
* Annotations for a resource
|
|
4
7
|
* @see https://modelcontextprotocol.io/specification/2025-06-18/server/resources#annotations
|
|
@@ -23,6 +26,14 @@ export interface StandardMcpResourceDefinition {
|
|
|
23
26
|
_meta?: Record<string, unknown>;
|
|
24
27
|
handler: ReadResourceCallback | ReadResourceTemplateCallback;
|
|
25
28
|
file?: never;
|
|
29
|
+
/**
|
|
30
|
+
* Cache configuration for the resource response
|
|
31
|
+
* - string: Duration parsed by `ms` (e.g., '1h', '2 days', '30m')
|
|
32
|
+
* - number: Duration in milliseconds
|
|
33
|
+
* - object: Full cache options with getKey, group, swr, etc.
|
|
34
|
+
* @see https://nitro.build/guide/cache#options
|
|
35
|
+
*/
|
|
36
|
+
cache?: McpResourceCache;
|
|
26
37
|
}
|
|
27
38
|
/**
|
|
28
39
|
* Definition of a file-based MCP resource
|
|
@@ -42,6 +53,14 @@ export interface FileMcpResourceDefinition {
|
|
|
42
53
|
* Relative to the project root
|
|
43
54
|
*/
|
|
44
55
|
file: string;
|
|
56
|
+
/**
|
|
57
|
+
* Cache configuration for the resource response
|
|
58
|
+
* - string: Duration parsed by `ms` (e.g., '1h', '2 days', '30m')
|
|
59
|
+
* - number: Duration in milliseconds
|
|
60
|
+
* - object: Full cache options with getKey, group, swr, etc.
|
|
61
|
+
* @see https://nitro.build/guide/cache#options
|
|
62
|
+
*/
|
|
63
|
+
cache?: McpResourceCache;
|
|
45
64
|
}
|
|
46
65
|
/**
|
|
47
66
|
* Definition of an MCP resource matching the SDK's registerResource signature
|
|
@@ -50,80 +69,23 @@ export interface FileMcpResourceDefinition {
|
|
|
50
69
|
*/
|
|
51
70
|
export type McpResourceDefinition = StandardMcpResourceDefinition | FileMcpResourceDefinition;
|
|
52
71
|
/**
|
|
53
|
-
*
|
|
72
|
+
* Register a resource from a McpResourceDefinition
|
|
73
|
+
* @internal
|
|
54
74
|
*/
|
|
55
75
|
export declare function registerResourceFromDefinition(server: McpServer, resource: McpResourceDefinition): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredResource | import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredResourceTemplate;
|
|
56
76
|
/**
|
|
57
|
-
* Define an MCP resource that will be automatically registered
|
|
58
|
-
*
|
|
59
|
-
* This function matches the structure of server.registerResource() from the MCP SDK.
|
|
77
|
+
* Define an MCP resource that will be automatically registered.
|
|
60
78
|
*
|
|
61
|
-
*
|
|
62
|
-
* (e.g., `list_documentation.ts` → `name: 'list-documentation'`, `title: 'List Documentation'`).
|
|
79
|
+
* `name` and `title` are auto-generated from filename if not provided.
|
|
63
80
|
*
|
|
64
|
-
* @
|
|
65
|
-
* ```ts
|
|
66
|
-
* // server/mcp/resources/my-resource.ts
|
|
67
|
-
* export default defineMcpResource({
|
|
68
|
-
* name: 'readme',
|
|
69
|
-
* title: 'README',
|
|
70
|
-
* description: 'Project README file',
|
|
71
|
-
* uri: 'file:///project/README.md',
|
|
72
|
-
* metadata: {
|
|
73
|
-
* mimeType: 'text/markdown'
|
|
74
|
-
* },
|
|
75
|
-
* handler: async (uri) => {
|
|
76
|
-
* const content = await readFile(uri.pathname, 'utf-8')
|
|
77
|
-
* return {
|
|
78
|
-
* contents: [{
|
|
79
|
-
* uri: uri.toString(),
|
|
80
|
-
* mimeType: 'text/markdown',
|
|
81
|
-
* text: content
|
|
82
|
-
* }]
|
|
83
|
-
* }
|
|
84
|
-
* }
|
|
85
|
-
* })
|
|
86
|
-
* ```
|
|
81
|
+
* @see https://mcp-toolkit.nuxt.dev/core-concepts/resources
|
|
87
82
|
*
|
|
88
83
|
* @example
|
|
89
84
|
* ```ts
|
|
90
|
-
* //
|
|
85
|
+
* // File-based resource
|
|
91
86
|
* export default defineMcpResource({
|
|
92
|
-
* name: 'readme',
|
|
93
87
|
* description: 'Project README file',
|
|
94
|
-
* file: 'README.md'
|
|
95
|
-
* })
|
|
96
|
-
* ```
|
|
97
|
-
*
|
|
98
|
-
* @example
|
|
99
|
-
* ```ts
|
|
100
|
-
* // Dynamic resource with template
|
|
101
|
-
* import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
102
|
-
*
|
|
103
|
-
* export default defineMcpResource({
|
|
104
|
-
* name: 'file',
|
|
105
|
-
* title: 'File Resource',
|
|
106
|
-
* uri: new ResourceTemplate('file:///project/{+path}', {
|
|
107
|
-
* list: async () => {
|
|
108
|
-
* return {
|
|
109
|
-
* resources: [
|
|
110
|
-
* { uri: 'file:///project/README.md', name: 'README.md' },
|
|
111
|
-
* { uri: 'file:///project/src/index.ts', name: 'index.ts' }
|
|
112
|
-
* ]
|
|
113
|
-
* }
|
|
114
|
-
* }
|
|
115
|
-
* }),
|
|
116
|
-
* handler: async (uri, variables) => {
|
|
117
|
-
* const path = variables.path
|
|
118
|
-
* const content = await readFile(path, 'utf-8')
|
|
119
|
-
* return {
|
|
120
|
-
* contents: [{
|
|
121
|
-
* uri: uri.toString(),
|
|
122
|
-
* mimeType: 'text/plain',
|
|
123
|
-
* text: content
|
|
124
|
-
* }]
|
|
125
|
-
* }
|
|
126
|
-
* }
|
|
88
|
+
* file: 'README.md'
|
|
127
89
|
* })
|
|
128
90
|
* ```
|
|
129
91
|
*/
|
|
@@ -2,6 +2,7 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import { resolve, extname } from "node:path";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
import { enrichNameTitle } from "./utils.js";
|
|
5
|
+
import { createCacheOptions, wrapWithCache } from "./cache.js";
|
|
5
6
|
function getMimeType(filePath) {
|
|
6
7
|
const ext = extname(filePath).toLowerCase();
|
|
7
8
|
switch (ext) {
|
|
@@ -74,6 +75,14 @@ export function registerResourceFromDefinition(server, resource) {
|
|
|
74
75
|
if (!handler) {
|
|
75
76
|
throw new Error(`Resource ${name} is missing a handler`);
|
|
76
77
|
}
|
|
78
|
+
if (resource.cache !== void 0) {
|
|
79
|
+
const defaultGetKey = (requestUri) => requestUri.pathname.replace(/\//g, "-").replace(/^-/, "");
|
|
80
|
+
const cacheOptions = createCacheOptions(resource.cache, `mcp-resource:${name}`, defaultGetKey);
|
|
81
|
+
handler = wrapWithCache(
|
|
82
|
+
handler,
|
|
83
|
+
cacheOptions
|
|
84
|
+
);
|
|
85
|
+
}
|
|
77
86
|
if (typeof uri === "string") {
|
|
78
87
|
return server.registerResource(
|
|
79
88
|
name,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a text result for an MCP tool response.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* export default defineMcpTool({
|
|
8
|
+
* handler: async () => textResult('Hello world')
|
|
9
|
+
* })
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function textResult(text: string): CallToolResult;
|
|
13
|
+
/**
|
|
14
|
+
* Create a JSON result for an MCP tool response.
|
|
15
|
+
* Automatically stringifies the data.
|
|
16
|
+
*
|
|
17
|
+
* @param data - The data to serialize as JSON
|
|
18
|
+
* @param pretty - Whether to pretty-print the JSON (default: true)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* export default defineMcpTool({
|
|
23
|
+
* handler: async () => jsonResult({ foo: 'bar', count: 42 })
|
|
24
|
+
* })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function jsonResult(data: unknown, pretty?: boolean): CallToolResult;
|
|
28
|
+
/**
|
|
29
|
+
* Create an error result for an MCP tool response.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* export default defineMcpTool({
|
|
34
|
+
* handler: async () => {
|
|
35
|
+
* if (!found) return errorResult('Resource not found')
|
|
36
|
+
* return textResult('Success')
|
|
37
|
+
* }
|
|
38
|
+
* })
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function errorResult(message: string): CallToolResult;
|
|
42
|
+
/**
|
|
43
|
+
* Create an image result for an MCP tool response.
|
|
44
|
+
*
|
|
45
|
+
* @param data - Base64-encoded image data
|
|
46
|
+
* @param mimeType - The MIME type of the image (e.g., 'image/png', 'image/jpeg')
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* export default defineMcpTool({
|
|
51
|
+
* handler: async () => imageResult(base64Data, 'image/png')
|
|
52
|
+
* })
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function imageResult(data: string, mimeType: string): CallToolResult;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function textResult(text) {
|
|
2
|
+
return { content: [{ type: "text", text }] };
|
|
3
|
+
}
|
|
4
|
+
export function jsonResult(data, pretty = true) {
|
|
5
|
+
const text = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
6
|
+
return { content: [{ type: "text", text }] };
|
|
7
|
+
}
|
|
8
|
+
export function errorResult(message) {
|
|
9
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
10
|
+
}
|
|
11
|
+
export function imageResult(data, mimeType) {
|
|
12
|
+
return { content: [{ type: "image", data, mimeType }] };
|
|
13
|
+
}
|
|
@@ -3,13 +3,17 @@ import type { CallToolResult, ServerRequest, ServerNotification, ToolAnnotations
|
|
|
3
3
|
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
4
4
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
5
|
import type { ShapeOutput } from '@modelcontextprotocol/sdk/server/zod-compat.js';
|
|
6
|
+
import { type MsCacheDuration, type McpCacheOptions, type McpCache } from './cache.js';
|
|
7
|
+
export type { MsCacheDuration };
|
|
8
|
+
export type McpToolCacheOptions<Args = unknown> = McpCacheOptions<Args>;
|
|
9
|
+
export type McpToolCache<Args = unknown> = McpCache<Args>;
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
11
|
+
* Handler callback type for MCP tools
|
|
8
12
|
*/
|
|
9
13
|
export type McpToolCallback<Args extends ZodRawShape | undefined = ZodRawShape> = Args extends ZodRawShape ? (args: ShapeOutput<Args>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult> : (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult>;
|
|
10
14
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
15
|
+
* MCP tool definition structure
|
|
16
|
+
* @see https://mcp-toolkit.nuxt.dev/core-concepts/tools
|
|
13
17
|
*/
|
|
14
18
|
export interface McpToolDefinition<InputSchema extends ZodRawShape | undefined = ZodRawShape, OutputSchema extends ZodRawShape = ZodRawShape> {
|
|
15
19
|
name?: string;
|
|
@@ -20,45 +24,36 @@ export interface McpToolDefinition<InputSchema extends ZodRawShape | undefined =
|
|
|
20
24
|
annotations?: ToolAnnotations;
|
|
21
25
|
_meta?: Record<string, unknown>;
|
|
22
26
|
handler: McpToolCallback<InputSchema>;
|
|
27
|
+
/**
|
|
28
|
+
* Cache configuration for the tool response
|
|
29
|
+
* - string: Duration parsed by `ms` (e.g., '1h', '2 days', '30m')
|
|
30
|
+
* - number: Duration in milliseconds
|
|
31
|
+
* - object: Full cache options with getKey, group, swr, etc.
|
|
32
|
+
* @see https://nitro.build/guide/cache#options
|
|
33
|
+
*/
|
|
34
|
+
cache?: McpToolCache<InputSchema extends ZodRawShape ? ShapeOutput<InputSchema> : undefined>;
|
|
23
35
|
}
|
|
24
36
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
37
|
+
* Register a tool from a McpToolDefinition
|
|
38
|
+
* @internal
|
|
27
39
|
*/
|
|
28
40
|
export declare function registerToolFromDefinition<InputSchema extends ZodRawShape | undefined = ZodRawShape, OutputSchema extends ZodRawShape = ZodRawShape>(server: McpServer, tool: McpToolDefinition<InputSchema, OutputSchema>): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredTool;
|
|
29
41
|
/**
|
|
30
|
-
* Define an MCP tool that will be automatically registered
|
|
42
|
+
* Define an MCP tool that will be automatically registered.
|
|
31
43
|
*
|
|
32
|
-
*
|
|
33
|
-
* making it easy to migrate code from the SDK to this module.
|
|
44
|
+
* `name` and `title` are auto-generated from filename if not provided.
|
|
34
45
|
*
|
|
35
|
-
*
|
|
36
|
-
* (e.g., `list_documentation.ts` → `name: 'list-documentation'`, `title: 'List Documentation'`).
|
|
46
|
+
* @see https://mcp-toolkit.nuxt.dev/core-concepts/tools
|
|
37
47
|
*
|
|
38
48
|
* @example
|
|
39
49
|
* ```ts
|
|
40
|
-
* // server/mcp/tools/my-tool.ts
|
|
41
|
-
* import { z } from 'zod'
|
|
42
|
-
*
|
|
43
50
|
* export default defineMcpTool({
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* },
|
|
51
|
-
* outputSchema: { bmi: z.number() },
|
|
52
|
-
* handler: async ({ weightKg, heightM }) => {
|
|
53
|
-
* const output = { bmi: weightKg / (heightM * heightM) }
|
|
54
|
-
* return {
|
|
55
|
-
* content: [{
|
|
56
|
-
* type: 'text',
|
|
57
|
-
* text: JSON.stringify(output)
|
|
58
|
-
* }],
|
|
59
|
-
* structuredContent: output
|
|
60
|
-
* }
|
|
61
|
-
* }
|
|
51
|
+
* description: 'Echo back a message',
|
|
52
|
+
* inputSchema: { message: z.string() },
|
|
53
|
+
* cache: '1h', // optional caching
|
|
54
|
+
* handler: async ({ message }) => ({
|
|
55
|
+
* content: [{ type: 'text', text: message }]
|
|
56
|
+
* })
|
|
62
57
|
* })
|
|
63
58
|
* ```
|
|
64
59
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { enrichNameTitle } from "./utils.js";
|
|
2
|
+
import { createCacheOptions, wrapWithCache } from "./cache.js";
|
|
2
3
|
export function registerToolFromDefinition(server, tool) {
|
|
3
4
|
const { name, title } = enrichNameTitle({
|
|
4
5
|
name: tool.name,
|
|
@@ -6,6 +7,18 @@ export function registerToolFromDefinition(server, tool) {
|
|
|
6
7
|
_meta: tool._meta,
|
|
7
8
|
type: "tool"
|
|
8
9
|
});
|
|
10
|
+
let handler = tool.handler;
|
|
11
|
+
if (tool.cache !== void 0) {
|
|
12
|
+
const defaultGetKey = tool.inputSchema ? (args) => {
|
|
13
|
+
const values = Object.values(args);
|
|
14
|
+
return values.map((v) => String(v).replace(/\//g, "-").replace(/^-/, "")).join(":");
|
|
15
|
+
} : void 0;
|
|
16
|
+
const cacheOptions = createCacheOptions(tool.cache, `mcp-tool:${name}`, defaultGetKey);
|
|
17
|
+
handler = wrapWithCache(
|
|
18
|
+
tool.handler,
|
|
19
|
+
cacheOptions
|
|
20
|
+
);
|
|
21
|
+
}
|
|
9
22
|
if (tool.inputSchema) {
|
|
10
23
|
return server.registerTool(
|
|
11
24
|
name,
|
|
@@ -17,7 +30,7 @@ export function registerToolFromDefinition(server, tool) {
|
|
|
17
30
|
annotations: tool.annotations,
|
|
18
31
|
_meta: tool._meta
|
|
19
32
|
},
|
|
20
|
-
|
|
33
|
+
handler
|
|
21
34
|
);
|
|
22
35
|
} else {
|
|
23
36
|
return server.registerTool(
|
|
@@ -29,7 +42,7 @@ export function registerToolFromDefinition(server, tool) {
|
|
|
29
42
|
annotations: tool.annotations,
|
|
30
43
|
_meta: tool._meta
|
|
31
44
|
},
|
|
32
|
-
|
|
45
|
+
handler
|
|
33
46
|
);
|
|
34
47
|
}
|
|
35
48
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtjs/mcp-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Create MCP servers directly in your Nuxt application. Define tools, resources, and prompts with a simple and intuitive API.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"automd": "^0.4.2",
|
|
39
39
|
"chokidar": "^4.0.3",
|
|
40
40
|
"defu": "^6.1.4",
|
|
41
|
+
"ms": "^2.1.3",
|
|
41
42
|
"pathe": "^2.0.3",
|
|
42
43
|
"scule": "^1.3.0",
|
|
43
44
|
"tinyglobby": "^0.2.15"
|