@karashiiro/my-cool-proxy 1.2.0 → 1.2.2
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/dist/e2e/fixtures/toy-servers/calculator-server.js +27 -1
- package/dist/e2e/fixtures/toy-servers/data-server.js +27 -1
- package/dist/e2e/fixtures/toy-servers/elicitation-server.js +26 -1
- package/dist/e2e/fixtures/toy-servers/index.js +0 -1
- package/dist/e2e/fixtures/toy-servers/sampling-server.js +28 -1
- package/dist/e2e/fixtures/toy-servers/stderr-server.js +18 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3627 -227
- package/dist/index.js.map +1 -1
- package/package.json +16 -12
- package/dist/container/binding-map.d.ts +0 -24
- package/dist/container/binding-map.d.ts.map +0 -1
- package/dist/container/binding-map.js +0 -2
- package/dist/container/binding-map.js.map +0 -1
- package/dist/container/decorators.d.ts +0 -5
- package/dist/container/decorators.d.ts.map +0 -1
- package/dist/container/decorators.js +0 -4
- package/dist/container/decorators.js.map +0 -1
- package/dist/container/inversify.config.d.ts +0 -6
- package/dist/container/inversify.config.d.ts.map +0 -1
- package/dist/container/inversify.config.js +0 -130
- package/dist/container/inversify.config.js.map +0 -1
- package/dist/e2e/fixtures/toy-servers/calculator-server.d.ts +0 -5
- package/dist/e2e/fixtures/toy-servers/calculator-server.d.ts.map +0 -1
- package/dist/e2e/fixtures/toy-servers/calculator-server.js.map +0 -1
- package/dist/e2e/fixtures/toy-servers/data-server.d.ts +0 -5
- package/dist/e2e/fixtures/toy-servers/data-server.d.ts.map +0 -1
- package/dist/e2e/fixtures/toy-servers/data-server.js.map +0 -1
- package/dist/e2e/fixtures/toy-servers/elicitation-server.d.ts +0 -5
- package/dist/e2e/fixtures/toy-servers/elicitation-server.d.ts.map +0 -1
- package/dist/e2e/fixtures/toy-servers/elicitation-server.js.map +0 -1
- package/dist/e2e/fixtures/toy-servers/index.d.ts +0 -6
- package/dist/e2e/fixtures/toy-servers/index.d.ts.map +0 -1
- package/dist/e2e/fixtures/toy-servers/index.js.map +0 -1
- package/dist/e2e/fixtures/toy-servers/sampling-server.d.ts +0 -5
- package/dist/e2e/fixtures/toy-servers/sampling-server.d.ts.map +0 -1
- package/dist/e2e/fixtures/toy-servers/sampling-server.js.map +0 -1
- package/dist/e2e/fixtures/toy-servers/stderr-server.d.ts +0 -2
- package/dist/e2e/fixtures/toy-servers/stderr-server.d.ts.map +0 -1
- package/dist/e2e/fixtures/toy-servers/stderr-server.js.map +0 -1
- package/dist/e2e/helpers/client-helpers.d.ts +0 -18
- package/dist/e2e/helpers/client-helpers.d.ts.map +0 -1
- package/dist/e2e/helpers/client-helpers.js +0 -119
- package/dist/e2e/helpers/client-helpers.js.map +0 -1
- package/dist/e2e/helpers/http-server-manager.d.ts +0 -10
- package/dist/e2e/helpers/http-server-manager.d.ts.map +0 -1
- package/dist/e2e/helpers/http-server-manager.js +0 -146
- package/dist/e2e/helpers/http-server-manager.js.map +0 -1
- package/dist/e2e/helpers/port-manager.d.ts +0 -2
- package/dist/e2e/helpers/port-manager.d.ts.map +0 -1
- package/dist/e2e/helpers/port-manager.js +0 -27
- package/dist/e2e/helpers/port-manager.js.map +0 -1
- package/dist/e2e/helpers/test-assertions.d.ts +0 -18
- package/dist/e2e/helpers/test-assertions.d.ts.map +0 -1
- package/dist/e2e/helpers/test-assertions.js +0 -71
- package/dist/e2e/helpers/test-assertions.js.map +0 -1
- package/dist/e2e/helpers/test-config-generator.d.ts +0 -26
- package/dist/e2e/helpers/test-config-generator.d.ts.map +0 -1
- package/dist/e2e/helpers/test-config-generator.js +0 -58
- package/dist/e2e/helpers/test-config-generator.js.map +0 -1
- package/dist/e2e/helpers/toy-server-manager.d.ts +0 -10
- package/dist/e2e/helpers/toy-server-manager.d.ts.map +0 -1
- package/dist/e2e/helpers/toy-server-manager.js +0 -58
- package/dist/e2e/helpers/toy-server-manager.js.map +0 -1
- package/dist/handlers/shutdown-handler.d.ts +0 -8
- package/dist/handlers/shutdown-handler.d.ts.map +0 -1
- package/dist/handlers/shutdown-handler.js +0 -37
- package/dist/handlers/shutdown-handler.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/mcp/gateway-server.d.ts +0 -25
- package/dist/mcp/gateway-server.d.ts.map +0 -1
- package/dist/mcp/gateway-server.js +0 -140
- package/dist/mcp/gateway-server.js.map +0 -1
- package/dist/services/capability-store.d.ts +0 -12
- package/dist/services/capability-store.d.ts.map +0 -1
- package/dist/services/capability-store.js +0 -52
- package/dist/services/capability-store.js.map +0 -1
- package/dist/services/server-info-preloader.d.ts +0 -11
- package/dist/services/server-info-preloader.d.ts.map +0 -1
- package/dist/services/server-info-preloader.js +0 -160
- package/dist/services/server-info-preloader.js.map +0 -1
- package/dist/services/skill-discovery-service.d.ts +0 -13
- package/dist/services/skill-discovery-service.d.ts.map +0 -1
- package/dist/services/skill-discovery-service.js +0 -329
- package/dist/services/skill-discovery-service.js.map +0 -1
- package/dist/services/skill-resource-provider.d.ts +0 -13
- package/dist/services/skill-resource-provider.d.ts.map +0 -1
- package/dist/services/skill-resource-provider.js +0 -99
- package/dist/services/skill-resource-provider.js.map +0 -1
- package/dist/tools/base-tool.d.ts +0 -11
- package/dist/tools/base-tool.d.ts.map +0 -1
- package/dist/tools/base-tool.js +0 -2
- package/dist/tools/base-tool.js.map +0 -1
- package/dist/tools/execute-lua-tool.d.ts +0 -18
- package/dist/tools/execute-lua-tool.d.ts.map +0 -1
- package/dist/tools/execute-lua-tool.js +0 -124
- package/dist/tools/execute-lua-tool.js.map +0 -1
- package/dist/tools/inspect-tool-response-tool.d.ts +0 -19
- package/dist/tools/inspect-tool-response-tool.d.ts.map +0 -1
- package/dist/tools/inspect-tool-response-tool.js +0 -66
- package/dist/tools/inspect-tool-response-tool.js.map +0 -1
- package/dist/tools/invoke-gateway-skill-script-tool.d.ts +0 -20
- package/dist/tools/invoke-gateway-skill-script-tool.d.ts.map +0 -1
- package/dist/tools/invoke-gateway-skill-script-tool.js +0 -202
- package/dist/tools/invoke-gateway-skill-script-tool.js.map +0 -1
- package/dist/tools/list-resources-tool.d.ts +0 -12
- package/dist/tools/list-resources-tool.d.ts.map +0 -1
- package/dist/tools/list-resources-tool.js +0 -84
- package/dist/tools/list-resources-tool.js.map +0 -1
- package/dist/tools/list-server-tools-tool.d.ts +0 -17
- package/dist/tools/list-server-tools-tool.d.ts.map +0 -1
- package/dist/tools/list-server-tools-tool.js +0 -52
- package/dist/tools/list-server-tools-tool.js.map +0 -1
- package/dist/tools/list-servers-tool.d.ts +0 -14
- package/dist/tools/list-servers-tool.d.ts.map +0 -1
- package/dist/tools/list-servers-tool.js +0 -47
- package/dist/tools/list-servers-tool.js.map +0 -1
- package/dist/tools/read-resource-tool.d.ts +0 -17
- package/dist/tools/read-resource-tool.d.ts.map +0 -1
- package/dist/tools/read-resource-tool.js +0 -98
- package/dist/tools/read-resource-tool.js.map +0 -1
- package/dist/tools/summary-stats-tool.d.ts +0 -16
- package/dist/tools/summary-stats-tool.d.ts.map +0 -1
- package/dist/tools/summary-stats-tool.js +0 -90
- package/dist/tools/summary-stats-tool.js.map +0 -1
- package/dist/tools/tool-details-tool.d.ts +0 -16
- package/dist/tools/tool-details-tool.d.ts.map +0 -1
- package/dist/tools/tool-details-tool.js +0 -45
- package/dist/tools/tool-details-tool.js.map +0 -1
- package/dist/tools/tool-registry.d.ts +0 -13
- package/dist/tools/tool-registry.d.ts.map +0 -1
- package/dist/tools/tool-registry.js +0 -24
- package/dist/tools/tool-registry.js.map +0 -1
- package/dist/tools/write-gateway-skill-tool.d.ts +0 -25
- package/dist/tools/write-gateway-skill-tool.d.ts.map +0 -1
- package/dist/tools/write-gateway-skill-tool.js +0 -240
- package/dist/tools/write-gateway-skill-tool.js.map +0 -1
- package/dist/types/index.d.ts +0 -22
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -22
- package/dist/types/index.js.map +0 -1
- package/dist/types/interfaces.d.ts +0 -127
- package/dist/types/interfaces.d.ts.map +0 -1
- package/dist/types/interfaces.js +0 -2
- package/dist/types/interfaces.js.map +0 -1
- package/dist/types/skill.d.ts +0 -12
- package/dist/types/skill.d.ts.map +0 -1
- package/dist/types/skill.js +0 -2
- package/dist/types/skill.js.map +0 -1
- package/dist/utils/cli-args.d.ts +0 -6
- package/dist/utils/cli-args.d.ts.map +0 -1
- package/dist/utils/cli-args.js +0 -7
- package/dist/utils/cli-args.js.map +0 -1
- package/dist/utils/config-loader.d.ts +0 -6
- package/dist/utils/config-loader.d.ts.map +0 -1
- package/dist/utils/config-loader.js +0 -108
- package/dist/utils/config-loader.js.map +0 -1
- package/dist/utils/config-paths.d.ts +0 -11
- package/dist/utils/config-paths.d.ts.map +0 -1
- package/dist/utils/config-paths.js +0 -40
- package/dist/utils/config-paths.js.map +0 -1
- package/dist/utils/log-paths.d.ts +0 -22
- package/dist/utils/log-paths.d.ts.map +0 -1
- package/dist/utils/log-paths.js +0 -47
- package/dist/utils/log-paths.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -9
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -46
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/logger.test-helper.d.ts +0 -2
- package/dist/utils/logger.test-helper.d.ts.map +0 -1
- package/dist/utils/logger.test-helper.js +0 -9
- package/dist/utils/logger.test-helper.js.map +0 -1
- package/dist/utils/skills.d.ts +0 -6
- package/dist/utils/skills.d.ts.map +0 -1
- package/dist/utils/skills.js +0 -12
- package/dist/utils/skills.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kara
|
|
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.
|
|
@@ -6,6 +6,9 @@ import { serve } from "@hono/node-server";
|
|
|
6
6
|
import { Hono } from "hono";
|
|
7
7
|
import * as z from "zod";
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
|
+
/**
|
|
10
|
+
* Creates a calculator MCP server with basic math tools
|
|
11
|
+
*/
|
|
9
12
|
function createCalculatorServer() {
|
|
10
13
|
const server = new McpServer({
|
|
11
14
|
name: "calculator",
|
|
@@ -15,6 +18,7 @@ function createCalculatorServer() {
|
|
|
15
18
|
tools: {},
|
|
16
19
|
},
|
|
17
20
|
});
|
|
21
|
+
// Add tool
|
|
18
22
|
server.registerTool("add", {
|
|
19
23
|
description: "Add two numbers",
|
|
20
24
|
inputSchema: z.object({
|
|
@@ -32,6 +36,7 @@ function createCalculatorServer() {
|
|
|
32
36
|
],
|
|
33
37
|
};
|
|
34
38
|
});
|
|
39
|
+
// Multiply tool
|
|
35
40
|
server.registerTool("multiply", {
|
|
36
41
|
description: "Multiply two numbers",
|
|
37
42
|
inputSchema: z.object({
|
|
@@ -49,6 +54,7 @@ function createCalculatorServer() {
|
|
|
49
54
|
],
|
|
50
55
|
};
|
|
51
56
|
});
|
|
57
|
+
// Subtract tool
|
|
52
58
|
server.registerTool("subtract", {
|
|
53
59
|
description: "Subtract two numbers",
|
|
54
60
|
inputSchema: z.object({
|
|
@@ -66,6 +72,7 @@ function createCalculatorServer() {
|
|
|
66
72
|
],
|
|
67
73
|
};
|
|
68
74
|
});
|
|
75
|
+
// Divide tool
|
|
69
76
|
server.registerTool("divide", {
|
|
70
77
|
description: "Divide two numbers",
|
|
71
78
|
inputSchema: z.object({
|
|
@@ -88,12 +95,18 @@ function createCalculatorServer() {
|
|
|
88
95
|
});
|
|
89
96
|
return server;
|
|
90
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Starts the calculator server in HTTP mode on the specified port
|
|
100
|
+
*/
|
|
91
101
|
export async function startHttpCalculatorServer(port) {
|
|
102
|
+
// Track transports and servers per session
|
|
92
103
|
const transports = new Map();
|
|
93
104
|
const servers = new Map();
|
|
105
|
+
// Create HTTP server with Hono
|
|
94
106
|
const app = new Hono();
|
|
95
107
|
app.all("/mcp", async (c) => {
|
|
96
108
|
const sessionId = c.req.header("mcp-session-id");
|
|
109
|
+
// Parse body to check if it's an initialize request
|
|
97
110
|
const rawRequest = c.req.raw;
|
|
98
111
|
const bodyText = await rawRequest.text();
|
|
99
112
|
let body = null;
|
|
@@ -103,11 +116,13 @@ export async function startHttpCalculatorServer(port) {
|
|
|
103
116
|
catch {
|
|
104
117
|
// Invalid JSON
|
|
105
118
|
}
|
|
119
|
+
// Helper to recreate request (since we consumed the body)
|
|
106
120
|
const recreateRequest = () => new Request(rawRequest.url, {
|
|
107
121
|
method: rawRequest.method,
|
|
108
122
|
headers: rawRequest.headers,
|
|
109
123
|
body: bodyText || undefined,
|
|
110
124
|
});
|
|
125
|
+
// New session: no session ID and initialize request
|
|
111
126
|
if (!sessionId && body && isInitializeRequest(body)) {
|
|
112
127
|
const newSessionId = randomUUID();
|
|
113
128
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
@@ -119,6 +134,7 @@ export async function startHttpCalculatorServer(port) {
|
|
|
119
134
|
servers.set(newSessionId, server);
|
|
120
135
|
return transport.handleRequest(recreateRequest());
|
|
121
136
|
}
|
|
137
|
+
// Existing session
|
|
122
138
|
if (sessionId) {
|
|
123
139
|
const transport = transports.get(sessionId);
|
|
124
140
|
if (!transport) {
|
|
@@ -126,6 +142,7 @@ export async function startHttpCalculatorServer(port) {
|
|
|
126
142
|
}
|
|
127
143
|
return transport.handleRequest(recreateRequest());
|
|
128
144
|
}
|
|
145
|
+
// Invalid request (no session ID, not an initialize request)
|
|
129
146
|
return c.text("Bad request - missing session ID", 400);
|
|
130
147
|
});
|
|
131
148
|
const httpServer = serve({
|
|
@@ -135,6 +152,7 @@ export async function startHttpCalculatorServer(port) {
|
|
|
135
152
|
});
|
|
136
153
|
return {
|
|
137
154
|
close: async () => {
|
|
155
|
+
// Close all servers and transports
|
|
138
156
|
for (const server of servers.values()) {
|
|
139
157
|
await server.close();
|
|
140
158
|
}
|
|
@@ -146,13 +164,22 @@ export async function startHttpCalculatorServer(port) {
|
|
|
146
164
|
},
|
|
147
165
|
};
|
|
148
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Starts the calculator server in stdio mode (for use as child process)
|
|
169
|
+
* This function does not return - it runs the server on stdin/stdout
|
|
170
|
+
*/
|
|
149
171
|
export async function startStdioCalculatorServer() {
|
|
150
172
|
const server = createCalculatorServer();
|
|
151
173
|
const transport = new StdioServerTransport();
|
|
152
174
|
await server.connect(transport);
|
|
175
|
+
// Keep process alive indefinitely
|
|
176
|
+
// The transport handles stdin/stdout, we just need to prevent exit
|
|
153
177
|
return new Promise(() => {
|
|
178
|
+
// Never resolves - keeps the process running forever
|
|
154
179
|
});
|
|
155
180
|
}
|
|
181
|
+
// If this file is run directly, start in stdio mode
|
|
182
|
+
// Check if this is the main module
|
|
156
183
|
if (process.argv[1]) {
|
|
157
184
|
const { fileURLToPath } = await import("node:url");
|
|
158
185
|
const currentFile = fileURLToPath(import.meta.url);
|
|
@@ -161,4 +188,3 @@ if (process.argv[1]) {
|
|
|
161
188
|
startStdioCalculatorServer().catch(console.error);
|
|
162
189
|
}
|
|
163
190
|
}
|
|
164
|
-
//# sourceMappingURL=calculator-server.js.map
|
|
@@ -6,6 +6,7 @@ import { serve } from "@hono/node-server";
|
|
|
6
6
|
import { Hono } from "hono";
|
|
7
7
|
import * as z from "zod";
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
|
+
// Sample data for resources
|
|
9
10
|
const testData = {
|
|
10
11
|
users: [
|
|
11
12
|
{ id: 1, name: "Alice", role: "admin" },
|
|
@@ -31,6 +32,9 @@ const fileContents = {
|
|
|
31
32
|
"test-data.json": JSON.stringify(testData, null, 2),
|
|
32
33
|
"config.yaml": configYaml,
|
|
33
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Creates a data server MCP server with resources, tools, and prompts
|
|
37
|
+
*/
|
|
34
38
|
function createDataServer() {
|
|
35
39
|
const server = new McpServer({
|
|
36
40
|
name: "data-server",
|
|
@@ -42,6 +46,7 @@ function createDataServer() {
|
|
|
42
46
|
resources: {},
|
|
43
47
|
},
|
|
44
48
|
});
|
|
49
|
+
// Register tools
|
|
45
50
|
server.registerTool("list-files", {
|
|
46
51
|
description: "List all available files",
|
|
47
52
|
inputSchema: z.object({}),
|
|
@@ -77,6 +82,7 @@ function createDataServer() {
|
|
|
77
82
|
}
|
|
78
83
|
throw new Error(`File not found: ${filename}`);
|
|
79
84
|
});
|
|
85
|
+
// Register prompts
|
|
80
86
|
server.registerPrompt("data-analysis", {
|
|
81
87
|
description: "Analyze the sample data",
|
|
82
88
|
argsSchema: {
|
|
@@ -96,6 +102,7 @@ function createDataServer() {
|
|
|
96
102
|
],
|
|
97
103
|
};
|
|
98
104
|
});
|
|
105
|
+
// Register resources
|
|
99
106
|
const testDataCallback = async (uri) => {
|
|
100
107
|
return {
|
|
101
108
|
contents: [
|
|
@@ -122,12 +129,18 @@ function createDataServer() {
|
|
|
122
129
|
server.resource("config", "file:///config.yaml", configCallback);
|
|
123
130
|
return server;
|
|
124
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Starts the data server in HTTP mode on the specified port
|
|
134
|
+
*/
|
|
125
135
|
export async function startHttpDataServer(port) {
|
|
136
|
+
// Track transports and servers per session
|
|
126
137
|
const transports = new Map();
|
|
127
138
|
const servers = new Map();
|
|
139
|
+
// Create HTTP server with Hono
|
|
128
140
|
const app = new Hono();
|
|
129
141
|
app.all("/mcp", async (c) => {
|
|
130
142
|
const sessionId = c.req.header("mcp-session-id");
|
|
143
|
+
// Parse body to check if it's an initialize request
|
|
131
144
|
const rawRequest = c.req.raw;
|
|
132
145
|
const bodyText = await rawRequest.text();
|
|
133
146
|
let body = null;
|
|
@@ -137,11 +150,13 @@ export async function startHttpDataServer(port) {
|
|
|
137
150
|
catch {
|
|
138
151
|
// Invalid JSON
|
|
139
152
|
}
|
|
153
|
+
// Helper to recreate request (since we consumed the body)
|
|
140
154
|
const recreateRequest = () => new Request(rawRequest.url, {
|
|
141
155
|
method: rawRequest.method,
|
|
142
156
|
headers: rawRequest.headers,
|
|
143
157
|
body: bodyText || undefined,
|
|
144
158
|
});
|
|
159
|
+
// New session: no session ID and initialize request
|
|
145
160
|
if (!sessionId && body && isInitializeRequest(body)) {
|
|
146
161
|
const newSessionId = randomUUID();
|
|
147
162
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
@@ -153,6 +168,7 @@ export async function startHttpDataServer(port) {
|
|
|
153
168
|
servers.set(newSessionId, server);
|
|
154
169
|
return transport.handleRequest(recreateRequest());
|
|
155
170
|
}
|
|
171
|
+
// Existing session
|
|
156
172
|
if (sessionId) {
|
|
157
173
|
const transport = transports.get(sessionId);
|
|
158
174
|
if (!transport) {
|
|
@@ -160,6 +176,7 @@ export async function startHttpDataServer(port) {
|
|
|
160
176
|
}
|
|
161
177
|
return transport.handleRequest(recreateRequest());
|
|
162
178
|
}
|
|
179
|
+
// Invalid request (no session ID, not an initialize request)
|
|
163
180
|
return c.text("Bad request - missing session ID", 400);
|
|
164
181
|
});
|
|
165
182
|
const httpServer = serve({
|
|
@@ -169,6 +186,7 @@ export async function startHttpDataServer(port) {
|
|
|
169
186
|
});
|
|
170
187
|
return {
|
|
171
188
|
close: async () => {
|
|
189
|
+
// Close all servers and transports
|
|
172
190
|
for (const server of servers.values()) {
|
|
173
191
|
await server.close();
|
|
174
192
|
}
|
|
@@ -180,13 +198,22 @@ export async function startHttpDataServer(port) {
|
|
|
180
198
|
},
|
|
181
199
|
};
|
|
182
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Starts the data server in stdio mode (for use as child process)
|
|
203
|
+
* This function does not return - it runs the server on stdin/stdout
|
|
204
|
+
*/
|
|
183
205
|
export async function startStdioDataServer() {
|
|
184
206
|
const server = createDataServer();
|
|
185
207
|
const transport = new StdioServerTransport();
|
|
186
208
|
await server.connect(transport);
|
|
209
|
+
// Keep process alive indefinitely
|
|
210
|
+
// The transport handles stdin/stdout, we just need to prevent exit
|
|
187
211
|
return new Promise(() => {
|
|
212
|
+
// Never resolves - keeps the process running forever
|
|
188
213
|
});
|
|
189
214
|
}
|
|
215
|
+
// If this file is run directly, start in stdio mode
|
|
216
|
+
// Check if this is the main module
|
|
190
217
|
if (process.argv[1]) {
|
|
191
218
|
const { fileURLToPath } = await import("node:url");
|
|
192
219
|
const currentFile = fileURLToPath(import.meta.url);
|
|
@@ -195,4 +222,3 @@ if (process.argv[1]) {
|
|
|
195
222
|
startStdioDataServer().catch(console.error);
|
|
196
223
|
}
|
|
197
224
|
}
|
|
198
|
-
//# sourceMappingURL=data-server.js.map
|
|
@@ -6,6 +6,11 @@ import { serve } from "@hono/node-server";
|
|
|
6
6
|
import { Hono } from "hono";
|
|
7
7
|
import * as z from "zod";
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
|
+
/**
|
|
10
|
+
* Creates an MCP server that uses elicitation requests.
|
|
11
|
+
* This server's tools will trigger elicitation requests to the connected client,
|
|
12
|
+
* which allows testing the elicitation proxy functionality.
|
|
13
|
+
*/
|
|
9
14
|
function createElicitationServer() {
|
|
10
15
|
const server = new McpServer({
|
|
11
16
|
name: "elicitation-test-server",
|
|
@@ -15,6 +20,7 @@ function createElicitationServer() {
|
|
|
15
20
|
tools: {},
|
|
16
21
|
},
|
|
17
22
|
});
|
|
23
|
+
// Tool that triggers a form elicitation request
|
|
18
24
|
server.registerTool("ask_user_form", {
|
|
19
25
|
description: "Ask the user for structured input via a form. This will send an elicitation request to the connected client.",
|
|
20
26
|
inputSchema: z.object({
|
|
@@ -22,6 +28,7 @@ function createElicitationServer() {
|
|
|
22
28
|
}),
|
|
23
29
|
}, async (args) => {
|
|
24
30
|
const { prompt } = args;
|
|
31
|
+
// Send form elicitation request to the connected client
|
|
25
32
|
const result = await server.server.elicitInput({
|
|
26
33
|
message: prompt,
|
|
27
34
|
requestedSchema: {
|
|
@@ -68,6 +75,7 @@ function createElicitationServer() {
|
|
|
68
75
|
};
|
|
69
76
|
}
|
|
70
77
|
});
|
|
78
|
+
// Tool that asks for multiple fields
|
|
71
79
|
server.registerTool("ask_user_details", {
|
|
72
80
|
description: "Ask the user for multiple details via a form",
|
|
73
81
|
inputSchema: z.object({
|
|
@@ -123,12 +131,18 @@ function createElicitationServer() {
|
|
|
123
131
|
});
|
|
124
132
|
return server;
|
|
125
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Starts the elicitation server in HTTP mode on the specified port
|
|
136
|
+
*/
|
|
126
137
|
export async function startHttpElicitationServer(port) {
|
|
138
|
+
// Track transports and servers per session
|
|
127
139
|
const transports = new Map();
|
|
128
140
|
const servers = new Map();
|
|
141
|
+
// Create HTTP server with Hono
|
|
129
142
|
const app = new Hono();
|
|
130
143
|
app.all("/mcp", async (c) => {
|
|
131
144
|
const sessionId = c.req.header("mcp-session-id");
|
|
145
|
+
// Parse body to check if it's an initialize request
|
|
132
146
|
const rawRequest = c.req.raw;
|
|
133
147
|
const bodyText = await rawRequest.text();
|
|
134
148
|
let body = null;
|
|
@@ -138,11 +152,13 @@ export async function startHttpElicitationServer(port) {
|
|
|
138
152
|
catch {
|
|
139
153
|
// Invalid JSON
|
|
140
154
|
}
|
|
155
|
+
// Helper to recreate request (since we consumed the body)
|
|
141
156
|
const recreateRequest = () => new Request(rawRequest.url, {
|
|
142
157
|
method: rawRequest.method,
|
|
143
158
|
headers: rawRequest.headers,
|
|
144
159
|
body: bodyText || undefined,
|
|
145
160
|
});
|
|
161
|
+
// New session: no session ID and initialize request
|
|
146
162
|
if (!sessionId && body && isInitializeRequest(body)) {
|
|
147
163
|
const newSessionId = randomUUID();
|
|
148
164
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
@@ -154,6 +170,7 @@ export async function startHttpElicitationServer(port) {
|
|
|
154
170
|
servers.set(newSessionId, server);
|
|
155
171
|
return transport.handleRequest(recreateRequest());
|
|
156
172
|
}
|
|
173
|
+
// Existing session
|
|
157
174
|
if (sessionId) {
|
|
158
175
|
const transport = transports.get(sessionId);
|
|
159
176
|
if (!transport) {
|
|
@@ -161,6 +178,7 @@ export async function startHttpElicitationServer(port) {
|
|
|
161
178
|
}
|
|
162
179
|
return transport.handleRequest(recreateRequest());
|
|
163
180
|
}
|
|
181
|
+
// Invalid request (no session ID, not an initialize request)
|
|
164
182
|
return c.text("Bad request - missing session ID", 400);
|
|
165
183
|
});
|
|
166
184
|
const httpServer = serve({
|
|
@@ -170,6 +188,7 @@ export async function startHttpElicitationServer(port) {
|
|
|
170
188
|
});
|
|
171
189
|
return {
|
|
172
190
|
close: async () => {
|
|
191
|
+
// Close all servers and transports
|
|
173
192
|
for (const server of servers.values()) {
|
|
174
193
|
await server.close();
|
|
175
194
|
}
|
|
@@ -181,13 +200,20 @@ export async function startHttpElicitationServer(port) {
|
|
|
181
200
|
},
|
|
182
201
|
};
|
|
183
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Starts the elicitation server in stdio mode (for use as child process)
|
|
205
|
+
* This function does not return - it runs the server on stdin/stdout
|
|
206
|
+
*/
|
|
184
207
|
export async function startStdioElicitationServer() {
|
|
185
208
|
const server = createElicitationServer();
|
|
186
209
|
const transport = new StdioServerTransport();
|
|
187
210
|
await server.connect(transport);
|
|
211
|
+
// Keep process alive indefinitely
|
|
188
212
|
return new Promise(() => {
|
|
213
|
+
// Never resolves - keeps the process running forever
|
|
189
214
|
});
|
|
190
215
|
}
|
|
216
|
+
// If this file is run directly, start in stdio mode
|
|
191
217
|
if (process.argv[1]) {
|
|
192
218
|
const { fileURLToPath } = await import("node:url");
|
|
193
219
|
const currentFile = fileURLToPath(import.meta.url);
|
|
@@ -196,4 +222,3 @@ if (process.argv[1]) {
|
|
|
196
222
|
startStdioElicitationServer().catch(console.error);
|
|
197
223
|
}
|
|
198
224
|
}
|
|
199
|
-
//# sourceMappingURL=elicitation-server.js.map
|
|
@@ -3,4 +3,3 @@ export { startHttpDataServer, startStdioDataServer } from "./data-server.js";
|
|
|
3
3
|
export { startHttpSamplingServer, startStdioSamplingServer, } from "./sampling-server.js";
|
|
4
4
|
export { startHttpElicitationServer, startStdioElicitationServer, } from "./elicitation-server.js";
|
|
5
5
|
export { startStdioStderrServer } from "./stderr-server.js";
|
|
6
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -6,6 +6,11 @@ import { serve } from "@hono/node-server";
|
|
|
6
6
|
import { Hono } from "hono";
|
|
7
7
|
import * as z from "zod";
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
|
+
/**
|
|
10
|
+
* Creates an MCP server that uses sampling requests.
|
|
11
|
+
* This server's tools will trigger sampling requests to the connected client,
|
|
12
|
+
* which allows testing the sampling proxy functionality.
|
|
13
|
+
*/
|
|
9
14
|
function createSamplingServer() {
|
|
10
15
|
const server = new McpServer({
|
|
11
16
|
name: "sampling-test-server",
|
|
@@ -15,6 +20,7 @@ function createSamplingServer() {
|
|
|
15
20
|
tools: {},
|
|
16
21
|
},
|
|
17
22
|
});
|
|
23
|
+
// Tool that triggers a sampling request to ask the LLM a question
|
|
18
24
|
server.registerTool("ask_llm", {
|
|
19
25
|
description: "Ask the LLM a question via sampling. This will send a sampling request to the connected client.",
|
|
20
26
|
inputSchema: z.object({
|
|
@@ -22,6 +28,8 @@ function createSamplingServer() {
|
|
|
22
28
|
}),
|
|
23
29
|
}, async (args) => {
|
|
24
30
|
const { question } = args;
|
|
31
|
+
// Send sampling request to the connected client (our proxy)
|
|
32
|
+
// The proxy will forward this to its downstream client
|
|
25
33
|
const result = await server.server.createMessage({
|
|
26
34
|
messages: [
|
|
27
35
|
{
|
|
@@ -34,6 +42,7 @@ function createSamplingServer() {
|
|
|
34
42
|
],
|
|
35
43
|
maxTokens: 100,
|
|
36
44
|
});
|
|
45
|
+
// Extract the text content from the response
|
|
37
46
|
const responseText = result.content.type === "text"
|
|
38
47
|
? result.content.text
|
|
39
48
|
: JSON.stringify(result.content);
|
|
@@ -46,6 +55,7 @@ function createSamplingServer() {
|
|
|
46
55
|
],
|
|
47
56
|
};
|
|
48
57
|
});
|
|
58
|
+
// Tool that asks a multi-turn question
|
|
49
59
|
server.registerTool("multi_turn_llm", {
|
|
50
60
|
description: "Ask the LLM with context from previous messages. Tests multi-message sampling.",
|
|
51
61
|
inputSchema: z.object({
|
|
@@ -94,12 +104,18 @@ function createSamplingServer() {
|
|
|
94
104
|
});
|
|
95
105
|
return server;
|
|
96
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Starts the sampling server in HTTP mode on the specified port
|
|
109
|
+
*/
|
|
97
110
|
export async function startHttpSamplingServer(port) {
|
|
111
|
+
// Track transports and servers per session
|
|
98
112
|
const transports = new Map();
|
|
99
113
|
const servers = new Map();
|
|
114
|
+
// Create HTTP server with Hono
|
|
100
115
|
const app = new Hono();
|
|
101
116
|
app.all("/mcp", async (c) => {
|
|
102
117
|
const sessionId = c.req.header("mcp-session-id");
|
|
118
|
+
// Parse body to check if it's an initialize request
|
|
103
119
|
const rawRequest = c.req.raw;
|
|
104
120
|
const bodyText = await rawRequest.text();
|
|
105
121
|
let body = null;
|
|
@@ -109,11 +125,13 @@ export async function startHttpSamplingServer(port) {
|
|
|
109
125
|
catch {
|
|
110
126
|
// Invalid JSON
|
|
111
127
|
}
|
|
128
|
+
// Helper to recreate request (since we consumed the body)
|
|
112
129
|
const recreateRequest = () => new Request(rawRequest.url, {
|
|
113
130
|
method: rawRequest.method,
|
|
114
131
|
headers: rawRequest.headers,
|
|
115
132
|
body: bodyText || undefined,
|
|
116
133
|
});
|
|
134
|
+
// New session: no session ID and initialize request
|
|
117
135
|
if (!sessionId && body && isInitializeRequest(body)) {
|
|
118
136
|
const newSessionId = randomUUID();
|
|
119
137
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
@@ -125,6 +143,7 @@ export async function startHttpSamplingServer(port) {
|
|
|
125
143
|
servers.set(newSessionId, server);
|
|
126
144
|
return transport.handleRequest(recreateRequest());
|
|
127
145
|
}
|
|
146
|
+
// Existing session
|
|
128
147
|
if (sessionId) {
|
|
129
148
|
const transport = transports.get(sessionId);
|
|
130
149
|
if (!transport) {
|
|
@@ -132,6 +151,7 @@ export async function startHttpSamplingServer(port) {
|
|
|
132
151
|
}
|
|
133
152
|
return transport.handleRequest(recreateRequest());
|
|
134
153
|
}
|
|
154
|
+
// Invalid request (no session ID, not an initialize request)
|
|
135
155
|
return c.text("Bad request - missing session ID", 400);
|
|
136
156
|
});
|
|
137
157
|
const httpServer = serve({
|
|
@@ -141,6 +161,7 @@ export async function startHttpSamplingServer(port) {
|
|
|
141
161
|
});
|
|
142
162
|
return {
|
|
143
163
|
close: async () => {
|
|
164
|
+
// Close all servers and transports
|
|
144
165
|
for (const server of servers.values()) {
|
|
145
166
|
await server.close();
|
|
146
167
|
}
|
|
@@ -152,13 +173,20 @@ export async function startHttpSamplingServer(port) {
|
|
|
152
173
|
},
|
|
153
174
|
};
|
|
154
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Starts the sampling server in stdio mode (for use as child process)
|
|
178
|
+
* This function does not return - it runs the server on stdin/stdout
|
|
179
|
+
*/
|
|
155
180
|
export async function startStdioSamplingServer() {
|
|
156
181
|
const server = createSamplingServer();
|
|
157
182
|
const transport = new StdioServerTransport();
|
|
158
183
|
await server.connect(transport);
|
|
184
|
+
// Keep process alive indefinitely
|
|
159
185
|
return new Promise(() => {
|
|
186
|
+
// Never resolves - keeps the process running forever
|
|
160
187
|
});
|
|
161
188
|
}
|
|
189
|
+
// If this file is run directly, start in stdio mode
|
|
162
190
|
if (process.argv[1]) {
|
|
163
191
|
const { fileURLToPath } = await import("node:url");
|
|
164
192
|
const currentFile = fileURLToPath(import.meta.url);
|
|
@@ -167,4 +195,3 @@ if (process.argv[1]) {
|
|
|
167
195
|
startStdioSamplingServer().catch(console.error);
|
|
168
196
|
}
|
|
169
197
|
}
|
|
170
|
-
//# sourceMappingURL=sampling-server.js.map
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import * as z from "zod";
|
|
4
|
+
/**
|
|
5
|
+
* Creates an MCP server that writes to stderr for testing stderr logging.
|
|
6
|
+
* This server intentionally outputs messages to stderr on startup and
|
|
7
|
+
* when its tool is called.
|
|
8
|
+
*/
|
|
4
9
|
function createStderrServer() {
|
|
5
10
|
const server = new McpServer({
|
|
6
11
|
name: "stderr-test-server",
|
|
@@ -10,6 +15,7 @@ function createStderrServer() {
|
|
|
10
15
|
tools: {},
|
|
11
16
|
},
|
|
12
17
|
});
|
|
18
|
+
// Tool that writes to stderr
|
|
13
19
|
server.registerTool("write_to_stderr", {
|
|
14
20
|
description: "Write a message to stderr for testing",
|
|
15
21
|
inputSchema: z.object({
|
|
@@ -17,6 +23,7 @@ function createStderrServer() {
|
|
|
17
23
|
}),
|
|
18
24
|
}, async (args) => {
|
|
19
25
|
const { message } = args;
|
|
26
|
+
// Write to stderr
|
|
20
27
|
process.stderr.write(`[stderr-test] Tool called: ${message}\n`);
|
|
21
28
|
return {
|
|
22
29
|
content: [
|
|
@@ -27,6 +34,7 @@ function createStderrServer() {
|
|
|
27
34
|
],
|
|
28
35
|
};
|
|
29
36
|
});
|
|
37
|
+
// Simple echo tool for verifying server is working
|
|
30
38
|
server.registerTool("echo", {
|
|
31
39
|
description: "Echo back the input message",
|
|
32
40
|
inputSchema: z.object({
|
|
@@ -45,21 +53,31 @@ function createStderrServer() {
|
|
|
45
53
|
});
|
|
46
54
|
return server;
|
|
47
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Starts the stderr test server in stdio mode.
|
|
58
|
+
* Writes to stderr on startup to verify logging is captured.
|
|
59
|
+
*/
|
|
48
60
|
export async function startStdioStderrServer() {
|
|
61
|
+
// Write startup message to stderr
|
|
49
62
|
process.stderr.write("[stderr-test] Server starting up...\n");
|
|
50
63
|
const server = createStderrServer();
|
|
51
64
|
const transport = new StdioServerTransport();
|
|
52
65
|
await server.connect(transport);
|
|
66
|
+
// Write ready message to stderr
|
|
53
67
|
process.stderr.write("[stderr-test] Server ready and accepting connections\n");
|
|
68
|
+
// Handle shutdown signals
|
|
54
69
|
const handleShutdown = () => {
|
|
55
70
|
process.stderr.write("[stderr-test] Server shutting down (received signal)\n");
|
|
56
71
|
process.exit(0);
|
|
57
72
|
};
|
|
58
73
|
process.on("SIGINT", handleShutdown);
|
|
59
74
|
process.on("SIGTERM", handleShutdown);
|
|
75
|
+
// Keep process alive indefinitely
|
|
60
76
|
return new Promise(() => {
|
|
77
|
+
// Never resolves - keeps the process running forever
|
|
61
78
|
});
|
|
62
79
|
}
|
|
80
|
+
// If this file is run directly, start in stdio mode
|
|
63
81
|
if (process.argv[1]) {
|
|
64
82
|
const { fileURLToPath } = await import("node:url");
|
|
65
83
|
const currentFile = fileURLToPath(import.meta.url);
|
|
@@ -68,4 +86,3 @@ if (process.argv[1]) {
|
|
|
68
86
|
startStdioStderrServer().catch(console.error);
|
|
69
87
|
}
|
|
70
88
|
}
|
|
71
|
-
//# sourceMappingURL=stderr-server.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
|
|
2
|
+
export { }
|