@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 +21 -0
- package/README.md +162 -0
- package/dist/index.d.mts +125 -0
- package/dist/index.d.ts +125 -0
- package/dist/index.js +312 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +274 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +56 -0
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
|
package/dist/index.d.mts
ADDED
|
@@ -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.d.ts
ADDED
|
@@ -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
|
+
}
|