@nuxtjs/mcp-toolkit 0.2.0 → 0.3.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxtjs/mcp-toolkit",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "configKey": "mcp",
5
5
  "docs": "https://mcp-toolkit.nuxt.dev/getting-started/installation",
6
6
  "mcp": "https://mcp-toolkit.nuxt.dev/mcp",
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.2.0";
9
+ const version = "0.3.0";
10
10
 
11
11
  const log = logger.withTag("@nuxtjs/mcp-toolkit");
12
12
  const { resolve } = createResolver(import.meta.url);
@@ -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
- * Helper function to register a prompt from a McpPromptDefinition
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
- * If `name` or `title` are not provided, they will be automatically generated from the filename
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
- * @example
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
- * return {
68
- * messages: [{
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
  */
@@ -50,80 +50,23 @@ export interface FileMcpResourceDefinition {
50
50
  */
51
51
  export type McpResourceDefinition = StandardMcpResourceDefinition | FileMcpResourceDefinition;
52
52
  /**
53
- * Helper function to register a resource from a McpResourceDefinition
53
+ * Register a resource from a McpResourceDefinition
54
+ * @internal
54
55
  */
55
56
  export declare function registerResourceFromDefinition(server: McpServer, resource: McpResourceDefinition): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredResource | import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredResourceTemplate;
56
57
  /**
57
- * Define an MCP resource that will be automatically registered
58
+ * Define an MCP resource that will be automatically registered.
58
59
  *
59
- * This function matches the structure of server.registerResource() from the MCP SDK.
60
+ * `name` and `title` are auto-generated from filename if not provided.
60
61
  *
61
- * If `name` or `title` are not provided, they will be automatically generated from the filename
62
- * (e.g., `list_documentation.ts` → `name: 'list-documentation'`, `title: 'List Documentation'`).
62
+ * @see https://mcp-toolkit.nuxt.dev/core-concepts/resources
63
63
  *
64
64
  * @example
65
65
  * ```ts
66
- * // server/mcp/resources/my-resource.ts
66
+ * // File-based resource
67
67
  * export default defineMcpResource({
68
- * name: 'readme',
69
- * title: 'README',
70
68
  * 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
- * ```
87
- *
88
- * @example
89
- * ```ts
90
- * // Simpler file-based resource
91
- * export default defineMcpResource({
92
- * name: 'readme',
93
- * description: 'Project README file',
94
- * file: 'README.md', // Automatically handles reading file and setting URI
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
- * }
69
+ * file: 'README.md'
127
70
  * })
128
71
  * ```
129
72
  */
@@ -4,12 +4,39 @@ import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/proto
4
4
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
5
  import type { ShapeOutput } from '@modelcontextprotocol/sdk/server/zod-compat.js';
6
6
  /**
7
- * Callback type for MCP tools, matching the SDK's ToolCallback type
7
+ * Cache duration strings supported by the `ms` package
8
+ */
9
+ 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>);
10
+ /**
11
+ * Cache options for MCP tools using Nitro's caching system
12
+ * @see https://nitro.build/guide/cache#options
13
+ */
14
+ export interface McpToolCacheOptions<Args = unknown> {
15
+ /** Cache duration as string (e.g. '1h') or milliseconds (required) */
16
+ maxAge: MsCacheDuration | number;
17
+ /** Duration for stale-while-revalidate */
18
+ staleMaxAge?: number;
19
+ /** Cache name (auto-generated from tool name by default) */
20
+ name?: string;
21
+ /** Function to generate cache key from arguments */
22
+ getKey?: (args: Args) => string;
23
+ /** Cache group (default: 'mcp') */
24
+ group?: string;
25
+ /** Enable stale-while-revalidate behavior */
26
+ swr?: boolean;
27
+ }
28
+ /**
29
+ * Cache configuration: string duration, milliseconds, or full options
30
+ * @see https://nitro.build/guide/cache#options
31
+ */
32
+ export type McpToolCache<Args = unknown> = MsCacheDuration | number | McpToolCacheOptions<Args>;
33
+ /**
34
+ * Handler callback type for MCP tools
8
35
  */
9
36
  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
37
  /**
11
- * Definition of an MCP tool matching the SDK's registerTool signature
12
- * This structure is identical to what you'd pass to server.registerTool()
38
+ * MCP tool definition structure
39
+ * @see https://mcp-toolkit.nuxt.dev/core-concepts/tools
13
40
  */
14
41
  export interface McpToolDefinition<InputSchema extends ZodRawShape | undefined = ZodRawShape, OutputSchema extends ZodRawShape = ZodRawShape> {
15
42
  name?: string;
@@ -20,45 +47,36 @@ export interface McpToolDefinition<InputSchema extends ZodRawShape | undefined =
20
47
  annotations?: ToolAnnotations;
21
48
  _meta?: Record<string, unknown>;
22
49
  handler: McpToolCallback<InputSchema>;
50
+ /**
51
+ * Cache configuration for the tool response
52
+ * - string: Duration parsed by `ms` (e.g., '1h', '2 days', '30m')
53
+ * - number: Duration in milliseconds
54
+ * - object: Full cache options with getKey, group, swr, etc.
55
+ * @see https://nitro.build/guide/cache#options
56
+ */
57
+ cache?: McpToolCache<InputSchema extends ZodRawShape ? ShapeOutput<InputSchema> : undefined>;
23
58
  }
24
59
  /**
25
- * Helper function to register a tool from a McpToolDefinition
26
- * This provides better type inference when registering tools
60
+ * Register a tool from a McpToolDefinition
61
+ * @internal
27
62
  */
28
63
  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
64
  /**
30
- * Define an MCP tool that will be automatically registered
65
+ * Define an MCP tool that will be automatically registered.
31
66
  *
32
- * This function matches the exact structure of server.registerTool() from the MCP SDK,
33
- * making it easy to migrate code from the SDK to this module.
67
+ * `name` and `title` are auto-generated from filename if not provided.
34
68
  *
35
- * If `name` or `title` are not provided, they will be automatically generated from the filename
36
- * (e.g., `list_documentation.ts` → `name: 'list-documentation'`, `title: 'List Documentation'`).
69
+ * @see https://mcp-toolkit.nuxt.dev/core-concepts/tools
37
70
  *
38
71
  * @example
39
72
  * ```ts
40
- * // server/mcp/tools/my-tool.ts
41
- * import { z } from 'zod'
42
- *
43
73
  * export default defineMcpTool({
44
- * name: 'calculate-bmi',
45
- * title: 'BMI Calculator',
46
- * description: 'Calculate Body Mass Index',
47
- * inputSchema: {
48
- * weightKg: z.number(),
49
- * heightM: z.number()
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
- * }
74
+ * description: 'Echo back a message',
75
+ * inputSchema: { message: z.string() },
76
+ * cache: '1h', // optional caching
77
+ * handler: async ({ message }) => ({
78
+ * content: [{ type: 'text', text: message }]
79
+ * })
62
80
  * })
63
81
  * ```
64
82
  */
@@ -1,4 +1,16 @@
1
+ import { defineCachedFunction } from "nitropack/runtime";
1
2
  import { enrichNameTitle } from "./utils.js";
3
+ import ms from "ms";
4
+ function parseCacheDuration(duration) {
5
+ if (typeof duration === "number") {
6
+ return duration;
7
+ }
8
+ const parsed = ms(duration);
9
+ if (parsed === void 0) {
10
+ throw new Error(`Invalid cache duration: ${duration}`);
11
+ }
12
+ return parsed;
13
+ }
2
14
  export function registerToolFromDefinition(server, tool) {
3
15
  const { name, title } = enrichNameTitle({
4
16
  name: tool.name,
@@ -6,6 +18,29 @@ export function registerToolFromDefinition(server, tool) {
6
18
  _meta: tool._meta,
7
19
  type: "tool"
8
20
  });
21
+ let handler = tool.handler;
22
+ if (tool.cache !== void 0) {
23
+ const defaultGetKey = tool.inputSchema ? (args) => {
24
+ const values = Object.values(args);
25
+ return values.map((v) => String(v).replace(/\//g, "-").replace(/^-/, "")).join(":");
26
+ } : void 0;
27
+ const cacheOptions = typeof tool.cache === "object" ? {
28
+ getKey: defaultGetKey,
29
+ ...tool.cache,
30
+ maxAge: parseCacheDuration(tool.cache.maxAge),
31
+ name: tool.cache.name ?? `mcp-tool:${name}`,
32
+ group: tool.cache.group ?? "mcp"
33
+ } : {
34
+ maxAge: parseCacheDuration(tool.cache),
35
+ name: `mcp-tool:${name}`,
36
+ group: "mcp",
37
+ getKey: defaultGetKey
38
+ };
39
+ handler = defineCachedFunction(
40
+ tool.handler,
41
+ cacheOptions
42
+ );
43
+ }
9
44
  if (tool.inputSchema) {
10
45
  return server.registerTool(
11
46
  name,
@@ -17,7 +52,7 @@ export function registerToolFromDefinition(server, tool) {
17
52
  annotations: tool.annotations,
18
53
  _meta: tool._meta
19
54
  },
20
- tool.handler
55
+ handler
21
56
  );
22
57
  } else {
23
58
  return server.registerTool(
@@ -29,7 +64,7 @@ export function registerToolFromDefinition(server, tool) {
29
64
  annotations: tool.annotations,
30
65
  _meta: tool._meta
31
66
  },
32
- tool.handler
67
+ handler
33
68
  );
34
69
  }
35
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxtjs/mcp-toolkit",
3
- "version": "0.2.0",
3
+ "version": "0.3.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"