@nuxtjs/mcp-toolkit 0.1.1 → 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/README.md CHANGED
@@ -39,20 +39,18 @@ Or install manually:
39
39
 
40
40
  ```bash
41
41
  # npm
42
- npm install -D @nuxtjs/mcp-toolkit zod@^3
42
+ npm install -D @nuxtjs/mcp-toolkit zod
43
43
 
44
44
  # yarn
45
- yarn add -D @nuxtjs/mcp-toolkit zod@^3
45
+ yarn add -D @nuxtjs/mcp-toolkit zod
46
46
 
47
47
  # pnpm
48
- pnpm add -D @nuxtjs/mcp-toolkit zod@^3
48
+ pnpm add -D @nuxtjs/mcp-toolkit zod
49
49
 
50
50
  # bun
51
- bun add -D @nuxtjs/mcp-toolkit zod@^3
51
+ bun add -D @nuxtjs/mcp-toolkit zod
52
52
  ```
53
53
 
54
- > **Note:** Zod v3 is required. Zod v4 is not yet compatible with the MCP SDK.
55
-
56
54
  <!-- /automd -->
57
55
 
58
56
  ## 📖 Quick Start
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxtjs/mcp-toolkit",
3
- "version": "0.1.1",
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.1.1";
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;
@@ -1,11 +1,12 @@
1
- import type { z, ZodTypeAny, ZodRawShape } from 'zod';
1
+ import type { ZodRawShape } from 'zod';
2
2
  import type { GetPromptResult, ServerRequest, ServerNotification } from '@modelcontextprotocol/sdk/types.js';
3
3
  import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
4
4
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { ShapeOutput } from '@modelcontextprotocol/sdk/server/zod-compat.js';
5
6
  /**
6
7
  * Callback type for MCP prompts, matching the SDK's PromptCallback type
7
8
  */
8
- export type McpPromptCallback<Args extends ZodRawShape | undefined = undefined> = Args extends ZodRawShape ? (args: z.objectOutputType<Args, ZodTypeAny>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => GetPromptResult | Promise<GetPromptResult> : (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => GetPromptResult | Promise<GetPromptResult>;
9
+ export type McpPromptCallback<Args extends ZodRawShape | undefined = undefined> = Args extends ZodRawShape ? (args: ShapeOutput<Args>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => GetPromptResult | Promise<GetPromptResult> : (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => GetPromptResult | Promise<GetPromptResult>;
9
10
  /**
10
11
  * Definition of an MCP prompt
11
12
  * Uses `inputSchema` for consistency with tools, which is mapped to `argsSchema` when registering with the SDK
@@ -19,60 +20,24 @@ export interface McpPromptDefinition<Args extends ZodRawShape | undefined = unde
19
20
  handler: McpPromptCallback<Args>;
20
21
  }
21
22
  /**
22
- * Helper function to register a prompt from a McpPromptDefinition
23
+ * Register a prompt from a McpPromptDefinition
24
+ * @internal
23
25
  */
24
26
  export declare function registerPromptFromDefinition<Args extends ZodRawShape | undefined = undefined>(server: McpServer, prompt: McpPromptDefinition<Args>): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredPrompt;
25
27
  /**
26
- * Define an MCP prompt that will be automatically registered
28
+ * Define an MCP prompt that will be automatically registered.
27
29
  *
28
- * If `name` or `title` are not provided, they will be automatically generated from the filename
29
- * (e.g., `list_documentation.ts` → `name: 'list-documentation'`, `title: 'List Documentation'`).
30
+ * `name` and `title` are auto-generated from filename if not provided.
30
31
  *
31
- * @example
32
- * ```ts
33
- * // server/mcp/prompts/my-prompt.ts
34
- * import { z } from 'zod'
35
- *
36
- * export default defineMcpPrompt({
37
- * name: 'summarize',
38
- * title: 'Text Summarizer',
39
- * description: 'Summarize any text using an LLM',
40
- * inputSchema: {
41
- * text: z.string().describe('The text to summarize'),
42
- * maxLength: z.string().optional().describe('Maximum length of summary')
43
- * },
44
- * handler: async ({ text, maxLength }) => {
45
- * const summary = await summarizeText(text, maxLength ? parseInt(maxLength) : undefined)
46
- * return {
47
- * messages: [{
48
- * role: 'user',
49
- * content: {
50
- * type: 'text',
51
- * text: summary
52
- * }
53
- * }]
54
- * }
55
- * }
56
- * })
57
- * ```
32
+ * @see https://mcp-toolkit.nuxt.dev/core-concepts/prompts
58
33
  *
59
34
  * @example
60
35
  * ```ts
61
- * // Simple prompt without arguments
62
36
  * export default defineMcpPrompt({
63
- * name: 'greeting',
64
37
  * description: 'Generate a greeting message',
65
- * handler: async () => {
66
- * return {
67
- * messages: [{
68
- * role: 'user',
69
- * content: {
70
- * type: 'text',
71
- * text: 'Hello! How can I help you today?'
72
- * }
73
- * }]
74
- * }
75
- * }
38
+ * handler: async () => ({
39
+ * messages: [{ role: 'user', content: { type: 'text', text: 'Hello!' } }]
40
+ * })
76
41
  * })
77
42
  * ```
78
43
  */
@@ -15,6 +15,7 @@ export interface McpResourceAnnotations {
15
15
  export interface StandardMcpResourceDefinition {
16
16
  name?: string;
17
17
  title?: string;
18
+ description?: string;
18
19
  uri: string | ResourceTemplate;
19
20
  metadata?: ResourceMetadata & {
20
21
  annotations?: McpResourceAnnotations;
@@ -29,6 +30,7 @@ export interface StandardMcpResourceDefinition {
29
30
  export interface FileMcpResourceDefinition {
30
31
  name?: string;
31
32
  title?: string;
33
+ description?: string;
32
34
  uri?: string;
33
35
  metadata?: ResourceMetadata & {
34
36
  annotations?: McpResourceAnnotations;
@@ -48,82 +50,23 @@ export interface FileMcpResourceDefinition {
48
50
  */
49
51
  export type McpResourceDefinition = StandardMcpResourceDefinition | FileMcpResourceDefinition;
50
52
  /**
51
- * Helper function to register a resource from a McpResourceDefinition
53
+ * Register a resource from a McpResourceDefinition
54
+ * @internal
52
55
  */
53
56
  export declare function registerResourceFromDefinition(server: McpServer, resource: McpResourceDefinition): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredResource | import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredResourceTemplate;
54
57
  /**
55
- * Define an MCP resource that will be automatically registered
58
+ * Define an MCP resource that will be automatically registered.
56
59
  *
57
- * This function matches the structure of server.registerResource() from the MCP SDK.
60
+ * `name` and `title` are auto-generated from filename if not provided.
58
61
  *
59
- * If `name` or `title` are not provided, they will be automatically generated from the filename
60
- * (e.g., `list_documentation.ts` → `name: 'list-documentation'`, `title: 'List Documentation'`).
62
+ * @see https://mcp-toolkit.nuxt.dev/core-concepts/resources
61
63
  *
62
64
  * @example
63
65
  * ```ts
64
- * // server/mcp/resources/my-resource.ts
66
+ * // File-based resource
65
67
  * export default defineMcpResource({
66
- * name: 'readme',
67
- * title: 'README',
68
- * uri: 'file:///project/README.md',
69
- * metadata: {
70
- * description: 'Project README file',
71
- * mimeType: 'text/markdown'
72
- * },
73
- * handler: async (uri) => {
74
- * const content = await readFile(uri.pathname, 'utf-8')
75
- * return {
76
- * contents: [{
77
- * uri: uri.toString(),
78
- * mimeType: 'text/markdown',
79
- * text: content
80
- * }]
81
- * }
82
- * }
83
- * })
84
- * ```
85
- *
86
- * @example
87
- * ```ts
88
- * // Simpler file-based resource
89
- * export default defineMcpResource({
90
- * name: 'readme',
91
- * file: 'README.md', // Automatically handles reading file and setting URI
92
- * metadata: {
93
- * description: 'Project README file'
94
- * }
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
- * }
68
+ * description: 'Project README file',
69
+ * file: 'README.md'
127
70
  * })
128
71
  * ```
129
72
  */
@@ -43,7 +43,8 @@ export function registerResourceFromDefinition(server, resource) {
43
43
  let handler = resource.handler;
44
44
  const metadata = {
45
45
  ...resource.metadata,
46
- title: resource.title || resource.metadata?.title || title
46
+ title: resource.title || resource.metadata?.title || title,
47
+ description: resource.description || resource.metadata?.description
47
48
  };
48
49
  if ("file" in resource && resource.file) {
49
50
  const filePath = resolve(process.cwd(), resource.file);
@@ -1,14 +1,42 @@
1
- import type { z, ZodRawShape, ZodTypeAny } from 'zod';
1
+ import type { ZodRawShape } from 'zod';
2
2
  import type { CallToolResult, ServerRequest, ServerNotification, ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
3
3
  import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
4
4
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { ShapeOutput } from '@modelcontextprotocol/sdk/server/zod-compat.js';
5
6
  /**
6
- * Callback type for MCP tools, matching the SDK's ToolCallback type
7
+ * Cache duration strings supported by the `ms` package
7
8
  */
8
- export type McpToolCallback<Args extends ZodRawShape | undefined = ZodRawShape> = Args extends ZodRawShape ? (args: z.objectOutputType<Args, ZodTypeAny>, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult> : (extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => CallToolResult | Promise<CallToolResult>;
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>);
9
10
  /**
10
- * Definition of an MCP tool matching the SDK's registerTool signature
11
- * This structure is identical to what you'd pass to server.registerTool()
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
35
+ */
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>;
37
+ /**
38
+ * MCP tool definition structure
39
+ * @see https://mcp-toolkit.nuxt.dev/core-concepts/tools
12
40
  */
13
41
  export interface McpToolDefinition<InputSchema extends ZodRawShape | undefined = ZodRawShape, OutputSchema extends ZodRawShape = ZodRawShape> {
14
42
  name?: string;
@@ -19,45 +47,36 @@ export interface McpToolDefinition<InputSchema extends ZodRawShape | undefined =
19
47
  annotations?: ToolAnnotations;
20
48
  _meta?: Record<string, unknown>;
21
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>;
22
58
  }
23
59
  /**
24
- * Helper function to register a tool from a McpToolDefinition
25
- * This provides better type inference when registering tools
60
+ * Register a tool from a McpToolDefinition
61
+ * @internal
26
62
  */
27
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;
28
64
  /**
29
- * Define an MCP tool that will be automatically registered
65
+ * Define an MCP tool that will be automatically registered.
30
66
  *
31
- * This function matches the exact structure of server.registerTool() from the MCP SDK,
32
- * making it easy to migrate code from the SDK to this module.
67
+ * `name` and `title` are auto-generated from filename if not provided.
33
68
  *
34
- * If `name` or `title` are not provided, they will be automatically generated from the filename
35
- * (e.g., `list_documentation.ts` → `name: 'list-documentation'`, `title: 'List Documentation'`).
69
+ * @see https://mcp-toolkit.nuxt.dev/core-concepts/tools
36
70
  *
37
71
  * @example
38
72
  * ```ts
39
- * // server/mcp/tools/my-tool.ts
40
- * import { z } from 'zod'
41
- *
42
73
  * export default defineMcpTool({
43
- * name: 'calculate-bmi',
44
- * title: 'BMI Calculator',
45
- * description: 'Calculate Body Mass Index',
46
- * inputSchema: {
47
- * weightKg: z.number(),
48
- * heightM: z.number()
49
- * },
50
- * outputSchema: { bmi: z.number() },
51
- * handler: async ({ weightKg, heightM }) => {
52
- * const output = { bmi: weightKg / (heightM * heightM) }
53
- * return {
54
- * content: [{
55
- * type: 'text',
56
- * text: JSON.stringify(output)
57
- * }],
58
- * structuredContent: output
59
- * }
60
- * }
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
+ * })
61
80
  * })
62
81
  * ```
63
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.1.1",
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",
@@ -33,17 +33,18 @@
33
33
  ],
34
34
  "dependencies": {
35
35
  "@clack/prompts": "^0.11.0",
36
- "@modelcontextprotocol/sdk": "^1.22.0",
36
+ "@modelcontextprotocol/sdk": "^1.23.0",
37
37
  "@nuxt/kit": "^4.2.1",
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"
44
45
  },
45
46
  "peerDependencies": {
46
- "zod": "^3.25.76"
47
+ "zod": "^4.1.13"
47
48
  },
48
49
  "peerDependenciesMeta": {
49
50
  "zod": {