@mcp-weave/express 0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mcp-weave
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # @mcp-weave/express
2
+
3
+ Express middleware and server for MCP (Model Context Protocol) servers.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @mcp-weave/express express
9
+ # or
10
+ pnpm add @mcp-weave/express express
11
+ ```
12
+
13
+ ## Features
14
+
15
+ - **Middleware** - Integrate MCP servers into existing Express apps
16
+ - **Standalone Server** - Quick setup for MCP-only servers
17
+ - **Router** - Mount MCP endpoints on any path
18
+ - **CORS Support** - Built-in CORS handling
19
+ - **REST API** - HTTP endpoints for tools, resources, and prompts
20
+
21
+ ## Quick Start
22
+
23
+ ### Standalone Server
24
+
25
+ ```typescript
26
+ import 'reflect-metadata';
27
+ import { McpExpressServer, McpServer, McpTool, McpInput } from '@mcp-weave/express';
28
+
29
+ @McpServer({ name: 'my-server', version: '1.0.0' })
30
+ class MyServer {
31
+ @McpTool({
32
+ name: 'greet',
33
+ description: 'Greets a user',
34
+ inputSchema: {
35
+ type: 'object',
36
+ properties: { name: { type: 'string' } },
37
+ required: ['name'],
38
+ },
39
+ })
40
+ greet(@McpInput() input: { name: string }) {
41
+ return `Hello, ${input.name}!`;
42
+ }
43
+ }
44
+
45
+ const server = new McpExpressServer(MyServer, { port: 3000 });
46
+ await server.start();
47
+ // Server running at http://localhost:3000/mcp
48
+ ```
49
+
50
+ ### Middleware Integration
51
+
52
+ ```typescript
53
+ import express from 'express';
54
+ import { createMcpMiddleware, McpServer, McpTool } from '@mcp-weave/express';
55
+
56
+ @McpServer({ name: 'my-server', version: '1.0.0' })
57
+ class MyServer {
58
+ @McpTool({ name: 'hello', description: 'Say hello' })
59
+ hello() {
60
+ return 'Hello!';
61
+ }
62
+ }
63
+
64
+ const app = express();
65
+ app.use(express.json());
66
+ app.use('/mcp', createMcpMiddleware(MyServer));
67
+
68
+ // Your other routes
69
+ app.get('/', (req, res) => res.send('Welcome!'));
70
+
71
+ app.listen(3000);
72
+ ```
73
+
74
+ ### Router
75
+
76
+ ```typescript
77
+ import express from 'express';
78
+ import { createMcpRouter, McpServer, McpTool } from '@mcp-weave/express';
79
+
80
+ @McpServer({ name: 'my-server', version: '1.0.0' })
81
+ class MyServer {
82
+ @McpTool({ name: 'hello', description: 'Say hello' })
83
+ hello() {
84
+ return 'Hello!';
85
+ }
86
+ }
87
+
88
+ const app = express();
89
+ app.use(express.json());
90
+ app.use('/api/v1/mcp', createMcpRouter(MyServer));
91
+ app.listen(3000);
92
+ ```
93
+
94
+ ## API Endpoints
95
+
96
+ Once mounted, the following endpoints are available:
97
+
98
+ | Method | Endpoint | Description |
99
+ | ------ | ----------------- | ------------------------------ |
100
+ | GET | `/health` | Server health and capabilities |
101
+ | GET | `/tools` | List available tools |
102
+ | POST | `/tools/call` | Call a tool |
103
+ | GET | `/resources` | List available resources |
104
+ | POST | `/resources/read` | Read a resource |
105
+ | GET | `/prompts` | List available prompts |
106
+ | POST | `/prompts/get` | Get a prompt |
107
+
108
+ ### Example Requests
109
+
110
+ **Call a tool:**
111
+
112
+ ```bash
113
+ curl -X POST http://localhost:3000/mcp/tools/call \
114
+ -H "Content-Type: application/json" \
115
+ -d '{"name": "greet", "arguments": {"name": "World"}}'
116
+ ```
117
+
118
+ **Read a resource:**
119
+
120
+ ```bash
121
+ curl -X POST http://localhost:3000/mcp/resources/read \
122
+ -H "Content-Type: application/json" \
123
+ -d '{"uri": "config://settings"}'
124
+ ```
125
+
126
+ **Get a prompt:**
127
+
128
+ ```bash
129
+ curl -X POST http://localhost:3000/mcp/prompts/get \
130
+ -H "Content-Type: application/json" \
131
+ -d '{"name": "welcome", "arguments": {"username": "Alice"}}'
132
+ ```
133
+
134
+ ## Options
135
+
136
+ ### McpMiddlewareOptions
137
+
138
+ | Option | Type | Default | Description |
139
+ | ------------ | --------- | -------- | --------------------------- |
140
+ | `basePath` | `string` | `'/mcp'` | Base path for MCP endpoints |
141
+ | `cors` | `boolean` | `true` | Enable CORS headers |
142
+ | `corsOrigin` | `string` | `'*'` | CORS origin header |
143
+
144
+ ### McpExpressOptions
145
+
146
+ Extends `McpMiddlewareOptions` with:
147
+
148
+ | Option | Type | Default | Description |
149
+ | ------ | --------- | ----------- | ------------------ |
150
+ | `port` | `number` | `3000` | Server port |
151
+ | `host` | `string` | `'0.0.0.0'` | Server host |
152
+ | `app` | `Express` | - | Custom Express app |
153
+
154
+ ## Related Packages
155
+
156
+ - [`@mcp-weave/nestjs`](https://www.npmjs.com/package/@mcp-weave/nestjs) - NestJS-style decorators
157
+ - [`@mcp-weave/testing`](https://www.npmjs.com/package/@mcp-weave/testing) - Testing utilities
158
+ - [`@mcp-weave/cli`](https://www.npmjs.com/package/@mcp-weave/cli) - CLI tools
159
+
160
+ ## License
161
+
162
+ MIT
@@ -0,0 +1,125 @@
1
+ import { RequestHandler, Express, Router } from 'express';
2
+ export { McpInput, McpParam, McpPrompt, McpPromptArg, McpResource, McpServer, McpTool } from '@mcp-weave/nestjs';
3
+
4
+ /**
5
+ * Options for MCP Express middleware
6
+ */
7
+ interface McpMiddlewareOptions {
8
+ /**
9
+ * Base path for MCP endpoints (default: '/mcp')
10
+ */
11
+ basePath?: string;
12
+ /**
13
+ * Enable CORS headers (default: true)
14
+ */
15
+ cors?: boolean;
16
+ /**
17
+ * Custom CORS origin (default: '*')
18
+ */
19
+ corsOrigin?: string;
20
+ }
21
+ /**
22
+ * Create Express middleware for an MCP server
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import express from 'express';
27
+ * import { createMcpMiddleware, McpServer, McpTool } from '@mcp-weave/express';
28
+ *
29
+ * @McpServer({ name: 'my-server', version: '1.0.0' })
30
+ * class MyServer {
31
+ * @McpTool({ name: 'hello', description: 'Say hello' })
32
+ * hello(input: { name: string }) {
33
+ * return `Hello, ${input.name}!`;
34
+ * }
35
+ * }
36
+ *
37
+ * const app = express();
38
+ * app.use('/mcp', createMcpMiddleware(MyServer));
39
+ * app.listen(3000);
40
+ * ```
41
+ */
42
+ declare function createMcpMiddleware(target: Function, options?: McpMiddlewareOptions): RequestHandler;
43
+
44
+ /**
45
+ * Options for MCP Express server
46
+ */
47
+ interface McpExpressOptions extends McpMiddlewareOptions {
48
+ /**
49
+ * Port to listen on (default: 3000)
50
+ */
51
+ port?: number;
52
+ /**
53
+ * Host to bind to (default: '0.0.0.0')
54
+ */
55
+ host?: string;
56
+ /**
57
+ * Custom Express app (if you want to add other middleware)
58
+ */
59
+ app?: Express;
60
+ }
61
+ /**
62
+ * Standalone Express server for MCP
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * import { McpExpressServer, McpServer, McpTool } from '@mcp-weave/express';
67
+ *
68
+ * @McpServer({ name: 'my-server', version: '1.0.0' })
69
+ * class MyServer {
70
+ * @McpTool({ name: 'hello', description: 'Say hello' })
71
+ * hello(input: { name: string }) {
72
+ * return `Hello, ${input.name}!`;
73
+ * }
74
+ * }
75
+ *
76
+ * const server = new McpExpressServer(MyServer);
77
+ * await server.start();
78
+ * // Server running at http://localhost:3000/mcp
79
+ * ```
80
+ */
81
+ declare class McpExpressServer {
82
+ private app;
83
+ private target;
84
+ private options;
85
+ private httpServer?;
86
+ constructor(target: Function, options?: McpExpressOptions);
87
+ /**
88
+ * Start the Express server
89
+ */
90
+ start(): Promise<void>;
91
+ /**
92
+ * Stop the server
93
+ */
94
+ stop(): Promise<void>;
95
+ /**
96
+ * Get the Express app instance
97
+ */
98
+ getApp(): Express;
99
+ }
100
+
101
+ /**
102
+ * Create an Express Router for MCP endpoints
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * import express from 'express';
107
+ * import { createMcpRouter, McpServer, McpTool } from '@mcp-weave/express';
108
+ *
109
+ * @McpServer({ name: 'my-server', version: '1.0.0' })
110
+ * class MyServer {
111
+ * @McpTool({ name: 'hello', description: 'Say hello' })
112
+ * hello(input: { name: string }) {
113
+ * return `Hello, ${input.name}!`;
114
+ * }
115
+ * }
116
+ *
117
+ * const app = express();
118
+ * app.use(express.json());
119
+ * app.use('/api/mcp', createMcpRouter(MyServer));
120
+ * app.listen(3000);
121
+ * ```
122
+ */
123
+ declare function createMcpRouter(target: Function, options?: McpMiddlewareOptions): Router;
124
+
125
+ export { type McpExpressOptions, McpExpressServer, type McpMiddlewareOptions, createMcpMiddleware, createMcpRouter };
@@ -0,0 +1,125 @@
1
+ import { RequestHandler, Express, Router } from 'express';
2
+ export { McpInput, McpParam, McpPrompt, McpPromptArg, McpResource, McpServer, McpTool } from '@mcp-weave/nestjs';
3
+
4
+ /**
5
+ * Options for MCP Express middleware
6
+ */
7
+ interface McpMiddlewareOptions {
8
+ /**
9
+ * Base path for MCP endpoints (default: '/mcp')
10
+ */
11
+ basePath?: string;
12
+ /**
13
+ * Enable CORS headers (default: true)
14
+ */
15
+ cors?: boolean;
16
+ /**
17
+ * Custom CORS origin (default: '*')
18
+ */
19
+ corsOrigin?: string;
20
+ }
21
+ /**
22
+ * Create Express middleware for an MCP server
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import express from 'express';
27
+ * import { createMcpMiddleware, McpServer, McpTool } from '@mcp-weave/express';
28
+ *
29
+ * @McpServer({ name: 'my-server', version: '1.0.0' })
30
+ * class MyServer {
31
+ * @McpTool({ name: 'hello', description: 'Say hello' })
32
+ * hello(input: { name: string }) {
33
+ * return `Hello, ${input.name}!`;
34
+ * }
35
+ * }
36
+ *
37
+ * const app = express();
38
+ * app.use('/mcp', createMcpMiddleware(MyServer));
39
+ * app.listen(3000);
40
+ * ```
41
+ */
42
+ declare function createMcpMiddleware(target: Function, options?: McpMiddlewareOptions): RequestHandler;
43
+
44
+ /**
45
+ * Options for MCP Express server
46
+ */
47
+ interface McpExpressOptions extends McpMiddlewareOptions {
48
+ /**
49
+ * Port to listen on (default: 3000)
50
+ */
51
+ port?: number;
52
+ /**
53
+ * Host to bind to (default: '0.0.0.0')
54
+ */
55
+ host?: string;
56
+ /**
57
+ * Custom Express app (if you want to add other middleware)
58
+ */
59
+ app?: Express;
60
+ }
61
+ /**
62
+ * Standalone Express server for MCP
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * import { McpExpressServer, McpServer, McpTool } from '@mcp-weave/express';
67
+ *
68
+ * @McpServer({ name: 'my-server', version: '1.0.0' })
69
+ * class MyServer {
70
+ * @McpTool({ name: 'hello', description: 'Say hello' })
71
+ * hello(input: { name: string }) {
72
+ * return `Hello, ${input.name}!`;
73
+ * }
74
+ * }
75
+ *
76
+ * const server = new McpExpressServer(MyServer);
77
+ * await server.start();
78
+ * // Server running at http://localhost:3000/mcp
79
+ * ```
80
+ */
81
+ declare class McpExpressServer {
82
+ private app;
83
+ private target;
84
+ private options;
85
+ private httpServer?;
86
+ constructor(target: Function, options?: McpExpressOptions);
87
+ /**
88
+ * Start the Express server
89
+ */
90
+ start(): Promise<void>;
91
+ /**
92
+ * Stop the server
93
+ */
94
+ stop(): Promise<void>;
95
+ /**
96
+ * Get the Express app instance
97
+ */
98
+ getApp(): Express;
99
+ }
100
+
101
+ /**
102
+ * Create an Express Router for MCP endpoints
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * import express from 'express';
107
+ * import { createMcpRouter, McpServer, McpTool } from '@mcp-weave/express';
108
+ *
109
+ * @McpServer({ name: 'my-server', version: '1.0.0' })
110
+ * class MyServer {
111
+ * @McpTool({ name: 'hello', description: 'Say hello' })
112
+ * hello(input: { name: string }) {
113
+ * return `Hello, ${input.name}!`;
114
+ * }
115
+ * }
116
+ *
117
+ * const app = express();
118
+ * app.use(express.json());
119
+ * app.use('/api/mcp', createMcpRouter(MyServer));
120
+ * app.listen(3000);
121
+ * ```
122
+ */
123
+ declare function createMcpRouter(target: Function, options?: McpMiddlewareOptions): Router;
124
+
125
+ export { type McpExpressOptions, McpExpressServer, type McpMiddlewareOptions, createMcpMiddleware, createMcpRouter };
package/dist/index.js ADDED
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ McpExpressServer: () => McpExpressServer,
34
+ McpInput: () => import_nestjs3.McpInput,
35
+ McpParam: () => import_nestjs3.McpParam,
36
+ McpPrompt: () => import_nestjs3.McpPrompt,
37
+ McpPromptArg: () => import_nestjs3.McpPromptArg,
38
+ McpResource: () => import_nestjs3.McpResource,
39
+ McpServer: () => import_nestjs3.McpServer,
40
+ McpTool: () => import_nestjs3.McpTool,
41
+ createMcpMiddleware: () => createMcpMiddleware,
42
+ createMcpRouter: () => createMcpRouter
43
+ });
44
+ module.exports = __toCommonJS(index_exports);
45
+
46
+ // src/middleware.ts
47
+ var import_nestjs = require("@mcp-weave/nestjs");
48
+ function createMcpMiddleware(target, options = {}) {
49
+ const { cors = true, corsOrigin = "*" } = options;
50
+ const state = {
51
+ metadata: (0, import_nestjs.extractMetadata)(target),
52
+ target
53
+ };
54
+ return async (req, res, next) => {
55
+ if (cors) {
56
+ res.setHeader("Access-Control-Allow-Origin", corsOrigin);
57
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
58
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
59
+ if (req.method === "OPTIONS") {
60
+ res.status(200).end();
61
+ return;
62
+ }
63
+ }
64
+ const path = req.path;
65
+ try {
66
+ if (path === "/health" || path === "/") {
67
+ res.json({
68
+ status: "ok",
69
+ server: state.metadata.server?.name,
70
+ version: state.metadata.server?.version,
71
+ capabilities: {
72
+ tools: state.metadata.tools.length,
73
+ resources: state.metadata.resources.length,
74
+ prompts: state.metadata.prompts.length
75
+ }
76
+ });
77
+ return;
78
+ }
79
+ if (path === "/tools" && req.method === "GET") {
80
+ res.json({
81
+ tools: state.metadata.tools.map((t) => ({
82
+ name: t.name,
83
+ description: t.description,
84
+ inputSchema: t.inputSchema
85
+ }))
86
+ });
87
+ return;
88
+ }
89
+ if (path === "/tools/call" && req.method === "POST") {
90
+ const { name, arguments: args } = req.body;
91
+ if (!name) {
92
+ res.status(400).json({ error: "Tool name is required" });
93
+ return;
94
+ }
95
+ const tool = state.metadata.tools.find((t) => t.name === name);
96
+ if (!tool) {
97
+ res.status(404).json({ error: `Tool not found: ${name}` });
98
+ return;
99
+ }
100
+ const instance = new state.target();
101
+ const method = Reflect.get(instance, tool.propertyKey);
102
+ if (typeof method !== "function") {
103
+ res.status(500).json({ error: `Method ${String(tool.propertyKey)} not found` });
104
+ return;
105
+ }
106
+ const result = await method.call(instance, args ?? {});
107
+ res.json({
108
+ content: [
109
+ {
110
+ type: "text",
111
+ text: typeof result === "string" ? result : JSON.stringify(result)
112
+ }
113
+ ]
114
+ });
115
+ return;
116
+ }
117
+ if (path === "/resources" && req.method === "GET") {
118
+ res.json({
119
+ resources: state.metadata.resources.map((r) => ({
120
+ uri: r.uri,
121
+ name: r.name,
122
+ description: r.description,
123
+ mimeType: r.mimeType
124
+ }))
125
+ });
126
+ return;
127
+ }
128
+ if (path === "/resources/read" && req.method === "POST") {
129
+ const { uri } = req.body;
130
+ if (!uri) {
131
+ res.status(400).json({ error: "Resource URI is required" });
132
+ return;
133
+ }
134
+ const instance = new state.target();
135
+ for (const resource of state.metadata.resources) {
136
+ const uriParams = extractUriParams(resource.uri, uri);
137
+ if (uriParams) {
138
+ const method = Reflect.get(instance, resource.propertyKey);
139
+ if (typeof method !== "function") {
140
+ res.status(500).json({ error: `Method ${String(resource.propertyKey)} not found` });
141
+ return;
142
+ }
143
+ const params = state.metadata.params.filter(
144
+ (p) => p.propertyKey === resource.propertyKey && p.type === "param"
145
+ );
146
+ const args = [];
147
+ for (const param of params) {
148
+ if (param.name) {
149
+ args[param.parameterIndex] = uriParams[param.name];
150
+ }
151
+ }
152
+ const result = await method.apply(instance, args);
153
+ res.json(result);
154
+ return;
155
+ }
156
+ }
157
+ res.status(404).json({ error: `Resource not found: ${uri}` });
158
+ return;
159
+ }
160
+ if (path === "/prompts" && req.method === "GET") {
161
+ res.json({
162
+ prompts: state.metadata.prompts.map((p) => ({
163
+ name: p.name,
164
+ description: p.description,
165
+ arguments: p.arguments
166
+ }))
167
+ });
168
+ return;
169
+ }
170
+ if (path === "/prompts/get" && req.method === "POST") {
171
+ const { name, arguments: args } = req.body;
172
+ if (!name) {
173
+ res.status(400).json({ error: "Prompt name is required" });
174
+ return;
175
+ }
176
+ const prompt = state.metadata.prompts.find((p) => p.name === name);
177
+ if (!prompt) {
178
+ res.status(404).json({ error: `Prompt not found: ${name}` });
179
+ return;
180
+ }
181
+ const instance = new state.target();
182
+ const method = Reflect.get(instance, prompt.propertyKey);
183
+ if (typeof method !== "function") {
184
+ res.status(500).json({ error: `Method ${String(prompt.propertyKey)} not found` });
185
+ return;
186
+ }
187
+ const params = state.metadata.params.filter(
188
+ (p) => p.propertyKey === prompt.propertyKey && p.type === "promptArg"
189
+ );
190
+ const methodArgs = [];
191
+ for (const param of params) {
192
+ if (param.name && args) {
193
+ methodArgs[param.parameterIndex] = args[param.name];
194
+ }
195
+ }
196
+ const result = await method.apply(instance, methodArgs);
197
+ res.json(result);
198
+ return;
199
+ }
200
+ next();
201
+ } catch (error) {
202
+ res.status(500).json({
203
+ error: error instanceof Error ? error.message : "Internal server error"
204
+ });
205
+ }
206
+ };
207
+ }
208
+ function extractUriParams(template, uri) {
209
+ const paramNames = [];
210
+ const regexStr = template.replace(/\{(\w+)\}/g, (_, name) => {
211
+ paramNames.push(name);
212
+ return "([^/]+)";
213
+ });
214
+ const regex = new RegExp(`^${regexStr}$`);
215
+ const match = uri.match(regex);
216
+ if (!match) return null;
217
+ const params = {};
218
+ paramNames.forEach((name, index) => {
219
+ params[name] = match[index + 1] ?? "";
220
+ });
221
+ return params;
222
+ }
223
+
224
+ // src/server.ts
225
+ var import_express = __toESM(require("express"));
226
+ var import_nestjs2 = require("@mcp-weave/nestjs");
227
+ var McpExpressServer = class {
228
+ app;
229
+ target;
230
+ options;
231
+ httpServer;
232
+ constructor(target, options = {}) {
233
+ this.target = target;
234
+ this.options = options;
235
+ this.app = options.app ?? (0, import_express.default)();
236
+ this.app.use(import_express.default.json());
237
+ this.app.use(
238
+ options.basePath ?? "/mcp",
239
+ createMcpMiddleware(target, options)
240
+ );
241
+ }
242
+ /**
243
+ * Start the Express server
244
+ */
245
+ async start() {
246
+ const port = this.options.port ?? 3e3;
247
+ const host = this.options.host ?? "0.0.0.0";
248
+ const basePath = this.options.basePath ?? "/mcp";
249
+ const metadata = (0, import_nestjs2.extractMetadata)(this.target);
250
+ return new Promise((resolve) => {
251
+ this.httpServer = this.app.listen(port, host, () => {
252
+ console.log(`\u{1F680} MCP Express server '${metadata.server?.name}' started`);
253
+ console.log(
254
+ ` Base URL: http://${host === "0.0.0.0" ? "localhost" : host}:${port}${basePath}`
255
+ );
256
+ console.log(
257
+ ` Health: http://${host === "0.0.0.0" ? "localhost" : host}:${port}${basePath}/health`
258
+ );
259
+ console.log(` Tools: ${metadata.tools.length}`);
260
+ console.log(` Resources: ${metadata.resources.length}`);
261
+ console.log(` Prompts: ${metadata.prompts.length}`);
262
+ resolve();
263
+ });
264
+ });
265
+ }
266
+ /**
267
+ * Stop the server
268
+ */
269
+ async stop() {
270
+ return new Promise((resolve, reject) => {
271
+ if (this.httpServer) {
272
+ this.httpServer.close((err) => {
273
+ if (err) reject(err);
274
+ else resolve();
275
+ });
276
+ } else {
277
+ resolve();
278
+ }
279
+ });
280
+ }
281
+ /**
282
+ * Get the Express app instance
283
+ */
284
+ getApp() {
285
+ return this.app;
286
+ }
287
+ };
288
+
289
+ // src/router.ts
290
+ var import_express2 = require("express");
291
+ function createMcpRouter(target, options = {}) {
292
+ const router = (0, import_express2.Router)();
293
+ router.use(createMcpMiddleware(target, options));
294
+ return router;
295
+ }
296
+
297
+ // src/index.ts
298
+ var import_nestjs3 = require("@mcp-weave/nestjs");
299
+ // Annotate the CommonJS export names for ESM import in node:
300
+ 0 && (module.exports = {
301
+ McpExpressServer,
302
+ McpInput,
303
+ McpParam,
304
+ McpPrompt,
305
+ McpPromptArg,
306
+ McpResource,
307
+ McpServer,
308
+ McpTool,
309
+ createMcpMiddleware,
310
+ createMcpRouter
311
+ });
312
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/middleware.ts","../src/server.ts","../src/router.ts"],"sourcesContent":["/**\n * @mcp-weave/express\n *\n * Express middleware for MCP (Model Context Protocol) servers.\n * Provides easy integration of MCP servers with Express applications.\n */\n\nexport { createMcpMiddleware, type McpMiddlewareOptions } from './middleware.js';\nexport { McpExpressServer, type McpExpressOptions } from './server.js';\nexport { createMcpRouter } from './router.js';\n\n// Re-export common decorators from nestjs for convenience\nexport {\n McpServer,\n McpTool,\n McpResource,\n McpPrompt,\n McpInput,\n McpParam,\n McpPromptArg,\n} from '@mcp-weave/nestjs';\n","import type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { extractMetadata } from '@mcp-weave/nestjs';\n\n/**\n * Options for MCP Express middleware\n */\nexport interface McpMiddlewareOptions {\n /**\n * Base path for MCP endpoints (default: '/mcp')\n */\n basePath?: string;\n\n /**\n * Enable CORS headers (default: true)\n */\n cors?: boolean;\n\n /**\n * Custom CORS origin (default: '*')\n */\n corsOrigin?: string;\n}\n\n/**\n * Internal state for MCP middleware\n */\ninterface McpMiddlewareState {\n metadata: ReturnType<typeof extractMetadata>;\n target: Function;\n}\n\n/**\n * Create Express middleware for an MCP server\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { createMcpMiddleware, McpServer, McpTool } from '@mcp-weave/express';\n *\n * @McpServer({ name: 'my-server', version: '1.0.0' })\n * class MyServer {\n * @McpTool({ name: 'hello', description: 'Say hello' })\n * hello(input: { name: string }) {\n * return `Hello, ${input.name}!`;\n * }\n * }\n *\n * const app = express();\n * app.use('/mcp', createMcpMiddleware(MyServer));\n * app.listen(3000);\n * ```\n */\nexport function createMcpMiddleware(\n target: Function,\n options: McpMiddlewareOptions = {}\n): RequestHandler {\n const { cors = true, corsOrigin = '*' } = options;\n\n // Initialize metadata\n const state: McpMiddlewareState = {\n metadata: extractMetadata(target),\n target,\n };\n\n return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n // Handle CORS\n if (cors) {\n res.setHeader('Access-Control-Allow-Origin', corsOrigin);\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.status(200).end();\n return;\n }\n }\n\n const path = req.path;\n\n try {\n // Health check\n if (path === '/health' || path === '/') {\n res.json({\n status: 'ok',\n server: state.metadata.server?.name,\n version: state.metadata.server?.version,\n capabilities: {\n tools: state.metadata.tools.length,\n resources: state.metadata.resources.length,\n prompts: state.metadata.prompts.length,\n },\n });\n return;\n }\n\n // List tools\n if (path === '/tools' && req.method === 'GET') {\n res.json({\n tools: state.metadata.tools.map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n });\n return;\n }\n\n // Call tool\n if (path === '/tools/call' && req.method === 'POST') {\n const { name, arguments: args } = req.body as {\n name: string;\n arguments?: Record<string, unknown>;\n };\n\n if (!name) {\n res.status(400).json({ error: 'Tool name is required' });\n return;\n }\n\n const tool = state.metadata.tools.find(t => t.name === name);\n if (!tool) {\n res.status(404).json({ error: `Tool not found: ${name}` });\n return;\n }\n\n // Execute tool via internal server\n const instance = new (state.target as new () => unknown)();\n const method = Reflect.get(instance as object, tool.propertyKey);\n\n if (typeof method !== 'function') {\n res.status(500).json({ error: `Method ${String(tool.propertyKey)} not found` });\n return;\n }\n\n const result = await method.call(instance, args ?? {});\n res.json({\n content: [\n {\n type: 'text',\n text: typeof result === 'string' ? result : JSON.stringify(result),\n },\n ],\n });\n return;\n }\n\n // List resources\n if (path === '/resources' && req.method === 'GET') {\n res.json({\n resources: state.metadata.resources.map(r => ({\n uri: r.uri,\n name: r.name,\n description: r.description,\n mimeType: r.mimeType,\n })),\n });\n return;\n }\n\n // Read resource\n if (path === '/resources/read' && req.method === 'POST') {\n const { uri } = req.body as { uri: string };\n\n if (!uri) {\n res.status(400).json({ error: 'Resource URI is required' });\n return;\n }\n\n const instance = new (state.target as new () => unknown)();\n\n for (const resource of state.metadata.resources) {\n const uriParams = extractUriParams(resource.uri, uri);\n if (uriParams) {\n const method = Reflect.get(instance as object, resource.propertyKey);\n if (typeof method !== 'function') {\n res.status(500).json({ error: `Method ${String(resource.propertyKey)} not found` });\n return;\n }\n\n // Resolve params\n const params = state.metadata.params.filter(\n p => p.propertyKey === resource.propertyKey && p.type === 'param'\n );\n const args: unknown[] = [];\n for (const param of params) {\n if (param.name) {\n args[param.parameterIndex] = uriParams[param.name];\n }\n }\n\n const result = await method.apply(instance, args);\n res.json(result);\n return;\n }\n }\n\n res.status(404).json({ error: `Resource not found: ${uri}` });\n return;\n }\n\n // List prompts\n if (path === '/prompts' && req.method === 'GET') {\n res.json({\n prompts: state.metadata.prompts.map(p => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments,\n })),\n });\n return;\n }\n\n // Get prompt\n if (path === '/prompts/get' && req.method === 'POST') {\n const { name, arguments: args } = req.body as {\n name: string;\n arguments?: Record<string, unknown>;\n };\n\n if (!name) {\n res.status(400).json({ error: 'Prompt name is required' });\n return;\n }\n\n const prompt = state.metadata.prompts.find(p => p.name === name);\n if (!prompt) {\n res.status(404).json({ error: `Prompt not found: ${name}` });\n return;\n }\n\n const instance = new (state.target as new () => unknown)();\n const method = Reflect.get(instance as object, prompt.propertyKey);\n\n if (typeof method !== 'function') {\n res.status(500).json({ error: `Method ${String(prompt.propertyKey)} not found` });\n return;\n }\n\n // Resolve prompt args\n const params = state.metadata.params.filter(\n p => p.propertyKey === prompt.propertyKey && p.type === 'promptArg'\n );\n const methodArgs: unknown[] = [];\n for (const param of params) {\n if (param.name && args) {\n methodArgs[param.parameterIndex] = args[param.name];\n }\n }\n\n const result = await method.apply(instance, methodArgs);\n res.json(result);\n return;\n }\n\n // Not found\n next();\n } catch (error) {\n res.status(500).json({\n error: error instanceof Error ? error.message : 'Internal server error',\n });\n }\n };\n}\n\n/**\n * Extract parameters from a URI template\n */\nfunction extractUriParams(template: string, uri: string): Record<string, string> | null {\n const paramNames: string[] = [];\n const regexStr = template.replace(/\\{(\\w+)\\}/g, (_, name) => {\n paramNames.push(name);\n return '([^/]+)';\n });\n\n const regex = new RegExp(`^${regexStr}$`);\n const match = uri.match(regex);\n\n if (!match) return null;\n\n const params: Record<string, string> = {};\n paramNames.forEach((name, index) => {\n params[name] = match[index + 1] ?? '';\n });\n\n return params;\n}\n","import express, { type Express, type RequestHandler } from 'express';\nimport { createMcpMiddleware, type McpMiddlewareOptions } from './middleware.js';\nimport { extractMetadata } from '@mcp-weave/nestjs';\n\n/**\n * Options for MCP Express server\n */\nexport interface McpExpressOptions extends McpMiddlewareOptions {\n /**\n * Port to listen on (default: 3000)\n */\n port?: number;\n\n /**\n * Host to bind to (default: '0.0.0.0')\n */\n host?: string;\n\n /**\n * Custom Express app (if you want to add other middleware)\n */\n app?: Express;\n}\n\n/**\n * Standalone Express server for MCP\n *\n * @example\n * ```typescript\n * import { McpExpressServer, McpServer, McpTool } from '@mcp-weave/express';\n *\n * @McpServer({ name: 'my-server', version: '1.0.0' })\n * class MyServer {\n * @McpTool({ name: 'hello', description: 'Say hello' })\n * hello(input: { name: string }) {\n * return `Hello, ${input.name}!`;\n * }\n * }\n *\n * const server = new McpExpressServer(MyServer);\n * await server.start();\n * // Server running at http://localhost:3000/mcp\n * ```\n */\nexport class McpExpressServer {\n private app: Express;\n private target: Function;\n private options: McpExpressOptions;\n private httpServer?: ReturnType<Express['listen']>;\n\n constructor(target: Function, options: McpExpressOptions = {}) {\n this.target = target;\n this.options = options;\n this.app = options.app ?? express();\n\n // Setup middleware\n this.app.use(express.json() as RequestHandler);\n this.app.use(\n options.basePath ?? '/mcp',\n createMcpMiddleware(target, options) as RequestHandler\n );\n }\n\n /**\n * Start the Express server\n */\n async start(): Promise<void> {\n const port = this.options.port ?? 3000;\n const host = this.options.host ?? '0.0.0.0';\n const basePath = this.options.basePath ?? '/mcp';\n\n const metadata = extractMetadata(this.target);\n\n return new Promise(resolve => {\n this.httpServer = this.app.listen(port, host, () => {\n console.log(`🚀 MCP Express server '${metadata.server?.name}' started`);\n console.log(\n ` Base URL: http://${host === '0.0.0.0' ? 'localhost' : host}:${port}${basePath}`\n );\n console.log(\n ` Health: http://${host === '0.0.0.0' ? 'localhost' : host}:${port}${basePath}/health`\n );\n console.log(` Tools: ${metadata.tools.length}`);\n console.log(` Resources: ${metadata.resources.length}`);\n console.log(` Prompts: ${metadata.prompts.length}`);\n resolve();\n });\n });\n }\n\n /**\n * Stop the server\n */\n async stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.httpServer) {\n this.httpServer.close(err => {\n if (err) reject(err);\n else resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n /**\n * Get the Express app instance\n */\n getApp(): Express {\n return this.app;\n }\n}\n","import { Router, type RequestHandler } from 'express';\nimport { createMcpMiddleware, type McpMiddlewareOptions } from './middleware.js';\n\n/**\n * Create an Express Router for MCP endpoints\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { createMcpRouter, McpServer, McpTool } from '@mcp-weave/express';\n *\n * @McpServer({ name: 'my-server', version: '1.0.0' })\n * class MyServer {\n * @McpTool({ name: 'hello', description: 'Say hello' })\n * hello(input: { name: string }) {\n * return `Hello, ${input.name}!`;\n * }\n * }\n *\n * const app = express();\n * app.use(express.json());\n * app.use('/api/mcp', createMcpRouter(MyServer));\n * app.listen(3000);\n * ```\n */\nexport function createMcpRouter(target: Function, options: McpMiddlewareOptions = {}): Router {\n const router = Router();\n router.use(createMcpMiddleware(target, options) as RequestHandler);\n return router;\n}\n"],"mappings":"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","names":["import_nestjs","express","import_express","import_nestjs"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,274 @@
1
+ // src/middleware.ts
2
+ import { extractMetadata } from "@mcp-weave/nestjs";
3
+ function createMcpMiddleware(target, options = {}) {
4
+ const { cors = true, corsOrigin = "*" } = options;
5
+ const state = {
6
+ metadata: extractMetadata(target),
7
+ target
8
+ };
9
+ return async (req, res, next) => {
10
+ if (cors) {
11
+ res.setHeader("Access-Control-Allow-Origin", corsOrigin);
12
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
13
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
14
+ if (req.method === "OPTIONS") {
15
+ res.status(200).end();
16
+ return;
17
+ }
18
+ }
19
+ const path = req.path;
20
+ try {
21
+ if (path === "/health" || path === "/") {
22
+ res.json({
23
+ status: "ok",
24
+ server: state.metadata.server?.name,
25
+ version: state.metadata.server?.version,
26
+ capabilities: {
27
+ tools: state.metadata.tools.length,
28
+ resources: state.metadata.resources.length,
29
+ prompts: state.metadata.prompts.length
30
+ }
31
+ });
32
+ return;
33
+ }
34
+ if (path === "/tools" && req.method === "GET") {
35
+ res.json({
36
+ tools: state.metadata.tools.map((t) => ({
37
+ name: t.name,
38
+ description: t.description,
39
+ inputSchema: t.inputSchema
40
+ }))
41
+ });
42
+ return;
43
+ }
44
+ if (path === "/tools/call" && req.method === "POST") {
45
+ const { name, arguments: args } = req.body;
46
+ if (!name) {
47
+ res.status(400).json({ error: "Tool name is required" });
48
+ return;
49
+ }
50
+ const tool = state.metadata.tools.find((t) => t.name === name);
51
+ if (!tool) {
52
+ res.status(404).json({ error: `Tool not found: ${name}` });
53
+ return;
54
+ }
55
+ const instance = new state.target();
56
+ const method = Reflect.get(instance, tool.propertyKey);
57
+ if (typeof method !== "function") {
58
+ res.status(500).json({ error: `Method ${String(tool.propertyKey)} not found` });
59
+ return;
60
+ }
61
+ const result = await method.call(instance, args ?? {});
62
+ res.json({
63
+ content: [
64
+ {
65
+ type: "text",
66
+ text: typeof result === "string" ? result : JSON.stringify(result)
67
+ }
68
+ ]
69
+ });
70
+ return;
71
+ }
72
+ if (path === "/resources" && req.method === "GET") {
73
+ res.json({
74
+ resources: state.metadata.resources.map((r) => ({
75
+ uri: r.uri,
76
+ name: r.name,
77
+ description: r.description,
78
+ mimeType: r.mimeType
79
+ }))
80
+ });
81
+ return;
82
+ }
83
+ if (path === "/resources/read" && req.method === "POST") {
84
+ const { uri } = req.body;
85
+ if (!uri) {
86
+ res.status(400).json({ error: "Resource URI is required" });
87
+ return;
88
+ }
89
+ const instance = new state.target();
90
+ for (const resource of state.metadata.resources) {
91
+ const uriParams = extractUriParams(resource.uri, uri);
92
+ if (uriParams) {
93
+ const method = Reflect.get(instance, resource.propertyKey);
94
+ if (typeof method !== "function") {
95
+ res.status(500).json({ error: `Method ${String(resource.propertyKey)} not found` });
96
+ return;
97
+ }
98
+ const params = state.metadata.params.filter(
99
+ (p) => p.propertyKey === resource.propertyKey && p.type === "param"
100
+ );
101
+ const args = [];
102
+ for (const param of params) {
103
+ if (param.name) {
104
+ args[param.parameterIndex] = uriParams[param.name];
105
+ }
106
+ }
107
+ const result = await method.apply(instance, args);
108
+ res.json(result);
109
+ return;
110
+ }
111
+ }
112
+ res.status(404).json({ error: `Resource not found: ${uri}` });
113
+ return;
114
+ }
115
+ if (path === "/prompts" && req.method === "GET") {
116
+ res.json({
117
+ prompts: state.metadata.prompts.map((p) => ({
118
+ name: p.name,
119
+ description: p.description,
120
+ arguments: p.arguments
121
+ }))
122
+ });
123
+ return;
124
+ }
125
+ if (path === "/prompts/get" && req.method === "POST") {
126
+ const { name, arguments: args } = req.body;
127
+ if (!name) {
128
+ res.status(400).json({ error: "Prompt name is required" });
129
+ return;
130
+ }
131
+ const prompt = state.metadata.prompts.find((p) => p.name === name);
132
+ if (!prompt) {
133
+ res.status(404).json({ error: `Prompt not found: ${name}` });
134
+ return;
135
+ }
136
+ const instance = new state.target();
137
+ const method = Reflect.get(instance, prompt.propertyKey);
138
+ if (typeof method !== "function") {
139
+ res.status(500).json({ error: `Method ${String(prompt.propertyKey)} not found` });
140
+ return;
141
+ }
142
+ const params = state.metadata.params.filter(
143
+ (p) => p.propertyKey === prompt.propertyKey && p.type === "promptArg"
144
+ );
145
+ const methodArgs = [];
146
+ for (const param of params) {
147
+ if (param.name && args) {
148
+ methodArgs[param.parameterIndex] = args[param.name];
149
+ }
150
+ }
151
+ const result = await method.apply(instance, methodArgs);
152
+ res.json(result);
153
+ return;
154
+ }
155
+ next();
156
+ } catch (error) {
157
+ res.status(500).json({
158
+ error: error instanceof Error ? error.message : "Internal server error"
159
+ });
160
+ }
161
+ };
162
+ }
163
+ function extractUriParams(template, uri) {
164
+ const paramNames = [];
165
+ const regexStr = template.replace(/\{(\w+)\}/g, (_, name) => {
166
+ paramNames.push(name);
167
+ return "([^/]+)";
168
+ });
169
+ const regex = new RegExp(`^${regexStr}$`);
170
+ const match = uri.match(regex);
171
+ if (!match) return null;
172
+ const params = {};
173
+ paramNames.forEach((name, index) => {
174
+ params[name] = match[index + 1] ?? "";
175
+ });
176
+ return params;
177
+ }
178
+
179
+ // src/server.ts
180
+ import express from "express";
181
+ import { extractMetadata as extractMetadata2 } from "@mcp-weave/nestjs";
182
+ var McpExpressServer = class {
183
+ app;
184
+ target;
185
+ options;
186
+ httpServer;
187
+ constructor(target, options = {}) {
188
+ this.target = target;
189
+ this.options = options;
190
+ this.app = options.app ?? express();
191
+ this.app.use(express.json());
192
+ this.app.use(
193
+ options.basePath ?? "/mcp",
194
+ createMcpMiddleware(target, options)
195
+ );
196
+ }
197
+ /**
198
+ * Start the Express server
199
+ */
200
+ async start() {
201
+ const port = this.options.port ?? 3e3;
202
+ const host = this.options.host ?? "0.0.0.0";
203
+ const basePath = this.options.basePath ?? "/mcp";
204
+ const metadata = extractMetadata2(this.target);
205
+ return new Promise((resolve) => {
206
+ this.httpServer = this.app.listen(port, host, () => {
207
+ console.log(`\u{1F680} MCP Express server '${metadata.server?.name}' started`);
208
+ console.log(
209
+ ` Base URL: http://${host === "0.0.0.0" ? "localhost" : host}:${port}${basePath}`
210
+ );
211
+ console.log(
212
+ ` Health: http://${host === "0.0.0.0" ? "localhost" : host}:${port}${basePath}/health`
213
+ );
214
+ console.log(` Tools: ${metadata.tools.length}`);
215
+ console.log(` Resources: ${metadata.resources.length}`);
216
+ console.log(` Prompts: ${metadata.prompts.length}`);
217
+ resolve();
218
+ });
219
+ });
220
+ }
221
+ /**
222
+ * Stop the server
223
+ */
224
+ async stop() {
225
+ return new Promise((resolve, reject) => {
226
+ if (this.httpServer) {
227
+ this.httpServer.close((err) => {
228
+ if (err) reject(err);
229
+ else resolve();
230
+ });
231
+ } else {
232
+ resolve();
233
+ }
234
+ });
235
+ }
236
+ /**
237
+ * Get the Express app instance
238
+ */
239
+ getApp() {
240
+ return this.app;
241
+ }
242
+ };
243
+
244
+ // src/router.ts
245
+ import { Router } from "express";
246
+ function createMcpRouter(target, options = {}) {
247
+ const router = Router();
248
+ router.use(createMcpMiddleware(target, options));
249
+ return router;
250
+ }
251
+
252
+ // src/index.ts
253
+ import {
254
+ McpServer,
255
+ McpTool,
256
+ McpResource,
257
+ McpPrompt,
258
+ McpInput,
259
+ McpParam,
260
+ McpPromptArg
261
+ } from "@mcp-weave/nestjs";
262
+ export {
263
+ McpExpressServer,
264
+ McpInput,
265
+ McpParam,
266
+ McpPrompt,
267
+ McpPromptArg,
268
+ McpResource,
269
+ McpServer,
270
+ McpTool,
271
+ createMcpMiddleware,
272
+ createMcpRouter
273
+ };
274
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware.ts","../src/server.ts","../src/router.ts","../src/index.ts"],"sourcesContent":["import type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { extractMetadata } from '@mcp-weave/nestjs';\n\n/**\n * Options for MCP Express middleware\n */\nexport interface McpMiddlewareOptions {\n /**\n * Base path for MCP endpoints (default: '/mcp')\n */\n basePath?: string;\n\n /**\n * Enable CORS headers (default: true)\n */\n cors?: boolean;\n\n /**\n * Custom CORS origin (default: '*')\n */\n corsOrigin?: string;\n}\n\n/**\n * Internal state for MCP middleware\n */\ninterface McpMiddlewareState {\n metadata: ReturnType<typeof extractMetadata>;\n target: Function;\n}\n\n/**\n * Create Express middleware for an MCP server\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { createMcpMiddleware, McpServer, McpTool } from '@mcp-weave/express';\n *\n * @McpServer({ name: 'my-server', version: '1.0.0' })\n * class MyServer {\n * @McpTool({ name: 'hello', description: 'Say hello' })\n * hello(input: { name: string }) {\n * return `Hello, ${input.name}!`;\n * }\n * }\n *\n * const app = express();\n * app.use('/mcp', createMcpMiddleware(MyServer));\n * app.listen(3000);\n * ```\n */\nexport function createMcpMiddleware(\n target: Function,\n options: McpMiddlewareOptions = {}\n): RequestHandler {\n const { cors = true, corsOrigin = '*' } = options;\n\n // Initialize metadata\n const state: McpMiddlewareState = {\n metadata: extractMetadata(target),\n target,\n };\n\n return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n // Handle CORS\n if (cors) {\n res.setHeader('Access-Control-Allow-Origin', corsOrigin);\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.status(200).end();\n return;\n }\n }\n\n const path = req.path;\n\n try {\n // Health check\n if (path === '/health' || path === '/') {\n res.json({\n status: 'ok',\n server: state.metadata.server?.name,\n version: state.metadata.server?.version,\n capabilities: {\n tools: state.metadata.tools.length,\n resources: state.metadata.resources.length,\n prompts: state.metadata.prompts.length,\n },\n });\n return;\n }\n\n // List tools\n if (path === '/tools' && req.method === 'GET') {\n res.json({\n tools: state.metadata.tools.map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n });\n return;\n }\n\n // Call tool\n if (path === '/tools/call' && req.method === 'POST') {\n const { name, arguments: args } = req.body as {\n name: string;\n arguments?: Record<string, unknown>;\n };\n\n if (!name) {\n res.status(400).json({ error: 'Tool name is required' });\n return;\n }\n\n const tool = state.metadata.tools.find(t => t.name === name);\n if (!tool) {\n res.status(404).json({ error: `Tool not found: ${name}` });\n return;\n }\n\n // Execute tool via internal server\n const instance = new (state.target as new () => unknown)();\n const method = Reflect.get(instance as object, tool.propertyKey);\n\n if (typeof method !== 'function') {\n res.status(500).json({ error: `Method ${String(tool.propertyKey)} not found` });\n return;\n }\n\n const result = await method.call(instance, args ?? {});\n res.json({\n content: [\n {\n type: 'text',\n text: typeof result === 'string' ? result : JSON.stringify(result),\n },\n ],\n });\n return;\n }\n\n // List resources\n if (path === '/resources' && req.method === 'GET') {\n res.json({\n resources: state.metadata.resources.map(r => ({\n uri: r.uri,\n name: r.name,\n description: r.description,\n mimeType: r.mimeType,\n })),\n });\n return;\n }\n\n // Read resource\n if (path === '/resources/read' && req.method === 'POST') {\n const { uri } = req.body as { uri: string };\n\n if (!uri) {\n res.status(400).json({ error: 'Resource URI is required' });\n return;\n }\n\n const instance = new (state.target as new () => unknown)();\n\n for (const resource of state.metadata.resources) {\n const uriParams = extractUriParams(resource.uri, uri);\n if (uriParams) {\n const method = Reflect.get(instance as object, resource.propertyKey);\n if (typeof method !== 'function') {\n res.status(500).json({ error: `Method ${String(resource.propertyKey)} not found` });\n return;\n }\n\n // Resolve params\n const params = state.metadata.params.filter(\n p => p.propertyKey === resource.propertyKey && p.type === 'param'\n );\n const args: unknown[] = [];\n for (const param of params) {\n if (param.name) {\n args[param.parameterIndex] = uriParams[param.name];\n }\n }\n\n const result = await method.apply(instance, args);\n res.json(result);\n return;\n }\n }\n\n res.status(404).json({ error: `Resource not found: ${uri}` });\n return;\n }\n\n // List prompts\n if (path === '/prompts' && req.method === 'GET') {\n res.json({\n prompts: state.metadata.prompts.map(p => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments,\n })),\n });\n return;\n }\n\n // Get prompt\n if (path === '/prompts/get' && req.method === 'POST') {\n const { name, arguments: args } = req.body as {\n name: string;\n arguments?: Record<string, unknown>;\n };\n\n if (!name) {\n res.status(400).json({ error: 'Prompt name is required' });\n return;\n }\n\n const prompt = state.metadata.prompts.find(p => p.name === name);\n if (!prompt) {\n res.status(404).json({ error: `Prompt not found: ${name}` });\n return;\n }\n\n const instance = new (state.target as new () => unknown)();\n const method = Reflect.get(instance as object, prompt.propertyKey);\n\n if (typeof method !== 'function') {\n res.status(500).json({ error: `Method ${String(prompt.propertyKey)} not found` });\n return;\n }\n\n // Resolve prompt args\n const params = state.metadata.params.filter(\n p => p.propertyKey === prompt.propertyKey && p.type === 'promptArg'\n );\n const methodArgs: unknown[] = [];\n for (const param of params) {\n if (param.name && args) {\n methodArgs[param.parameterIndex] = args[param.name];\n }\n }\n\n const result = await method.apply(instance, methodArgs);\n res.json(result);\n return;\n }\n\n // Not found\n next();\n } catch (error) {\n res.status(500).json({\n error: error instanceof Error ? error.message : 'Internal server error',\n });\n }\n };\n}\n\n/**\n * Extract parameters from a URI template\n */\nfunction extractUriParams(template: string, uri: string): Record<string, string> | null {\n const paramNames: string[] = [];\n const regexStr = template.replace(/\\{(\\w+)\\}/g, (_, name) => {\n paramNames.push(name);\n return '([^/]+)';\n });\n\n const regex = new RegExp(`^${regexStr}$`);\n const match = uri.match(regex);\n\n if (!match) return null;\n\n const params: Record<string, string> = {};\n paramNames.forEach((name, index) => {\n params[name] = match[index + 1] ?? '';\n });\n\n return params;\n}\n","import express, { type Express, type RequestHandler } from 'express';\nimport { createMcpMiddleware, type McpMiddlewareOptions } from './middleware.js';\nimport { extractMetadata } from '@mcp-weave/nestjs';\n\n/**\n * Options for MCP Express server\n */\nexport interface McpExpressOptions extends McpMiddlewareOptions {\n /**\n * Port to listen on (default: 3000)\n */\n port?: number;\n\n /**\n * Host to bind to (default: '0.0.0.0')\n */\n host?: string;\n\n /**\n * Custom Express app (if you want to add other middleware)\n */\n app?: Express;\n}\n\n/**\n * Standalone Express server for MCP\n *\n * @example\n * ```typescript\n * import { McpExpressServer, McpServer, McpTool } from '@mcp-weave/express';\n *\n * @McpServer({ name: 'my-server', version: '1.0.0' })\n * class MyServer {\n * @McpTool({ name: 'hello', description: 'Say hello' })\n * hello(input: { name: string }) {\n * return `Hello, ${input.name}!`;\n * }\n * }\n *\n * const server = new McpExpressServer(MyServer);\n * await server.start();\n * // Server running at http://localhost:3000/mcp\n * ```\n */\nexport class McpExpressServer {\n private app: Express;\n private target: Function;\n private options: McpExpressOptions;\n private httpServer?: ReturnType<Express['listen']>;\n\n constructor(target: Function, options: McpExpressOptions = {}) {\n this.target = target;\n this.options = options;\n this.app = options.app ?? express();\n\n // Setup middleware\n this.app.use(express.json() as RequestHandler);\n this.app.use(\n options.basePath ?? '/mcp',\n createMcpMiddleware(target, options) as RequestHandler\n );\n }\n\n /**\n * Start the Express server\n */\n async start(): Promise<void> {\n const port = this.options.port ?? 3000;\n const host = this.options.host ?? '0.0.0.0';\n const basePath = this.options.basePath ?? '/mcp';\n\n const metadata = extractMetadata(this.target);\n\n return new Promise(resolve => {\n this.httpServer = this.app.listen(port, host, () => {\n console.log(`🚀 MCP Express server '${metadata.server?.name}' started`);\n console.log(\n ` Base URL: http://${host === '0.0.0.0' ? 'localhost' : host}:${port}${basePath}`\n );\n console.log(\n ` Health: http://${host === '0.0.0.0' ? 'localhost' : host}:${port}${basePath}/health`\n );\n console.log(` Tools: ${metadata.tools.length}`);\n console.log(` Resources: ${metadata.resources.length}`);\n console.log(` Prompts: ${metadata.prompts.length}`);\n resolve();\n });\n });\n }\n\n /**\n * Stop the server\n */\n async stop(): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.httpServer) {\n this.httpServer.close(err => {\n if (err) reject(err);\n else resolve();\n });\n } else {\n resolve();\n }\n });\n }\n\n /**\n * Get the Express app instance\n */\n getApp(): Express {\n return this.app;\n }\n}\n","import { Router, type RequestHandler } from 'express';\nimport { createMcpMiddleware, type McpMiddlewareOptions } from './middleware.js';\n\n/**\n * Create an Express Router for MCP endpoints\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { createMcpRouter, McpServer, McpTool } from '@mcp-weave/express';\n *\n * @McpServer({ name: 'my-server', version: '1.0.0' })\n * class MyServer {\n * @McpTool({ name: 'hello', description: 'Say hello' })\n * hello(input: { name: string }) {\n * return `Hello, ${input.name}!`;\n * }\n * }\n *\n * const app = express();\n * app.use(express.json());\n * app.use('/api/mcp', createMcpRouter(MyServer));\n * app.listen(3000);\n * ```\n */\nexport function createMcpRouter(target: Function, options: McpMiddlewareOptions = {}): Router {\n const router = Router();\n router.use(createMcpMiddleware(target, options) as RequestHandler);\n return router;\n}\n","/**\n * @mcp-weave/express\n *\n * Express middleware for MCP (Model Context Protocol) servers.\n * Provides easy integration of MCP servers with Express applications.\n */\n\nexport { createMcpMiddleware, type McpMiddlewareOptions } from './middleware.js';\nexport { McpExpressServer, type McpExpressOptions } from './server.js';\nexport { createMcpRouter } from './router.js';\n\n// Re-export common decorators from nestjs for convenience\nexport {\n McpServer,\n McpTool,\n McpResource,\n McpPrompt,\n McpInput,\n McpParam,\n McpPromptArg,\n} from '@mcp-weave/nestjs';\n"],"mappings":"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","names":["extractMetadata"]}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@mcp-weave/express",
3
+ "version": "0.2.0",
4
+ "description": "Express middleware for MCP servers",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "@modelcontextprotocol/sdk": "^1.0.0",
20
+ "@mcp-weave/nestjs": "0.2.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/express": "^4.17.21",
24
+ "@types/node": "^20.17.12",
25
+ "express": "^4.21.2",
26
+ "reflect-metadata": "^0.2.2",
27
+ "tsup": "^8.3.5",
28
+ "typescript": "^5.7.3",
29
+ "vitest": "^2.1.8"
30
+ },
31
+ "peerDependencies": {
32
+ "express": "^4.18.0 || ^5.0.0"
33
+ },
34
+ "keywords": [
35
+ "mcp",
36
+ "model-context-protocol",
37
+ "express",
38
+ "middleware",
39
+ "server"
40
+ ],
41
+ "license": "MIT",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/mcp-weave/mcp-weave.git",
45
+ "directory": "packages/express"
46
+ },
47
+ "author": "MCP-Weave Contributors",
48
+ "scripts": {
49
+ "build": "tsup",
50
+ "dev": "tsup --watch",
51
+ "lint": "eslint src --ext .ts",
52
+ "test": "vitest run",
53
+ "test:watch": "vitest",
54
+ "typecheck": "tsc --noEmit"
55
+ }
56
+ }