@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/README.md
CHANGED
|
@@ -2,32 +2,62 @@
|
|
|
2
2
|
|
|
3
3
|
## Description
|
|
4
4
|
|
|
5
|
-
[Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for PortKey. It provides tools to map project names to port numbers using keyboard-based letter-to-number mapping and
|
|
5
|
+
[Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for PortKey. It provides tools to map project names to port numbers using keyboard-based letter-to-number mapping, check port availability, and access PortKey configuration.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
### Running the Server
|
|
10
|
+
|
|
11
|
+
The PortKey MCP server supports both Stdio and Streamable HTTP transport modes.
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
#### Stdio Mode (Default)
|
|
14
|
+
|
|
15
|
+
Designed to be run by an IDE-based MCP client like [Visual Studio Code's Copilot](https://code.visualstudio.com/docs/copilot/chat/chat-agent-mode).
|
|
10
16
|
|
|
11
17
|
```shell
|
|
12
|
-
|
|
18
|
+
npx @lionad/port-key-mcp
|
|
13
19
|
```
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
#### HTTP Mode (Streamable)
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
Runs an HTTP server implementing the Streamable HTTP transport. This mode is suitable for remote connections or when stdio is not available.
|
|
24
|
+
|
|
25
|
+
```shell
|
|
26
|
+
# Run on default port 10945
|
|
27
|
+
npx @lionad/port-key-mcp --streamable
|
|
18
28
|
|
|
19
|
-
|
|
29
|
+
# Run on specific port
|
|
30
|
+
npx @lionad/port-key-mcp --streamable --port 8080
|
|
31
|
+
|
|
32
|
+
# Reuse the already-running server on the same port (default: true)
|
|
33
|
+
npx @lionad/port-key-mcp --streamable --port 8080 --reuse
|
|
34
|
+
|
|
35
|
+
# Force starting a new process (will fail if the port is already in use by another service)
|
|
36
|
+
npx @lionad/port-key-mcp --streamable --port 8080 --reuse false
|
|
37
|
+
```
|
|
20
38
|
|
|
39
|
+
Environment variables are also supported:
|
|
21
40
|
```shell
|
|
22
|
-
npx @lionad/port-key-mcp
|
|
41
|
+
PORT=8080 LOG_LEVEL=debug npx @lionad/port-key-mcp --streamable
|
|
23
42
|
```
|
|
24
43
|
|
|
44
|
+
##### Single-instance reuse (Streamable)
|
|
45
|
+
|
|
46
|
+
When you run `npx @lionad/port-key-mcp --streamable` from multiple terminals using the same port, the CLI will detect an existing PortKey MCP server (via `GET /health`) and exit successfully without starting a new server process. This keeps “one port = one MCP server instance” while allowing repeated invocations.
|
|
47
|
+
|
|
48
|
+
##### Endpoints (Streamable)
|
|
49
|
+
|
|
50
|
+
- `GET /health` returns a JSON health payload.
|
|
51
|
+
- `POST /mcp`, `GET /mcp`, `DELETE /mcp` implement MCP Streamable HTTP transport (stateful sessions).
|
|
52
|
+
|
|
25
53
|
### Available Tools
|
|
26
54
|
|
|
27
|
-
The MCP server provides following tools:
|
|
55
|
+
The MCP server provides the following tools:
|
|
28
56
|
|
|
29
57
|
- **map-project-name-to-port**: Map a project name to a port number using keyboard-based letter-to-number mapping
|
|
30
58
|
- **get-design-philosophy**: Get design philosophy and background of PortKey
|
|
59
|
+
- **check-port-availability**: Check if a specific port is available or occupied
|
|
60
|
+
- **get-port-occupancy**: Get information about processes occupying specific ports
|
|
31
61
|
|
|
32
62
|
#### map-project-name-to-port
|
|
33
63
|
|
|
@@ -68,29 +98,24 @@ The MCP server provides following tools:
|
|
|
68
98
|
|
|
69
99
|
- `lang` (string, optional): Language code for design philosophy content. Supported languages: `"cn"`, `"es"`, `"fr"`, `"de"`, `"ja"`, `"ko"`, `"ru"`, `"ar"`, `"pt"`, `"it"`. Default: `"cn"`.
|
|
70
100
|
|
|
71
|
-
|
|
101
|
+
#### check-port-availability
|
|
72
102
|
|
|
73
|
-
|
|
74
|
-
{
|
|
75
|
-
"name": "get-design-philosophy",
|
|
76
|
-
"arguments": {
|
|
77
|
-
"lang": "en"
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
```
|
|
103
|
+
##### Tool Parameters
|
|
81
104
|
|
|
82
|
-
|
|
105
|
+
- `port` (number, required): The port number to check (0-65535)
|
|
83
106
|
|
|
84
|
-
|
|
85
|
-
以下是 PortKey 的设计理念:
|
|
107
|
+
#### get-port-occupancy
|
|
86
108
|
|
|
87
|
-
|
|
109
|
+
##### Tool Parameters
|
|
88
110
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
111
|
+
- `ports` (array of numbers, optional): List of port numbers to filter results
|
|
112
|
+
|
|
113
|
+
### Available Resources
|
|
92
114
|
|
|
93
|
-
|
|
115
|
+
- **config://port-mapping**: Get default port mapping configuration and blocked ports
|
|
116
|
+
- **projects://{projectName}/port-history**: Get history of port assignments for a project
|
|
117
|
+
|
|
118
|
+
### Supported Languages (for design philosophy)
|
|
94
119
|
|
|
95
120
|
| Code | Language |
|
|
96
121
|
|-------|------------|
|
|
@@ -120,22 +145,49 @@ You can configure MCP server in your MCP client's configuration file (e.g., for
|
|
|
120
145
|
}
|
|
121
146
|
```
|
|
122
147
|
|
|
148
|
+
For HTTP mode configuration in clients that support it:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"mcpServers": {
|
|
153
|
+
"port-key": {
|
|
154
|
+
"command": "npx",
|
|
155
|
+
"args": ["@lionad/port-key-mcp", "--streamable"]
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Logs
|
|
162
|
+
|
|
163
|
+
In Streamable HTTP mode, logs are written under `~/.port-key/logs`.
|
|
164
|
+
|
|
123
165
|
## Development
|
|
124
166
|
|
|
125
167
|
Build locales (generates from docs/ directory):
|
|
126
168
|
|
|
127
169
|
```shell
|
|
128
|
-
|
|
170
|
+
pnpm run build:locales
|
|
129
171
|
```
|
|
130
172
|
|
|
131
173
|
Run tests:
|
|
132
174
|
|
|
133
175
|
```shell
|
|
134
|
-
|
|
176
|
+
pnpm test
|
|
135
177
|
```
|
|
136
178
|
|
|
137
179
|
Run tests in watch mode:
|
|
138
180
|
|
|
139
181
|
```shell
|
|
140
|
-
|
|
182
|
+
pnpm run test:watch
|
|
141
183
|
```
|
|
184
|
+
|
|
185
|
+
E2E tests live under `tests/e2e/` and are included in `pnpm test`.
|
|
186
|
+
|
|
187
|
+
## Thanks
|
|
188
|
+
|
|
189
|
+
- **[Template-Nodejs-MCP-Server](https://github.com/HarveyYifanLi/Template-Nodejs-MCP-Server)** by HarveyYifanLi
|
|
190
|
+
- Provided excellent examples of stateful session management and modular tool/resource architecture.
|
|
191
|
+
|
|
192
|
+
- **[mcp-restaurant-booking](https://github.com/modelcontextprotocol/typescript-sdk/tree/main/servers/restaurant)** by Model Context Protocol
|
|
193
|
+
- Provided reference for production-grade TypeScript project configuration and logging systems.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface LoggingConfig {
|
|
2
|
+
level: string;
|
|
3
|
+
}
|
|
4
|
+
interface ServerConfig {
|
|
5
|
+
port: number;
|
|
6
|
+
streamable: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface SessionConfig {
|
|
9
|
+
ttl: number;
|
|
10
|
+
timeout: number;
|
|
11
|
+
}
|
|
12
|
+
interface HealthConfig {
|
|
13
|
+
enableDiskCheck: boolean;
|
|
14
|
+
enableMemoryCheck: boolean;
|
|
15
|
+
enableSessionCheck: boolean;
|
|
16
|
+
diskThreshold: number;
|
|
17
|
+
memoryThreshold: number;
|
|
18
|
+
}
|
|
19
|
+
interface Config {
|
|
20
|
+
logging: LoggingConfig;
|
|
21
|
+
server: ServerConfig;
|
|
22
|
+
session: SessionConfig;
|
|
23
|
+
health: HealthConfig;
|
|
24
|
+
}
|
|
25
|
+
declare const config: Config;
|
|
26
|
+
export default config;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
dotenv.config();
|
|
3
|
+
const config = {
|
|
4
|
+
logging: {
|
|
5
|
+
level: process.env.LOG_LEVEL || 'info',
|
|
6
|
+
},
|
|
7
|
+
server: {
|
|
8
|
+
port: process.env.PORT ? parseInt(process.env.PORT, 10) : 10945,
|
|
9
|
+
streamable: process.env.STREAMABLE === 'true' || process.env.STREAMABLE === '1',
|
|
10
|
+
},
|
|
11
|
+
session: {
|
|
12
|
+
ttl: parseInt(process.env.SESSION_TTL || '3600', 10),
|
|
13
|
+
timeout: parseInt(process.env.SESSION_TIMEOUT || '300000', 10),
|
|
14
|
+
},
|
|
15
|
+
health: {
|
|
16
|
+
enableDiskCheck: process.env.ENABLE_DISK_CHECK !== 'false',
|
|
17
|
+
enableMemoryCheck: process.env.ENABLE_MEMORY_CHECK !== 'false',
|
|
18
|
+
enableSessionCheck: process.env.ENABLE_SESSION_CHECK !== 'false',
|
|
19
|
+
diskThreshold: parseInt(process.env.DISK_THRESHOLD || '1024', 10),
|
|
20
|
+
memoryThreshold: parseInt(process.env.MEMORY_THRESHOLD || '512', 10),
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
export default config;
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,CAAC,MAAM,EAAE,CAAC;AA+BhB,MAAM,MAAM,GAAW;IACrB,OAAO,EAAE;QACP,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;KACvC;IACD,MAAM,EAAE;QACN,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK;QAC/D,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,GAAG;KAChF;IACD,OAAO,EAAE;QACP,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,EAAE,EAAE,CAAC;QACpD,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,QAAQ,EAAE,EAAE,CAAC;KAC/D;IACD,MAAM,EAAE;QACN,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,OAAO;QAC1D,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,OAAO;QAC9D,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,OAAO;QAChE,aAAa,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,MAAM,EAAE,EAAE,CAAC;QACjE,eAAe,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,KAAK,EAAE,EAAE,CAAC;KACrE;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/logger.d.ts
ADDED
package/dist/logger.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import winston from 'winston';
|
|
2
|
+
import DailyRotateFile from 'winston-daily-rotate-file';
|
|
3
|
+
import config from './config/index.js';
|
|
4
|
+
const logger = winston.createLogger({
|
|
5
|
+
level: config.logging.level,
|
|
6
|
+
format: winston.format.combine(winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.json()),
|
|
7
|
+
transports: [
|
|
8
|
+
new DailyRotateFile({
|
|
9
|
+
filename: 'logs/error-%DATE%.log',
|
|
10
|
+
datePattern: 'YYYY-MM-DD',
|
|
11
|
+
zippedArchive: true,
|
|
12
|
+
maxSize: '10m',
|
|
13
|
+
maxFiles: '14d',
|
|
14
|
+
level: 'error',
|
|
15
|
+
}),
|
|
16
|
+
new DailyRotateFile({
|
|
17
|
+
filename: 'logs/combined-%DATE%.log',
|
|
18
|
+
datePattern: 'YYYY-MM-DD',
|
|
19
|
+
zippedArchive: true,
|
|
20
|
+
maxSize: '1',
|
|
21
|
+
maxFiles: '14d',
|
|
22
|
+
}),
|
|
23
|
+
],
|
|
24
|
+
});
|
|
25
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
26
|
+
logger.add(new winston.transports.Console({
|
|
27
|
+
format: winston.format.combine(winston.format.colorize(), winston.format.printf(({ timestamp, level, message, ...rest }) => {
|
|
28
|
+
let args = '';
|
|
29
|
+
if (typeof message === 'object') {
|
|
30
|
+
args = JSON.stringify(message, null, 2);
|
|
31
|
+
message = '';
|
|
32
|
+
}
|
|
33
|
+
const extraArgs = Object.keys(rest).length
|
|
34
|
+
? JSON.stringify(rest, null, 2)
|
|
35
|
+
: '';
|
|
36
|
+
return `${timestamp} ${level}: ${message} ${args} ${extraArgs}`.trim();
|
|
37
|
+
})),
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
logger.getLevel = () => logger.level;
|
|
41
|
+
logger.setLevel = (level) => {
|
|
42
|
+
logger.level = level;
|
|
43
|
+
logger.transports.forEach((transport) => {
|
|
44
|
+
transport.level = level;
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
export default logger;
|
|
48
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,eAAe,MAAM,2BAA2B,CAAC;AACxD,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAOvC,MAAM,MAAM,GAAiB,OAAO,CAAC,YAAY,CAAC;IAChD,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK;IAC3B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAC5B,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,EAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EACtC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CACtB;IACD,UAAU,EAAE;QACV,IAAI,eAAe,CAAC;YAClB,QAAQ,EAAE,uBAAuB;YACjC,WAAW,EAAE,YAAY;YACzB,aAAa,EAAE,IAAI;YACnB,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,OAAO;SACf,CAAC;QACF,IAAI,eAAe,CAAC;YAClB,QAAQ,EAAE,0BAA0B;YACpC,WAAW,EAAE,YAAY;YACzB,aAAa,EAAE,IAAI;YACnB,OAAO,EAAE,GAAG;YACZ,QAAQ,EAAE,KAAK;SAChB,CAAC;KACH;CACF,CAAiB,CAAC;AAEnB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;IAC1C,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,EACzB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE;YAC/D,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAChC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBACxC,OAAO,GAAG,EAAE,CAAC;YACf,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM;gBACxC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/B,CAAC,CAAC,EAAE,CAAC;YACP,OAAO,GAAG,SAAS,IAAI,KAAK,KAAK,OAAO,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC;QACzE,CAAC,CAAC,CACH;KACF,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,QAAQ,GAAG,GAAW,EAAE,CAAC,MAAM,CAAC,KAAe,CAAC;AACvD,MAAM,CAAC,QAAQ,GAAG,CAAC,KAAa,EAAQ,EAAE;IACxC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;QACtC,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/mcp-cli.js
CHANGED
|
@@ -1,13 +1,85 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { mcpServerApp } from "./mcp-server.js";
|
|
2
|
+
import config from "./config/index.js";
|
|
3
|
+
// Parse command line arguments
|
|
4
|
+
const args = process.argv.slice(2);
|
|
5
|
+
const options = {};
|
|
6
|
+
function printHelp() {
|
|
7
|
+
console.log(`
|
|
8
|
+
Usage: port-key-mcp [options]
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
-s, --streamable Run in streamable mode (HTTP)
|
|
12
|
+
-p, --port <number> Specify port number (default: 10945)
|
|
13
|
+
-l, --local [boolean] Enable/disable local tools (default: true)
|
|
14
|
+
--reuse [boolean] Reuse existing streamable server on same port (default: true)
|
|
15
|
+
-h, --help Show this help message
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
port-key-mcp --streamable --port 8080
|
|
19
|
+
port-key-mcp --local false
|
|
20
|
+
`);
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < args.length; i++) {
|
|
23
|
+
const arg = args[i];
|
|
24
|
+
if (arg === "--help" || arg === "-h") {
|
|
25
|
+
printHelp();
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
else if (arg === "--streamable" || arg === "-s") {
|
|
29
|
+
options.streamable = true;
|
|
30
|
+
}
|
|
31
|
+
else if (arg === "--port" || arg === "-p") {
|
|
32
|
+
const port = parseInt(args[i + 1], 10);
|
|
33
|
+
if (!isNaN(port)) {
|
|
34
|
+
options.port = port;
|
|
35
|
+
i++; // Skip next argument
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if (arg === "--local" || arg === "-l") {
|
|
39
|
+
options.local = args[i + 1] !== 'false';
|
|
40
|
+
if (args[i + 1] === 'true' || args[i + 1] === 'false') {
|
|
41
|
+
i++; // Skip next argument if it's a boolean value
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (arg === "--reuse") {
|
|
45
|
+
options.reuse = args[i + 1] !== "false";
|
|
46
|
+
if (args[i + 1] === "true" || args[i + 1] === "false") {
|
|
47
|
+
i++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function resolvePort() {
|
|
52
|
+
if (typeof options.port === "number")
|
|
53
|
+
return options.port;
|
|
54
|
+
const envPort = process.env.PORT ? parseInt(process.env.PORT, 10) : NaN;
|
|
55
|
+
if (!Number.isNaN(envPort))
|
|
56
|
+
return envPort;
|
|
57
|
+
return config.server.port;
|
|
58
|
+
}
|
|
59
|
+
async function isPortKeyMcpServerRunning(port) {
|
|
60
|
+
try {
|
|
61
|
+
const res = await fetch(`http://127.0.0.1:${port}/health`, {
|
|
62
|
+
signal: AbortSignal.timeout(1000),
|
|
63
|
+
headers: { Accept: "application/json" },
|
|
64
|
+
});
|
|
65
|
+
if (!res.ok)
|
|
66
|
+
return false;
|
|
67
|
+
const body = await res.json().catch(() => null);
|
|
68
|
+
return Boolean(body && typeof body === "object" && body.status === "ok");
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const shouldRunStreamable = options.streamable || config.server.streamable;
|
|
75
|
+
const reuseEnabled = options.reuse !== false;
|
|
76
|
+
if (shouldRunStreamable && reuseEnabled) {
|
|
77
|
+
const port = resolvePort();
|
|
78
|
+
const running = await isPortKeyMcpServerRunning(port);
|
|
79
|
+
if (running) {
|
|
80
|
+
console.log(`PortKey MCP Server already running at http://127.0.0.1:${port}`);
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
await mcpServerApp.run(options);
|
|
13
85
|
//# sourceMappingURL=mcp-cli.js.map
|
package/dist/mcp-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-cli.js","sourceRoot":"","sources":["../src/mcp-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"mcp-cli.js","sourceRoot":"","sources":["../src/mcp-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-server.d.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
declare
|
|
3
|
-
|
|
2
|
+
export declare class MCPServerApp {
|
|
3
|
+
private server;
|
|
4
|
+
constructor();
|
|
5
|
+
private createServer;
|
|
6
|
+
private registerTools;
|
|
7
|
+
private registerResources;
|
|
8
|
+
getMcpServer(): McpServer;
|
|
9
|
+
runStdio(): Promise<void>;
|
|
10
|
+
runHttp(port?: number): Promise<void>;
|
|
11
|
+
run(options?: {
|
|
12
|
+
streamable?: boolean;
|
|
13
|
+
port?: number;
|
|
14
|
+
local?: boolean;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export declare const mcpServerApp: MCPServerApp;
|