@lionad/port-key-mcp 0.3.0 → 0.4.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/README.md +81 -29
- package/dist/config/index.d.ts +26 -0
- package/dist/config/index.js +24 -0
- package/dist/config/index.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +48 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-cli.js +84 -12
- package/dist/mcp-cli.js.map +1 -1
- package/dist/mcp-server.d.ts +16 -2
- package/dist/mcp-server.js +250 -92
- package/dist/mcp-server.js.map +1 -1
- package/dist/resources/index.d.ts +13 -0
- package/dist/resources/index.js +5 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/port-mapping-config.d.ts +13 -0
- package/dist/resources/port-mapping-config.js +22 -0
- package/dist/resources/port-mapping-config.js.map +1 -0
- package/dist/resources/project-port-history.d.ts +15 -0
- package/dist/resources/project-port-history.js +30 -0
- package/dist/resources/project-port-history.js.map +1 -0
- package/dist/session-manager.d.ts +35 -0
- package/dist/session-manager.js +66 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/tools/check-port-availability.d.ts +25 -0
- package/dist/tools/check-port-availability.js +65 -0
- package/dist/tools/check-port-availability.js.map +1 -0
- package/dist/tools/get-design-philosophy.d.ts +24 -0
- package/dist/tools/get-design-philosophy.js +52 -0
- package/dist/tools/get-design-philosophy.js.map +1 -0
- package/dist/tools/get-port-occupancy.d.ts +25 -0
- package/dist/tools/get-port-occupancy.js +69 -0
- package/dist/tools/get-port-occupancy.js.map +1 -0
- package/dist/tools/index.d.ts +94 -0
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/map-project-name-to-port.d.ts +27 -0
- package/dist/tools/map-project-name-to-port.js +51 -0
- package/dist/tools/map-project-name-to-port.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.js +55 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/session-manager.d.ts +35 -0
- package/dist/utils/session-manager.js +66 -0
- package/dist/utils/session-manager.js.map +1 -0
- package/package.json +11 -5
package/dist/mcp-server.js
CHANGED
|
@@ -1,103 +1,261 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import Fastify from "fastify";
|
|
7
|
+
import cors from "@fastify/cors";
|
|
8
|
+
import { tools } from "./tools/index.js";
|
|
9
|
+
import { resources } from "./resources/index.js";
|
|
10
|
+
import config from "./config/index.js";
|
|
11
|
+
import logger from "./utils/logger.js";
|
|
12
|
+
import { SessionManager } from "./utils/session-manager.js";
|
|
13
|
+
// Session manager for HTTP transport
|
|
14
|
+
const sessionManager = new SessionManager(config.session);
|
|
15
|
+
export class MCPServerApp {
|
|
16
|
+
server;
|
|
17
|
+
constructor() {
|
|
18
|
+
this.server = this.createServer();
|
|
16
19
|
}
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
createServer() {
|
|
21
|
+
const server = new McpServer({
|
|
22
|
+
name: "PortKey",
|
|
23
|
+
// ! AUTO GENERATED VERSION - DO NOT EDIT
|
|
24
|
+
version: "0.4.2",
|
|
25
|
+
});
|
|
26
|
+
this.registerTools(server);
|
|
27
|
+
this.registerResources(server);
|
|
28
|
+
return server;
|
|
19
29
|
}
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
map: z.string().optional(),
|
|
31
|
-
preferDigitCount: z.number().int().min(2).max(5).optional(),
|
|
32
|
-
minPort: z.number().int().min(0).max(65535).optional(),
|
|
33
|
-
maxPort: z.number().int().min(0).max(65535).optional(),
|
|
34
|
-
blockedPorts: z.array(z.number().int().min(0).max(65535)).optional(),
|
|
35
|
-
},
|
|
36
|
-
}, async ({ projectName, map, preferDigitCount, minPort, maxPort, blockedPorts }) => {
|
|
37
|
-
try {
|
|
38
|
-
let customMap = undefined;
|
|
39
|
-
if (map && map !== "") {
|
|
40
|
-
customMap = JSON.parse(map);
|
|
30
|
+
registerTools(server, isLocal = true) {
|
|
31
|
+
for (const tool of tools) {
|
|
32
|
+
// 云端执行时,不注册依赖本地工具的工具
|
|
33
|
+
if (!isLocal && tool.isLocal) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
server.registerTool(tool.name, {
|
|
37
|
+
description: tool.description,
|
|
38
|
+
inputSchema: tool.inputSchema,
|
|
39
|
+
}, tool.execute);
|
|
41
40
|
}
|
|
42
|
-
const options = {
|
|
43
|
-
preferDigitCount,
|
|
44
|
-
minPort,
|
|
45
|
-
maxPort,
|
|
46
|
-
blockedPorts: blockedPorts ? new Set(blockedPorts) : undefined,
|
|
47
|
-
};
|
|
48
|
-
const result = mapToPort(projectName, customMap, options);
|
|
49
|
-
return {
|
|
50
|
-
content: [
|
|
51
|
-
{
|
|
52
|
-
type: "text",
|
|
53
|
-
text: JSON.stringify(result, null, 2),
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
};
|
|
57
41
|
}
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
42
|
+
registerResources(server) {
|
|
43
|
+
for (const resource of resources) {
|
|
44
|
+
if (typeof resource.resourceUri === 'string') {
|
|
45
|
+
server.registerResource(resource.name, resource.resourceUri, {
|
|
46
|
+
title: resource.title,
|
|
47
|
+
description: resource.description,
|
|
48
|
+
mimeType: resource.mimeType,
|
|
49
|
+
}, async (uri) => {
|
|
50
|
+
const result = await resource.execute(uri);
|
|
51
|
+
return result;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
server.registerResource(resource.name, resource.resourceUri, {
|
|
56
|
+
title: resource.title,
|
|
57
|
+
description: resource.description,
|
|
58
|
+
mimeType: resource.mimeType,
|
|
59
|
+
}, async (uri, params) => {
|
|
60
|
+
const result = await resource.execute(uri, params);
|
|
61
|
+
return result;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
69
65
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
text: philosophy,
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
};
|
|
66
|
+
getMcpServer() {
|
|
67
|
+
return this.server;
|
|
68
|
+
}
|
|
69
|
+
async runStdio() {
|
|
70
|
+
logger.info("Starting PortKey MCP Server in Stdio mode");
|
|
71
|
+
try {
|
|
72
|
+
const transport = new StdioServerTransport();
|
|
73
|
+
await this.server.connect(transport);
|
|
74
|
+
logger.info("PortKey MCP Server connected to Stdio transport");
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
logger.error("Failed to start Stdio server", error);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
88
80
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
81
|
+
async runHttp(port = config.server.port) {
|
|
82
|
+
logger.info(`Starting PortKey MCP Server in HTTP mode on port ${port}`);
|
|
83
|
+
const fastify = Fastify({
|
|
84
|
+
logger: false, // We use our own logger
|
|
85
|
+
});
|
|
86
|
+
// Register CORS
|
|
87
|
+
await fastify.register(cors, {
|
|
88
|
+
origin: true, // Allow all origins for now, can be configured
|
|
89
|
+
exposedHeaders: ["mcp-session-id"],
|
|
90
|
+
allowedHeaders: ["Content-Type", "mcp-session-id", "mcp-protocol-version"],
|
|
91
|
+
});
|
|
92
|
+
// Health check endpoint
|
|
93
|
+
fastify.get("/health", async () => {
|
|
94
|
+
// Basic health check
|
|
95
|
+
const memoryUsage = process.memoryUsage();
|
|
96
|
+
const healthStatus = {
|
|
97
|
+
status: "ok",
|
|
98
|
+
uptime: process.uptime(),
|
|
99
|
+
memory: {
|
|
100
|
+
rss: Math.round(memoryUsage.rss / 1024 / 1024) + "MB",
|
|
101
|
+
heapTotal: Math.round(memoryUsage.heapTotal / 1024 / 1024) + "MB",
|
|
102
|
+
heapUsed: Math.round(memoryUsage.heapUsed / 1024 / 1024) + "MB",
|
|
96
103
|
},
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
sessions: sessionManager.size,
|
|
105
|
+
};
|
|
106
|
+
return healthStatus;
|
|
107
|
+
});
|
|
108
|
+
// Handle POST requests for client-to-server communication
|
|
109
|
+
fastify.post("/mcp", async (request, reply) => {
|
|
110
|
+
const sessionId = request.headers["mcp-session-id"];
|
|
111
|
+
let transport;
|
|
112
|
+
// Reuse existing transport if session ID provided
|
|
113
|
+
if (sessionId) {
|
|
114
|
+
transport = sessionManager.get(sessionId);
|
|
115
|
+
}
|
|
116
|
+
// Initialize new transport
|
|
117
|
+
if (!transport && isInitializeRequest(request.body)) {
|
|
118
|
+
const allowedHosts = [
|
|
119
|
+
`127.0.0.1:${port}`,
|
|
120
|
+
`localhost:${port}`,
|
|
121
|
+
`[::1]:${port}`,
|
|
122
|
+
];
|
|
123
|
+
transport = new StreamableHTTPServerTransport({
|
|
124
|
+
sessionIdGenerator: () => randomUUID(),
|
|
125
|
+
onsessioninitialized: (id) => {
|
|
126
|
+
if (transport) {
|
|
127
|
+
sessionManager.set(id, transport);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
// DNS rebinding protection
|
|
131
|
+
enableDnsRebindingProtection: true,
|
|
132
|
+
allowedHosts,
|
|
133
|
+
});
|
|
134
|
+
transport.onclose = () => {
|
|
135
|
+
if (transport?.sessionId) {
|
|
136
|
+
sessionManager.remove(transport.sessionId);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
// Connect a new server instance to this transport
|
|
140
|
+
// Each HTTP session needs its own server instance to maintain state isolation
|
|
141
|
+
const sessionServer = this.createServer();
|
|
142
|
+
await sessionServer.connect(transport);
|
|
143
|
+
}
|
|
144
|
+
else if (!transport) {
|
|
145
|
+
return reply.code(400).send({
|
|
146
|
+
jsonrpc: "2.0",
|
|
147
|
+
error: {
|
|
148
|
+
code: -32000,
|
|
149
|
+
message: "Bad Request: No valid session ID provided or invalid initialization",
|
|
150
|
+
},
|
|
151
|
+
id: null,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// Handle the request
|
|
155
|
+
// @ts-ignore - Fastify types compatibility
|
|
156
|
+
await transport.handleRequest(request.raw, reply.raw, request.body);
|
|
157
|
+
});
|
|
158
|
+
// Handle GET requests for server-to-client notifications
|
|
159
|
+
fastify.get("/mcp", async (request, reply) => {
|
|
160
|
+
const sessionId = request.headers["mcp-session-id"];
|
|
161
|
+
if (!sessionId) {
|
|
162
|
+
return reply.code(400).send("Invalid or missing session ID");
|
|
163
|
+
}
|
|
164
|
+
const transport = sessionManager.get(sessionId);
|
|
165
|
+
if (!transport) {
|
|
166
|
+
return reply.code(400).send("Session not found");
|
|
167
|
+
}
|
|
168
|
+
// @ts-ignore
|
|
169
|
+
await transport.handleRequest(request.raw, reply.raw);
|
|
170
|
+
});
|
|
171
|
+
// Handle DELETE requests for session termination
|
|
172
|
+
fastify.delete("/mcp", async (request, reply) => {
|
|
173
|
+
const sessionId = request.headers["mcp-session-id"];
|
|
174
|
+
if (!sessionId) {
|
|
175
|
+
return reply.code(400).send("Invalid or missing session ID");
|
|
176
|
+
}
|
|
177
|
+
const transport = sessionManager.get(sessionId);
|
|
178
|
+
if (!transport) {
|
|
179
|
+
return reply.code(400).send("Session not found");
|
|
180
|
+
}
|
|
181
|
+
// @ts-ignore
|
|
182
|
+
await transport.handleRequest(request.raw, reply.raw);
|
|
183
|
+
sessionManager.remove(sessionId);
|
|
184
|
+
});
|
|
185
|
+
try {
|
|
186
|
+
await fastify.listen({ port, host: "127.0.0.1" });
|
|
187
|
+
logger.info(`PortKey MCP Server listening on http://127.0.0.1:${port}`);
|
|
188
|
+
logger.info(`Health check available at http://127.0.0.1:${port}/health`);
|
|
189
|
+
logger.info(`MCP endpoint available at http://127.0.0.1:${port}/mcp`);
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
const code = err && typeof err === "object" && "code" in err ? err.code : undefined;
|
|
193
|
+
if (code === "EADDRINUSE") {
|
|
194
|
+
try {
|
|
195
|
+
const res = await fetch(`http://127.0.0.1:${port}/health`, {
|
|
196
|
+
signal: AbortSignal.timeout(1000),
|
|
197
|
+
headers: { Accept: "application/json" },
|
|
198
|
+
});
|
|
199
|
+
if (res.ok) {
|
|
200
|
+
const body = await res.json().catch(() => null);
|
|
201
|
+
if (body && typeof body === "object" && body.status === "ok") {
|
|
202
|
+
logger.info(`PortKey MCP Server already running on http://127.0.0.1:${port}`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
logger.error("Failed to start HTTP server", err);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async run(options = {}) {
|
|
215
|
+
// Graceful shutdown
|
|
216
|
+
const shutdown = () => {
|
|
217
|
+
logger.info("Shutting down PortKey MCP Server...");
|
|
218
|
+
sessionManager.destroy();
|
|
219
|
+
process.exit(0);
|
|
99
220
|
};
|
|
221
|
+
process.on("SIGINT", shutdown);
|
|
222
|
+
process.on("SIGTERM", shutdown);
|
|
223
|
+
// Re-register tools based on options.local
|
|
224
|
+
// By default local is true unless explicitly set to false
|
|
225
|
+
const isLocal = options.local !== false;
|
|
226
|
+
// Clear existing tools registration and re-register
|
|
227
|
+
// Note: Since we register in createServer(), we might need to recreate server or just register again
|
|
228
|
+
// But sdk doesn't support unregister. So we should create server with correct tools from start or
|
|
229
|
+
// modify registerTools to take options.
|
|
230
|
+
// Since createServer is called in constructor, we need a way to re-init or filter tools.
|
|
231
|
+
// Better approach: We should register tools in run() or have a separate init()
|
|
232
|
+
// But since constructor calls createServer, let's just create a NEW server instance if we need to filter tools
|
|
233
|
+
// However, this.server is already assigned.
|
|
234
|
+
// Let's modify createServer to accept options, but we can't change constructor signature easily without breaking things.
|
|
235
|
+
// Instead, let's re-create the server instance here if we need to filter tools.
|
|
236
|
+
if (isLocal === false) {
|
|
237
|
+
this.server = new McpServer({
|
|
238
|
+
name: "PortKey",
|
|
239
|
+
version: "0.1.5", // Should match what was in createServer
|
|
240
|
+
});
|
|
241
|
+
// Register only non-local tools
|
|
242
|
+
this.registerTools(this.server, false);
|
|
243
|
+
this.registerResources(this.server);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
// If isLocal is true (default), we already registered all tools in constructor
|
|
247
|
+
// But to be safe and consistent, we could re-register or just ensure constructor did the right thing.
|
|
248
|
+
// The constructor calls createServer which calls registerTools without args (so all tools).
|
|
249
|
+
// So if isLocal is true, we are good with default instance.
|
|
250
|
+
}
|
|
251
|
+
if (options.streamable || config.server.streamable) {
|
|
252
|
+
await this.runHttp(options.port || config.server.port);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
await this.runStdio();
|
|
256
|
+
}
|
|
100
257
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
258
|
+
}
|
|
259
|
+
// Export a singleton for backward compatibility if needed, though class usage is preferred
|
|
260
|
+
export const mcpServerApp = new MCPServerApp();
|
|
103
261
|
//# sourceMappingURL=mcp-server.js.map
|
package/dist/mcp-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAErE,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,yBAAyB;CAC1B,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DEFAULT_MAP, DEFAULT_BLOCKED_PORTS } from "@lionad/port-key";
|
|
2
|
+
export const portMappingConfigResource = {
|
|
3
|
+
name: "config",
|
|
4
|
+
resourceUri: "config://port-mapping",
|
|
5
|
+
title: "Port Mapping Configuration",
|
|
6
|
+
description: "Default port mapping configuration and blocked ports",
|
|
7
|
+
mimeType: "application/json",
|
|
8
|
+
execute: async (uri) => {
|
|
9
|
+
return {
|
|
10
|
+
contents: [
|
|
11
|
+
{
|
|
12
|
+
uri: uri.href,
|
|
13
|
+
text: JSON.stringify({
|
|
14
|
+
defaultMap: DEFAULT_MAP,
|
|
15
|
+
defaultBlockedPorts: Array.from(DEFAULT_BLOCKED_PORTS),
|
|
16
|
+
}, null, 2),
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=port-mapping-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-mapping-config.js","sourceRoot":"","sources":["../../src/resources/port-mapping-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEtE,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,uBAAuB;IACpC,KAAK,EAAE,4BAA4B;IACnC,WAAW,EAAE,sDAAsD;IACnE,QAAQ,EAAE,kBAAkB;IAC5B,OAAO,EAAE,KAAK,EAAE,GAAQ,EAAE,EAAE;QAC1B,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,UAAU,EAAE,WAAW;wBACvB,mBAAmB,EAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;qBACvD,EAAE,IAAI,EAAE,CAAC,CAAC;iBACZ;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export declare const projectPortHistoryResource: {
|
|
3
|
+
name: string;
|
|
4
|
+
resourceUri: ResourceTemplate;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
execute: (uri: URL, { projectName }: {
|
|
8
|
+
projectName: string;
|
|
9
|
+
}) => Promise<{
|
|
10
|
+
contents: {
|
|
11
|
+
uri: string;
|
|
12
|
+
text: string;
|
|
13
|
+
}[];
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { mapToPort } from "@lionad/port-key";
|
|
3
|
+
export const projectPortHistoryResource = {
|
|
4
|
+
name: "project-port-history",
|
|
5
|
+
resourceUri: new ResourceTemplate("projects://{projectName}/port-history", { list: undefined }),
|
|
6
|
+
title: "Project Port History",
|
|
7
|
+
description: "History of port assignments for a project",
|
|
8
|
+
execute: async (uri, { projectName }) => {
|
|
9
|
+
// In a real application, this would fetch from a database or log file
|
|
10
|
+
// For now, we simulate history by generating the current port assignment
|
|
11
|
+
const result = mapToPort(projectName);
|
|
12
|
+
const history = [
|
|
13
|
+
{
|
|
14
|
+
timestamp: new Date().toISOString(),
|
|
15
|
+
projectName,
|
|
16
|
+
assignedPort: result.port,
|
|
17
|
+
digits: result.digits,
|
|
18
|
+
}
|
|
19
|
+
];
|
|
20
|
+
return {
|
|
21
|
+
contents: [
|
|
22
|
+
{
|
|
23
|
+
uri: uri.href,
|
|
24
|
+
text: JSON.stringify(history, null, 2),
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=project-port-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-port-history.js","sourceRoot":"","sources":["../../src/resources/project-port-history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EAAE,IAAI,gBAAgB,CAAC,uCAAuC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC/F,KAAK,EAAE,sBAAsB;IAC7B,WAAW,EAAE,2CAA2C;IACxD,OAAO,EAAE,KAAK,EAAE,GAAQ,EAAE,EAAE,WAAW,EAA2B,EAAE,EAAE;QACpE,sEAAsE;QACtE,yEAAyE;QACzE,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;QAEtC,MAAM,OAAO,GAAG;YACd;gBACE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,WAAW;gBACX,YAAY,EAAE,MAAM,CAAC,IAAI;gBACzB,MAAM,EAAE,MAAM,CAAC,MAAM;aACtB;SACF,CAAC;QAEF,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
interface SessionOptions {
|
|
2
|
+
ttl: number;
|
|
3
|
+
timeout: number;
|
|
4
|
+
}
|
|
5
|
+
export declare class SessionManager<T> {
|
|
6
|
+
private sessions;
|
|
7
|
+
private options;
|
|
8
|
+
private cleanupInterval;
|
|
9
|
+
constructor(options?: SessionOptions);
|
|
10
|
+
/**
|
|
11
|
+
* Set a session with the given ID and data
|
|
12
|
+
*/
|
|
13
|
+
set(id: string, data: T): void;
|
|
14
|
+
/**
|
|
15
|
+
* Get a session by ID. Updates the expiration time (sliding window).
|
|
16
|
+
*/
|
|
17
|
+
get(id: string): T | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Remove a session by ID
|
|
20
|
+
*/
|
|
21
|
+
remove(id: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Get the number of active sessions
|
|
24
|
+
*/
|
|
25
|
+
get size(): number;
|
|
26
|
+
/**
|
|
27
|
+
* Cleanup expired sessions
|
|
28
|
+
*/
|
|
29
|
+
private cleanup;
|
|
30
|
+
/**
|
|
31
|
+
* Stop the cleanup interval and clear all sessions
|
|
32
|
+
*/
|
|
33
|
+
destroy(): void;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import config from './config/index.js';
|
|
2
|
+
export class SessionManager {
|
|
3
|
+
sessions;
|
|
4
|
+
options;
|
|
5
|
+
cleanupInterval;
|
|
6
|
+
constructor(options = config.session) {
|
|
7
|
+
this.sessions = new Map();
|
|
8
|
+
this.options = options;
|
|
9
|
+
// Cleanup every minute to remove expired sessions
|
|
10
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), 60000);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Set a session with the given ID and data
|
|
14
|
+
*/
|
|
15
|
+
set(id, data) {
|
|
16
|
+
const expiresAt = Date.now() + this.options.ttl * 1000;
|
|
17
|
+
this.sessions.set(id, { data, expiresAt });
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get a session by ID. Updates the expiration time (sliding window).
|
|
21
|
+
*/
|
|
22
|
+
get(id) {
|
|
23
|
+
const session = this.sessions.get(id);
|
|
24
|
+
if (!session)
|
|
25
|
+
return undefined;
|
|
26
|
+
// Check if expired
|
|
27
|
+
if (Date.now() > session.expiresAt) {
|
|
28
|
+
this.sessions.delete(id);
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
// Refresh expiration
|
|
32
|
+
session.expiresAt = Date.now() + this.options.ttl * 1000;
|
|
33
|
+
return session.data;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Remove a session by ID
|
|
37
|
+
*/
|
|
38
|
+
remove(id) {
|
|
39
|
+
this.sessions.delete(id);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get the number of active sessions
|
|
43
|
+
*/
|
|
44
|
+
get size() {
|
|
45
|
+
return this.sessions.size;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Cleanup expired sessions
|
|
49
|
+
*/
|
|
50
|
+
cleanup() {
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
for (const [id, session] of this.sessions.entries()) {
|
|
53
|
+
if (now > session.expiresAt) {
|
|
54
|
+
this.sessions.delete(id);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Stop the cleanup interval and clear all sessions
|
|
60
|
+
*/
|
|
61
|
+
destroy() {
|
|
62
|
+
clearInterval(this.cleanupInterval);
|
|
63
|
+
this.sessions.clear();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAYvC,MAAM,OAAO,cAAc;IACjB,QAAQ,CAAiC;IACzC,OAAO,CAAiB;IACxB,eAAe,CAAiB;IAExC,YAAY,UAA0B,MAAM,CAAC,OAAO;QAClD,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,kDAAkD;QAClD,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,EAAU,EAAE,IAAO;QACrB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;QACvD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,EAAU;QACZ,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAE/B,mBAAmB;QACnB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACzB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,qBAAqB;QACrB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;QACzD,OAAO,OAAO,CAAC,IAAI,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAU;QACf,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED;;OAEG;IACK,OAAO;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,IAAI,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;gBAC5B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO;QACL,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACpC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const checkPortAvailabilityTool: {
|
|
3
|
+
name: string;
|
|
4
|
+
title: string;
|
|
5
|
+
isLocal: boolean;
|
|
6
|
+
description: string;
|
|
7
|
+
inputSchema: {
|
|
8
|
+
port: z.ZodNumber;
|
|
9
|
+
};
|
|
10
|
+
execute: ({ port }: {
|
|
11
|
+
port: number;
|
|
12
|
+
}) => Promise<{
|
|
13
|
+
content: {
|
|
14
|
+
type: string;
|
|
15
|
+
text: string;
|
|
16
|
+
}[];
|
|
17
|
+
isError?: undefined;
|
|
18
|
+
} | {
|
|
19
|
+
content: {
|
|
20
|
+
type: string;
|
|
21
|
+
text: string;
|
|
22
|
+
}[];
|
|
23
|
+
isError: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
};
|