@ttoss/http-server-mcp 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/dist/esm/index.js +52 -0
- package/dist/index.d.ts +61 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, Terezinha Tech Operations (ttoss)
|
|
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,214 @@
|
|
|
1
|
+
# @ttoss/http-server-mcp
|
|
2
|
+
|
|
3
|
+
[Model Context Protocol (MCP)](https://modelcontextprotocol.io) server integration for [@ttoss/http-server](https://ttoss.dev/docs/modules/packages/http-server).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @ttoss/http-server-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { App, bodyParser, cors } from '@ttoss/http-server';
|
|
15
|
+
import {
|
|
16
|
+
createMcpRouter,
|
|
17
|
+
Server as McpServer,
|
|
18
|
+
z,
|
|
19
|
+
} from '@ttoss/http-server-mcp';
|
|
20
|
+
|
|
21
|
+
// Create MCP server
|
|
22
|
+
const mcpServer = new McpServer({
|
|
23
|
+
name: 'my-mcp-server',
|
|
24
|
+
version: '1.0.0',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Register tools
|
|
28
|
+
mcpServer.registerTool(
|
|
29
|
+
'get-weather',
|
|
30
|
+
{
|
|
31
|
+
description: 'Get weather information for a location',
|
|
32
|
+
inputSchema: {
|
|
33
|
+
location: z.string().describe('City name'),
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
async ({ location }) => ({
|
|
37
|
+
content: [
|
|
38
|
+
{
|
|
39
|
+
type: 'text',
|
|
40
|
+
text: `Weather in ${location}: Sunny, 72°F`,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// Create HTTP server
|
|
47
|
+
const app = new App();
|
|
48
|
+
app.use(cors());
|
|
49
|
+
app.use(bodyParser());
|
|
50
|
+
|
|
51
|
+
// Mount MCP router
|
|
52
|
+
const mcpRouter = createMcpRouter(mcpServer);
|
|
53
|
+
app.use(mcpRouter.routes());
|
|
54
|
+
|
|
55
|
+
app.listen(3000, () => {
|
|
56
|
+
console.log('MCP server running on http://localhost:3000/mcp');
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## API Reference
|
|
61
|
+
|
|
62
|
+
### `createMcpRouter(server, options?)`
|
|
63
|
+
|
|
64
|
+
Creates a Koa router configured to handle MCP protocol requests.
|
|
65
|
+
|
|
66
|
+
**Parameters:**
|
|
67
|
+
|
|
68
|
+
- `server` (`McpServer`) - MCP server instance with registered tools and resources
|
|
69
|
+
- `options` (`McpRouterOptions`) - Optional configuration
|
|
70
|
+
- `path` (`string`) - HTTP path for MCP endpoint (default: `'/mcp'`)
|
|
71
|
+
- `sessionIdGenerator` (`() => string`) - Session ID generator for stateful servers (default: `undefined` for stateless)
|
|
72
|
+
|
|
73
|
+
**Returns:** `Router` - Koa router instance
|
|
74
|
+
|
|
75
|
+
## Examples
|
|
76
|
+
|
|
77
|
+
### Basic Tool
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { Server as McpServer, z } from '@ttoss/http-server-mcp';
|
|
81
|
+
|
|
82
|
+
const server = new McpServer({
|
|
83
|
+
name: 'calculator',
|
|
84
|
+
version: '1.0.0',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
server.registerTool(
|
|
88
|
+
'add',
|
|
89
|
+
{
|
|
90
|
+
description: 'Add two numbers',
|
|
91
|
+
inputSchema: {
|
|
92
|
+
a: z.number().describe('First number'),
|
|
93
|
+
b: z.number().describe('Second number'),
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
async ({ a, b }) => ({
|
|
97
|
+
content: [
|
|
98
|
+
{
|
|
99
|
+
type: 'text',
|
|
100
|
+
text: `${a} + ${b} = ${a + b}`,
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Multiple Tools
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
server.registerTool(
|
|
111
|
+
'multiply',
|
|
112
|
+
{
|
|
113
|
+
description: 'Multiply two numbers',
|
|
114
|
+
inputSchema: {
|
|
115
|
+
a: z.number(),
|
|
116
|
+
b: z.number(),
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
async ({ a, b }) => ({
|
|
120
|
+
content: [{ type: 'text', text: String(a * b) }],
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
server.registerTool(
|
|
125
|
+
'divide',
|
|
126
|
+
{
|
|
127
|
+
description: 'Divide two numbers',
|
|
128
|
+
inputSchema: {
|
|
129
|
+
a: z.number(),
|
|
130
|
+
b: z.number(),
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
async ({ a, b }) => {
|
|
134
|
+
if (b === 0) {
|
|
135
|
+
throw new Error('Division by zero');
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
content: [{ type: 'text', text: String(a / b) }],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Custom Path
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const router = createMcpRouter(server, {
|
|
148
|
+
path: '/api/mcp',
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Resources
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
server.resource(
|
|
156
|
+
'config://app',
|
|
157
|
+
'Application configuration',
|
|
158
|
+
'application/json',
|
|
159
|
+
async () => ({
|
|
160
|
+
contents: [
|
|
161
|
+
{
|
|
162
|
+
uri: 'config://app',
|
|
163
|
+
mimeType: 'application/json',
|
|
164
|
+
text: JSON.stringify({ version: '1.0.0', env: 'production' }),
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### With CORS and Multiple Endpoints
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { App, bodyParser, cors, Router } from '@ttoss/http-server';
|
|
175
|
+
import { createMcpRouter } from '@ttoss/http-server-mcp';
|
|
176
|
+
|
|
177
|
+
const app = new App();
|
|
178
|
+
app.use(cors());
|
|
179
|
+
app.use(bodyParser());
|
|
180
|
+
|
|
181
|
+
// Health check endpoint
|
|
182
|
+
const healthRouter = new Router();
|
|
183
|
+
healthRouter.get('/health', (ctx) => {
|
|
184
|
+
ctx.body = { status: 'ok' };
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// MCP endpoint
|
|
188
|
+
const mcpRouter = createMcpRouter(mcpServer);
|
|
189
|
+
|
|
190
|
+
app.use(healthRouter.routes());
|
|
191
|
+
app.use(mcpRouter.routes());
|
|
192
|
+
|
|
193
|
+
app.listen(3000);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Protocol Details
|
|
197
|
+
|
|
198
|
+
This package implements the [Model Context Protocol](https://spec.modelcontextprotocol.io/) over HTTP using JSON responses (no SSE streaming). It uses the `StreamableHTTPServerTransport` from the MCP SDK with `enableJsonResponse: true` and adapts Koa's context-based middleware to work with the MCP SDK's Node.js request/response expectations.
|
|
199
|
+
|
|
200
|
+
**Supported HTTP methods:**
|
|
201
|
+
|
|
202
|
+
- `POST /mcp` - Send JSON-RPC requests/notifications
|
|
203
|
+
- `DELETE /mcp` - Terminate session (optional)
|
|
204
|
+
|
|
205
|
+
## Related Packages
|
|
206
|
+
|
|
207
|
+
- [@ttoss/http-server](https://ttoss.dev/docs/modules/packages/http-server) - HTTP server foundation
|
|
208
|
+
- [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/sdk) - MCP SDK
|
|
209
|
+
|
|
210
|
+
## Resources
|
|
211
|
+
|
|
212
|
+
- [MCP Documentation](https://modelcontextprotocol.io)
|
|
213
|
+
- [MCP Specification](https://spec.modelcontextprotocol.io/)
|
|
214
|
+
- [MCP SDK TypeScript](https://github.com/modelcontextprotocol/typescript-sdk)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __name = (target, value) => __defProp(target, "name", {
|
|
4
|
+
value,
|
|
5
|
+
configurable: true
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
10
|
+
import { Router } from "@ttoss/http-server";
|
|
11
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
var createMcpRouter = /* @__PURE__ */__name((server, options = {}) => {
|
|
14
|
+
const {
|
|
15
|
+
path = "/mcp",
|
|
16
|
+
sessionIdGenerator
|
|
17
|
+
} = options;
|
|
18
|
+
const transport = new StreamableHTTPServerTransport({
|
|
19
|
+
sessionIdGenerator,
|
|
20
|
+
enableJsonResponse: true
|
|
21
|
+
});
|
|
22
|
+
server.connect(transport);
|
|
23
|
+
const router = new Router();
|
|
24
|
+
router.post(path, async ctx => {
|
|
25
|
+
try {
|
|
26
|
+
await transport.handleRequest(ctx.req, ctx.res, ctx.request.body);
|
|
27
|
+
ctx.respond = false;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (!ctx.res.headersSent) {
|
|
30
|
+
ctx.status = 500;
|
|
31
|
+
ctx.body = {
|
|
32
|
+
error: error instanceof Error ? error.message : "Internal server error"
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
router.delete(path, async ctx => {
|
|
38
|
+
try {
|
|
39
|
+
await transport.handleRequest(ctx.req, ctx.res, void 0);
|
|
40
|
+
ctx.respond = false;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (!ctx.res.headersSent) {
|
|
43
|
+
ctx.status = 500;
|
|
44
|
+
ctx.body = {
|
|
45
|
+
error: error instanceof Error ? error.message : "Internal server error"
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return router;
|
|
51
|
+
}, "createMcpRouter");
|
|
52
|
+
export { McpServer as Server, createMcpRouter, z };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as _koa_router from '@koa/router';
|
|
2
|
+
import * as koa from 'koa';
|
|
3
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
+
export { McpServer, McpServer as Server } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
export { z } from 'zod';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Options for configuring the MCP router
|
|
9
|
+
*/
|
|
10
|
+
interface McpRouterOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The HTTP path where the MCP server will be mounted
|
|
13
|
+
* @default '/mcp'
|
|
14
|
+
*/
|
|
15
|
+
path?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Optional session ID generator for stateful MCP servers
|
|
18
|
+
* Set to undefined for stateless servers
|
|
19
|
+
*/
|
|
20
|
+
sessionIdGenerator?: () => string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a Koa router configured to handle MCP protocol requests
|
|
24
|
+
*
|
|
25
|
+
* @param server - The MCP server instance with registered tools and resources
|
|
26
|
+
* @param options - Configuration options for the router
|
|
27
|
+
* @returns A Koa Router instance configured for MCP
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { App, bodyParser } from '@ttoss/http-server';
|
|
32
|
+
* import { createMcpRouter, Server as McpServer, z } from '@ttoss/http-server-mcp';
|
|
33
|
+
*
|
|
34
|
+
* const mcpServer = new McpServer({
|
|
35
|
+
* name: 'my-server',
|
|
36
|
+
* version: '1.0.0',
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* mcpServer.registerTool(
|
|
40
|
+
* 'hello',
|
|
41
|
+
* {
|
|
42
|
+
* description: 'Say hello',
|
|
43
|
+
* inputSchema: { name: z.string() },
|
|
44
|
+
* },
|
|
45
|
+
* async ({ name }) => ({
|
|
46
|
+
* content: [{ type: 'text', text: `Hello, ${name}!` }],
|
|
47
|
+
* })
|
|
48
|
+
* );
|
|
49
|
+
*
|
|
50
|
+
* const app = new App();
|
|
51
|
+
* app.use(bodyParser());
|
|
52
|
+
*
|
|
53
|
+
* const mcpRouter = createMcpRouter(mcpServer);
|
|
54
|
+
* app.use(mcpRouter.routes());
|
|
55
|
+
*
|
|
56
|
+
* app.listen(3000);
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare const createMcpRouter: (server: McpServer, options?: McpRouterOptions) => _koa_router.RouterInstance<koa.DefaultState, koa.DefaultContext>;
|
|
60
|
+
|
|
61
|
+
export { type McpRouterOptions, createMcpRouter };
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ttoss/http-server-mcp",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Model Context Protocol (MCP) server integration for @ttoss/http-server",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "ttoss",
|
|
7
|
+
"contributors": [
|
|
8
|
+
"Pedro Arantes <pedro@arantespp.com> (https://arantespp.com)"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/ttoss/ttoss.git",
|
|
13
|
+
"directory": "packages/http-server-mcp"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": "./dist/esm/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
28
|
+
"zod": "^3.25.76",
|
|
29
|
+
"@ttoss/http-server": "^0.3.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/koa": "^3.0.1",
|
|
33
|
+
"jest": "^30.2.0",
|
|
34
|
+
"supertest": "^7.1.4",
|
|
35
|
+
"tsup": "^8.5.1",
|
|
36
|
+
"@ttoss/config": "^1.35.12"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"ai",
|
|
40
|
+
"koa",
|
|
41
|
+
"llm",
|
|
42
|
+
"mcp",
|
|
43
|
+
"model-context-protocol",
|
|
44
|
+
"server"
|
|
45
|
+
],
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public",
|
|
48
|
+
"provenance": true
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup",
|
|
52
|
+
"test": "jest --projects tests/unit"
|
|
53
|
+
}
|
|
54
|
+
}
|