@nuxtjs/mcp-toolkit 0.5.1 → 0.6.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 +22 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +18 -2
- package/dist/runtime/server/mcp/definitions/handlers.d.ts +76 -3
- package/dist/runtime/server/mcp/definitions/tools.d.ts +1 -1
- package/dist/runtime/server/mcp/definitions/tools.js +9 -26
- package/dist/runtime/server/mcp/handler.d.ts +1 -1
- package/dist/runtime/server/mcp/handler.js +17 -2
- package/dist/runtime/server/mcp/loaders/index.d.ts +1 -0
- package/dist/runtime/server/mcp/loaders/index.js +36 -4
- package/dist/runtime/server/mcp/loaders/utils.d.ts +5 -0
- package/dist/runtime/server/mcp/loaders/utils.js +20 -1
- package/dist/runtime/server/mcp/providers/cloudflare.d.ts +2 -0
- package/dist/runtime/server/mcp/providers/cloudflare.js +15 -0
- package/dist/runtime/server/mcp/providers/node.d.ts +2 -0
- package/dist/runtime/server/mcp/providers/node.js +13 -0
- package/dist/runtime/server/mcp/providers/types.d.ts +4 -0
- package/dist/runtime/server/mcp/providers/types.js +1 -0
- package/dist/runtime/server/mcp/utils.d.ts +10 -11
- package/dist/runtime/server/mcp/utils.js +26 -14
- package/dist/runtime/server/types.server.d.ts +7 -0
- package/package.json +17 -13
package/README.md
CHANGED
|
@@ -93,6 +93,16 @@ export default defineMcpTool({
|
|
|
93
93
|
|
|
94
94
|
The tool will be automatically discovered and registered. No imports needed - all helpers are auto-imported!
|
|
95
95
|
|
|
96
|
+
## ☁️ Cloudflare Workers
|
|
97
|
+
|
|
98
|
+
For Cloudflare Workers/Pages deployment, install the [`agents`](https://developers.cloudflare.com/agents/model-context-protocol/mcp-handler-api/) package:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pnpm add agents
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The module automatically detects Cloudflare presets and uses the native MCP handler.
|
|
105
|
+
|
|
96
106
|
## 📚 Documentation
|
|
97
107
|
|
|
98
108
|
📖 **[Full Documentation →](https://mcp-toolkit.nuxt.dev)**
|
|
@@ -132,3 +142,15 @@ Made by [@HugoRCD](https://github.com/HugoRCD) and [community](https://github.co
|
|
|
132
142
|
</a>
|
|
133
143
|
|
|
134
144
|
<!-- /automd -->
|
|
145
|
+
|
|
146
|
+
<!-- automd:fetch url="gh:hugorcd/markdown/main/src/sponsors.md" -->
|
|
147
|
+
|
|
148
|
+
## Sponsors
|
|
149
|
+
|
|
150
|
+
<p align="center">
|
|
151
|
+
<a href="https://github.com/sponsors/HugoRCD">
|
|
152
|
+
<img src='https://cdn.jsdelivr.net/gh/hugorcd/static/sponsors.svg' alt="HugoRCD sponsors" />
|
|
153
|
+
</a>
|
|
154
|
+
</p>
|
|
155
|
+
|
|
156
|
+
<!-- /automd -->
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
|
-
import { logger, createResolver, defineNuxtModule, addComponent, addServerHandler, addServerImports } from '@nuxt/kit';
|
|
2
|
+
import { logger, createResolver, defineNuxtModule, addComponent, addServerHandler, addServerTemplate, addServerImports } from '@nuxt/kit';
|
|
3
3
|
import { defu } from 'defu';
|
|
4
4
|
import { loadAllDefinitions } from '../dist/runtime/server/mcp/loaders/index.js';
|
|
5
5
|
import { defaultMcpConfig } from '../dist/runtime/server/mcp/config.js';
|
|
@@ -7,7 +7,7 @@ import { ROUTES } from '../dist/runtime/server/mcp/constants.js';
|
|
|
7
7
|
import { addDevToolsCustomTabs } from '../dist/runtime/server/mcp/devtools/index.js';
|
|
8
8
|
|
|
9
9
|
const name = "@nuxtjs/mcp-toolkit";
|
|
10
|
-
const version = "0.
|
|
10
|
+
const version = "0.6.0";
|
|
11
11
|
|
|
12
12
|
const log = logger.withTag("@nuxtjs/mcp-toolkit");
|
|
13
13
|
const { resolve } = createResolver(import.meta.url);
|
|
@@ -21,6 +21,10 @@ const module$1 = defineNuxtModule({
|
|
|
21
21
|
},
|
|
22
22
|
defaults: defaultMcpConfig,
|
|
23
23
|
async setup(options, nuxt) {
|
|
24
|
+
if (nuxt.options.nitro.static || nuxt.options._generate) {
|
|
25
|
+
log.warn("@nuxtjs/mcp-toolkit is not compatible with `nuxt generate` as it needs a server to run.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
24
28
|
const resolver = createResolver(import.meta.url);
|
|
25
29
|
nuxt.options.runtimeConfig.mcp = defu(
|
|
26
30
|
nuxt.options.runtimeConfig.mcp,
|
|
@@ -97,6 +101,18 @@ const module$1 = defineNuxtModule({
|
|
|
97
101
|
nuxt.options.nitro.typescript.tsConfig ??= {};
|
|
98
102
|
nuxt.options.nitro.typescript.tsConfig.include ??= [];
|
|
99
103
|
nuxt.options.nitro.typescript.tsConfig.include.push(resolver.resolve("runtime/server/types.server.d.ts"));
|
|
104
|
+
let isCloudflare = false;
|
|
105
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
106
|
+
const preset = nitroConfig.preset || process.env.NITRO_PRESET || "";
|
|
107
|
+
isCloudflare = preset.includes("cloudflare");
|
|
108
|
+
});
|
|
109
|
+
addServerTemplate({
|
|
110
|
+
filename: "#nuxt-mcp/transport.mjs",
|
|
111
|
+
getContents: () => {
|
|
112
|
+
const provider = isCloudflare ? "cloudflare" : "node";
|
|
113
|
+
return `export { default } from '${resolver.resolve(`runtime/server/mcp/providers/${provider}`)}'`;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
100
116
|
const mcpDefinitionsPath = resolver.resolve("runtime/server/mcp/definitions");
|
|
101
117
|
addServerImports([
|
|
102
118
|
"defineMcpTool",
|
|
@@ -1,36 +1,109 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
1
2
|
import type { McpToolDefinition } from './tools.js';
|
|
2
3
|
import type { McpResourceDefinition } from './resources.js';
|
|
3
4
|
import type { McpPromptDefinition } from './prompts.js';
|
|
5
|
+
/**
|
|
6
|
+
* MCP middleware function that runs before/after MCP request processing.
|
|
7
|
+
*
|
|
8
|
+
* If you don't call `next()`, it will be called automatically after your middleware.
|
|
9
|
+
* Call `next()` explicitly if you need to run code after the handler or modify the response.
|
|
10
|
+
*
|
|
11
|
+
* @param event - The H3 event object
|
|
12
|
+
* @param next - Function to call the MCP handler
|
|
13
|
+
*
|
|
14
|
+
* @example Simple middleware (next() called automatically)
|
|
15
|
+
* ```ts
|
|
16
|
+
* middleware: async (event) => {
|
|
17
|
+
* // Just set context - next() is called automatically
|
|
18
|
+
* event.context.userId = 'user-123'
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example Full control middleware
|
|
23
|
+
* ```ts
|
|
24
|
+
* middleware: async (event, next) => {
|
|
25
|
+
* const start = Date.now()
|
|
26
|
+
* const response = await next()
|
|
27
|
+
* console.log(`Request took ${Date.now() - start}ms`)
|
|
28
|
+
* return response
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export type McpMiddleware = (event: H3Event, next: () => Promise<Response | undefined>) => Promise<Response | undefined | void> | Response | undefined | void;
|
|
4
33
|
/**
|
|
5
34
|
* Options for defining a custom MCP handler
|
|
6
35
|
* @see https://mcp-toolkit.nuxt.dev/core-concepts/handlers
|
|
7
36
|
*/
|
|
8
37
|
export interface McpHandlerOptions {
|
|
9
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The name of the handler. Required for custom handlers accessed via /mcp/:handler.
|
|
40
|
+
* Optional for default handler override (server/mcp/index.ts).
|
|
41
|
+
*/
|
|
42
|
+
name?: string;
|
|
10
43
|
version?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Custom route for the handler.
|
|
46
|
+
* Only used for custom handlers (not for default handler override in index.ts).
|
|
47
|
+
* To change the default route, use `mcp.route` in nuxt.config.ts.
|
|
48
|
+
*/
|
|
11
49
|
route?: string;
|
|
12
50
|
browserRedirect?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Middleware to run before/after MCP request processing.
|
|
53
|
+
* If you don't call next(), it will be called automatically.
|
|
54
|
+
*
|
|
55
|
+
* @example Simple (next() auto-called)
|
|
56
|
+
* ```ts
|
|
57
|
+
* middleware: async (event) => {
|
|
58
|
+
* event.context.userId = 'user-123'
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @example Full control
|
|
63
|
+
* ```ts
|
|
64
|
+
* middleware: async (event, next) => {
|
|
65
|
+
* const start = Date.now()
|
|
66
|
+
* const response = await next()
|
|
67
|
+
* console.log(`Took ${Date.now() - start}ms`)
|
|
68
|
+
* return response
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
middleware?: McpMiddleware;
|
|
13
73
|
tools?: Array<McpToolDefinition<any, any>>;
|
|
14
74
|
resources?: McpResourceDefinition[];
|
|
15
75
|
prompts?: McpPromptDefinition[];
|
|
16
76
|
}
|
|
17
|
-
export interface McpHandlerDefinition extends Required<Omit<McpHandlerOptions, 'tools' | 'resources' | 'prompts'>> {
|
|
77
|
+
export interface McpHandlerDefinition extends Required<Omit<McpHandlerOptions, 'tools' | 'resources' | 'prompts' | 'middleware'>> {
|
|
18
78
|
tools: Array<McpToolDefinition<any, any>>;
|
|
19
79
|
resources: McpResourceDefinition[];
|
|
20
80
|
prompts: McpPromptDefinition[];
|
|
81
|
+
middleware?: McpMiddleware;
|
|
21
82
|
}
|
|
22
83
|
/**
|
|
23
84
|
* Define a custom MCP handler with specific tools, resources, and prompts.
|
|
24
85
|
*
|
|
25
86
|
* @see https://mcp-toolkit.nuxt.dev/core-concepts/handlers
|
|
26
87
|
*
|
|
27
|
-
* @example
|
|
88
|
+
* @example Custom handler (accessible via /mcp/:handler)
|
|
28
89
|
* ```ts
|
|
90
|
+
* // server/mcp/my-handler.ts
|
|
29
91
|
* export default defineMcpHandler({
|
|
30
92
|
* name: 'my-handler',
|
|
31
93
|
* tools: [myTool],
|
|
32
94
|
* resources: [myResource]
|
|
33
95
|
* })
|
|
34
96
|
* ```
|
|
97
|
+
*
|
|
98
|
+
* @example Default handler override (server/mcp/index.ts)
|
|
99
|
+
* ```ts
|
|
100
|
+
* // server/mcp/index.ts - overrides the default /mcp handler config
|
|
101
|
+
* export default defineMcpHandler({
|
|
102
|
+
* version: '2.0.0',
|
|
103
|
+
* browserRedirect: '/docs',
|
|
104
|
+
* // Note: 'route' is ignored here. Use mcp.route in nuxt.config.ts instead.
|
|
105
|
+
* // If tools/resources/prompts not specified, uses global definitions
|
|
106
|
+
* })
|
|
107
|
+
* ```
|
|
35
108
|
*/
|
|
36
109
|
export declare function defineMcpHandler(options: McpHandlerOptions): McpHandlerOptions;
|
|
@@ -37,7 +37,7 @@ export interface McpToolDefinition<InputSchema extends ZodRawShape | undefined =
|
|
|
37
37
|
* Register a tool from a McpToolDefinition
|
|
38
38
|
* @internal
|
|
39
39
|
*/
|
|
40
|
-
export declare function registerToolFromDefinition
|
|
40
|
+
export declare function registerToolFromDefinition(server: McpServer, tool: McpToolDefinition): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredTool;
|
|
41
41
|
/**
|
|
42
42
|
* Define an MCP tool that will be automatically registered.
|
|
43
43
|
*
|
|
@@ -19,32 +19,15 @@ export function registerToolFromDefinition(server, tool) {
|
|
|
19
19
|
cacheOptions
|
|
20
20
|
);
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
_meta: tool._meta
|
|
32
|
-
},
|
|
33
|
-
handler
|
|
34
|
-
);
|
|
35
|
-
} else {
|
|
36
|
-
return server.registerTool(
|
|
37
|
-
name,
|
|
38
|
-
{
|
|
39
|
-
title,
|
|
40
|
-
description: tool.description,
|
|
41
|
-
outputSchema: tool.outputSchema,
|
|
42
|
-
annotations: tool.annotations,
|
|
43
|
-
_meta: tool._meta
|
|
44
|
-
},
|
|
45
|
-
handler
|
|
46
|
-
);
|
|
47
|
-
}
|
|
22
|
+
const options = {
|
|
23
|
+
title,
|
|
24
|
+
description: tool.description,
|
|
25
|
+
inputSchema: tool.inputSchema,
|
|
26
|
+
outputSchema: tool.outputSchema,
|
|
27
|
+
annotations: tool.annotations,
|
|
28
|
+
_meta: tool._meta
|
|
29
|
+
};
|
|
30
|
+
return server.registerTool(name, options, handler);
|
|
48
31
|
}
|
|
49
32
|
export function defineMcpTool(definition) {
|
|
50
33
|
return definition;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<
|
|
1
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
|
|
2
2
|
export default _default;
|
|
@@ -4,6 +4,7 @@ import { tools } from "#nuxt-mcp/tools.mjs";
|
|
|
4
4
|
import { resources } from "#nuxt-mcp/resources.mjs";
|
|
5
5
|
import { prompts } from "#nuxt-mcp/prompts.mjs";
|
|
6
6
|
import { handlers } from "#nuxt-mcp/handlers.mjs";
|
|
7
|
+
import { defaultHandler } from "#nuxt-mcp/default-handler.mjs";
|
|
7
8
|
import { createMcpHandler } from "./utils.js";
|
|
8
9
|
import { getMcpConfig } from "./config.js";
|
|
9
10
|
export default createMcpHandler((event) => {
|
|
@@ -18,12 +19,26 @@ export default createMcpHandler((event) => {
|
|
|
18
19
|
throw new Error(`Handler "${handlerName}" not found`);
|
|
19
20
|
}
|
|
20
21
|
return {
|
|
21
|
-
name: handlerDef.name,
|
|
22
|
+
name: handlerDef.name ?? handlerName,
|
|
22
23
|
version: handlerDef.version ?? config.version,
|
|
23
24
|
browserRedirect: handlerDef.browserRedirect ?? config.browserRedirect,
|
|
24
25
|
tools: handlerDef.tools,
|
|
25
26
|
resources: handlerDef.resources,
|
|
26
|
-
prompts: handlerDef.prompts
|
|
27
|
+
prompts: handlerDef.prompts,
|
|
28
|
+
middleware: handlerDef.middleware
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const defaultHandlerDef = defaultHandler;
|
|
32
|
+
if (defaultHandlerDef) {
|
|
33
|
+
return {
|
|
34
|
+
name: defaultHandlerDef.name ?? config.name ?? "MCP Server",
|
|
35
|
+
version: defaultHandlerDef.version ?? config.version,
|
|
36
|
+
browserRedirect: defaultHandlerDef.browserRedirect ?? config.browserRedirect,
|
|
37
|
+
// Use handler's definitions if specified, otherwise use global definitions
|
|
38
|
+
tools: defaultHandlerDef.tools ?? tools,
|
|
39
|
+
resources: defaultHandlerDef.resources ?? resources,
|
|
40
|
+
prompts: defaultHandlerDef.prompts ?? prompts,
|
|
41
|
+
middleware: defaultHandlerDef.middleware
|
|
27
42
|
};
|
|
28
43
|
}
|
|
29
44
|
return {
|
|
@@ -2,6 +2,7 @@ import { addServerTemplate, logger } from "@nuxt/kit";
|
|
|
2
2
|
import {
|
|
3
3
|
createExcludePatterns,
|
|
4
4
|
createTemplateContent,
|
|
5
|
+
findIndexFile,
|
|
5
6
|
loadDefinitionFiles,
|
|
6
7
|
toIdentifier
|
|
7
8
|
} from "./utils.js";
|
|
@@ -47,7 +48,9 @@ async function loadHandlers(paths = []) {
|
|
|
47
48
|
excludePatterns,
|
|
48
49
|
filter: (filePath) => {
|
|
49
50
|
const relativePath = filePath.replace(/.*\/server\//, "");
|
|
50
|
-
|
|
51
|
+
const filename = filePath.split("/").pop();
|
|
52
|
+
const isIndexFile = /^index\.(?:ts|js|mts|mjs)$/.test(filename);
|
|
53
|
+
return !relativePath.includes("/tools/") && !relativePath.includes("/resources/") && !relativePath.includes("/prompts/") && !isIndexFile;
|
|
51
54
|
}
|
|
52
55
|
});
|
|
53
56
|
addServerTemplate({
|
|
@@ -83,19 +86,48 @@ export async function loadPrompts(paths) {
|
|
|
83
86
|
return loadMcpDefinitions("prompts", "#nuxt-mcp/prompts.mjs", paths);
|
|
84
87
|
}
|
|
85
88
|
export { loadHandlers };
|
|
89
|
+
async function loadDefaultHandler(paths = []) {
|
|
90
|
+
try {
|
|
91
|
+
const indexFile = await findIndexFile(paths);
|
|
92
|
+
addServerTemplate({
|
|
93
|
+
filename: "#nuxt-mcp/default-handler.mjs",
|
|
94
|
+
getContents: () => {
|
|
95
|
+
if (!indexFile) {
|
|
96
|
+
return `export const defaultHandler = null
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
return `import handler from '${indexFile}'
|
|
100
|
+
export const defaultHandler = handler
|
|
101
|
+
`;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
return indexFile !== null;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
107
|
+
log.error(`Failed to load default handler: ${errorMessage}`);
|
|
108
|
+
addServerTemplate({
|
|
109
|
+
filename: "#nuxt-mcp/default-handler.mjs",
|
|
110
|
+
getContents: () => `export const defaultHandler = null
|
|
111
|
+
`
|
|
112
|
+
});
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
86
116
|
export async function loadAllDefinitions(paths) {
|
|
87
117
|
try {
|
|
88
|
-
const [tools, resources, prompts, handlers] = await Promise.all([
|
|
118
|
+
const [tools, resources, prompts, handlers, hasDefaultHandler] = await Promise.all([
|
|
89
119
|
loadTools(paths.tools),
|
|
90
120
|
loadResources(paths.resources),
|
|
91
121
|
loadPrompts(paths.prompts),
|
|
92
|
-
loadHandlers(paths.handlers ?? [])
|
|
122
|
+
loadHandlers(paths.handlers ?? []),
|
|
123
|
+
loadDefaultHandler(paths.handlers ?? [])
|
|
93
124
|
]);
|
|
94
125
|
const results = {
|
|
95
126
|
tools,
|
|
96
127
|
resources,
|
|
97
128
|
prompts,
|
|
98
|
-
handlers
|
|
129
|
+
handlers,
|
|
130
|
+
hasDefaultHandler
|
|
99
131
|
};
|
|
100
132
|
return {
|
|
101
133
|
...results,
|
|
@@ -11,6 +11,11 @@ export declare function createLayerFilePatterns(layerServer: string, paths: stri
|
|
|
11
11
|
export declare function createExcludePatterns(paths: string[], subdirs: string[]): string[];
|
|
12
12
|
export declare function toIdentifier(filename: string): string;
|
|
13
13
|
export declare function createTemplateContent(type: string, entries: Array<[string, string]>): string;
|
|
14
|
+
/**
|
|
15
|
+
* Find index files (index.ts, index.js, etc.) in the given paths
|
|
16
|
+
* Returns the file path from the highest priority layer (app overrides extended layers)
|
|
17
|
+
*/
|
|
18
|
+
export declare function findIndexFile(paths: string[], extensions?: string[]): Promise<string | null>;
|
|
14
19
|
export declare function loadDefinitionFiles(paths: string[], options?: {
|
|
15
20
|
excludePatterns?: string[];
|
|
16
21
|
filter?: (filePath: string) => boolean;
|
|
@@ -114,6 +114,25 @@ export const ${type} = [
|
|
|
114
114
|
]
|
|
115
115
|
`;
|
|
116
116
|
}
|
|
117
|
+
export async function findIndexFile(paths, extensions = ["ts", "js", "mts", "mjs"]) {
|
|
118
|
+
if (paths.length === 0) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const layerDirectories = getLayerDirectories();
|
|
122
|
+
for (const layer of layerDirectories) {
|
|
123
|
+
const indexPatterns = paths.flatMap(
|
|
124
|
+
(pathPattern) => extensions.map((ext) => resolvePath(layer.server, `${pathPattern}/index.${ext}`))
|
|
125
|
+
);
|
|
126
|
+
const indexFiles = await glob(indexPatterns, {
|
|
127
|
+
absolute: true,
|
|
128
|
+
onlyFiles: true
|
|
129
|
+
});
|
|
130
|
+
if (indexFiles.length > 0) {
|
|
131
|
+
return indexFiles[0];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
117
136
|
export async function loadDefinitionFiles(paths, options = {}) {
|
|
118
137
|
if (paths.length === 0) {
|
|
119
138
|
return { count: 0, files: [], overriddenCount: 0 };
|
|
@@ -127,7 +146,7 @@ export async function loadDefinitionFiles(paths, options = {}) {
|
|
|
127
146
|
const layerFiles = await glob(layerPatterns, {
|
|
128
147
|
absolute: true,
|
|
129
148
|
onlyFiles: true,
|
|
130
|
-
ignore: options.excludePatterns
|
|
149
|
+
ignore: [...options.excludePatterns || [], "**/*.d.ts"]
|
|
131
150
|
});
|
|
132
151
|
const filteredFiles = options.filter ? layerFiles.filter(options.filter) : layerFiles;
|
|
133
152
|
for (const filePath of filteredFiles) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createMcpHandler } from "agents/mcp";
|
|
2
|
+
import { toWebRequest } from "h3";
|
|
3
|
+
import { createMcpTransportHandler } from "./types.js";
|
|
4
|
+
const fallbackCtx = {
|
|
5
|
+
waitUntil: () => {
|
|
6
|
+
},
|
|
7
|
+
passThroughOnException: () => {
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
export default createMcpTransportHandler((server, event) => {
|
|
11
|
+
const handler = createMcpHandler(server);
|
|
12
|
+
const request = toWebRequest(event);
|
|
13
|
+
const cf = event.context.cloudflare;
|
|
14
|
+
return handler(request, cf?.env ?? {}, cf?.ctx ?? fallbackCtx);
|
|
15
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2
|
+
import { readBody } from "h3";
|
|
3
|
+
import { createMcpTransportHandler } from "./types.js";
|
|
4
|
+
export default createMcpTransportHandler(async (server, event) => {
|
|
5
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
|
|
6
|
+
event.node.res.on("close", () => {
|
|
7
|
+
transport.close();
|
|
8
|
+
server.close();
|
|
9
|
+
});
|
|
10
|
+
await server.connect(transport);
|
|
11
|
+
const body = await readBody(event);
|
|
12
|
+
await transport.handleRequest(event.node.req, event.node.res, body);
|
|
13
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { H3Event } from 'h3';
|
|
3
|
+
export type McpTransportHandler = (server: McpServer, event: H3Event) => Promise<Response | void> | Response | void;
|
|
4
|
+
export declare const createMcpTransportHandler: (handler: McpTransportHandler) => McpTransportHandler;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const createMcpTransportHandler = (handler) => handler;
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import type { H3Event } from 'h3';
|
|
3
|
-
|
|
3
|
+
import type { McpToolDefinition, McpResourceDefinition, McpPromptDefinition, McpMiddleware } from './definitions/index.js';
|
|
4
|
+
export type { McpTransportHandler } from './providers/types.js';
|
|
5
|
+
export { createMcpTransportHandler } from './providers/types.js';
|
|
6
|
+
export interface ResolvedMcpConfig {
|
|
4
7
|
name: string;
|
|
5
8
|
version: string;
|
|
6
9
|
browserRedirect: string;
|
|
7
10
|
tools?: McpToolDefinition[];
|
|
8
11
|
resources?: McpResourceDefinition[];
|
|
9
12
|
prompts?: McpPromptDefinition[];
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
resources?: McpResourceDefinition[];
|
|
16
|
-
prompts?: McpPromptDefinition[];
|
|
17
|
-
});
|
|
18
|
-
export declare function createMcpHandler(config: CreateMcpHandlerConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
|
|
13
|
+
middleware?: McpMiddleware;
|
|
14
|
+
}
|
|
15
|
+
export type CreateMcpHandlerConfig = ResolvedMcpConfig | ((event: H3Event) => ResolvedMcpConfig);
|
|
16
|
+
export declare function createMcpServer(config: ResolvedMcpConfig): McpServer;
|
|
17
|
+
export declare function createMcpHandler(config: CreateMcpHandlerConfig): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import {
|
|
2
|
+
import { sendRedirect, getHeader, defineEventHandler } from "h3";
|
|
3
3
|
import { registerToolFromDefinition, registerResourceFromDefinition, registerPromptFromDefinition } from "./definitions/index.js";
|
|
4
|
-
import
|
|
4
|
+
import handleMcpRequest from "#nuxt-mcp/transport.mjs";
|
|
5
|
+
export { createMcpTransportHandler } from "./providers/types.js";
|
|
5
6
|
function resolveConfig(config, event) {
|
|
6
7
|
return typeof config === "function" ? config(event) : config;
|
|
7
8
|
}
|
|
8
|
-
function createMcpServer(config) {
|
|
9
|
+
export function createMcpServer(config) {
|
|
9
10
|
const server = new McpServer({
|
|
10
11
|
name: config.name,
|
|
11
12
|
version: config.version
|
|
@@ -27,16 +28,27 @@ export function createMcpHandler(config) {
|
|
|
27
28
|
if (getHeader(event, "accept")?.includes("text/html")) {
|
|
28
29
|
return sendRedirect(event, resolvedConfig.browserRedirect);
|
|
29
30
|
}
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
const handler = async () => {
|
|
32
|
+
const server = createMcpServer(resolvedConfig);
|
|
33
|
+
return handleMcpRequest(server, event);
|
|
34
|
+
};
|
|
35
|
+
if (resolvedConfig.middleware) {
|
|
36
|
+
let nextCalled = false;
|
|
37
|
+
let handlerResult;
|
|
38
|
+
const next = async () => {
|
|
39
|
+
nextCalled = true;
|
|
40
|
+
handlerResult = await handler();
|
|
41
|
+
return handlerResult;
|
|
42
|
+
};
|
|
43
|
+
const middlewareResult = await resolvedConfig.middleware(event, next);
|
|
44
|
+
if (middlewareResult !== void 0) {
|
|
45
|
+
return middlewareResult;
|
|
46
|
+
}
|
|
47
|
+
if (nextCalled) {
|
|
48
|
+
return handlerResult;
|
|
49
|
+
}
|
|
50
|
+
return handler();
|
|
51
|
+
}
|
|
52
|
+
return handler();
|
|
41
53
|
});
|
|
42
54
|
}
|
|
@@ -12,3 +12,10 @@ declare module '#nuxt-mcp/resources.mjs' {
|
|
|
12
12
|
declare module '#nuxt-mcp/prompts.mjs' {
|
|
13
13
|
export const prompts: McpPromptDefinition[]
|
|
14
14
|
}
|
|
15
|
+
|
|
16
|
+
declare module '#nuxt-mcp/transport.mjs' {
|
|
17
|
+
import type { McpTransportHandler } from './mcp/providers/types'
|
|
18
|
+
|
|
19
|
+
const handleMcpRequest: McpTransportHandler
|
|
20
|
+
export default handleMcpRequest
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtjs/mcp-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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,10 +33,10 @@
|
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@clack/prompts": "^0.11.0",
|
|
36
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
37
|
-
"@nuxt/kit": "^4.2.
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
37
|
+
"@nuxt/kit": "^4.2.2",
|
|
38
38
|
"automd": "^0.4.2",
|
|
39
|
-
"chokidar": "^
|
|
39
|
+
"chokidar": "^5.0.0",
|
|
40
40
|
"defu": "^6.1.4",
|
|
41
41
|
"ms": "^2.1.3",
|
|
42
42
|
"pathe": "^2.0.3",
|
|
@@ -45,26 +45,30 @@
|
|
|
45
45
|
"tinyglobby": "^0.2.15"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"zod": "^4.1.13"
|
|
48
|
+
"zod": "^4.1.13",
|
|
49
|
+
"agents": ">=0.2.32"
|
|
49
50
|
},
|
|
50
51
|
"peerDependenciesMeta": {
|
|
51
52
|
"zod": {
|
|
52
53
|
"optional": false
|
|
54
|
+
},
|
|
55
|
+
"agents": {
|
|
56
|
+
"optional": true
|
|
53
57
|
}
|
|
54
58
|
},
|
|
55
59
|
"devDependencies": {
|
|
56
|
-
"@nuxt/devtools": "^3.1.
|
|
57
|
-
"@nuxt/eslint-config": "^1.
|
|
60
|
+
"@nuxt/devtools": "^3.1.1",
|
|
61
|
+
"@nuxt/eslint-config": "^1.12.1",
|
|
58
62
|
"@nuxt/module-builder": "^1.0.2",
|
|
59
|
-
"@nuxt/schema": "^4.2.
|
|
60
|
-
"@nuxt/test-utils": "^3.
|
|
63
|
+
"@nuxt/schema": "^4.2.2",
|
|
64
|
+
"@nuxt/test-utils": "^3.21.0",
|
|
61
65
|
"@types/node": "latest",
|
|
62
66
|
"changelogen": "^0.6.2",
|
|
63
|
-
"eslint": "^9.39.
|
|
64
|
-
"nuxt": "^4.2.
|
|
67
|
+
"eslint": "^9.39.2",
|
|
68
|
+
"nuxt": "^4.2.2",
|
|
65
69
|
"typescript": "~5.9.3",
|
|
66
|
-
"vitest": "^4.0.
|
|
67
|
-
"vue-tsc": "^3.1.
|
|
70
|
+
"vitest": "^4.0.16",
|
|
71
|
+
"vue-tsc": "^3.1.8"
|
|
68
72
|
},
|
|
69
73
|
"publishConfig": {
|
|
70
74
|
"access": "public"
|