kubeview-mcp 1.7.5 → 1.7.6
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/CHANGELOG.md +13 -2
- package/README.md +28 -0
- package/dist/src/index.d.ts +4 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +66 -96
- package/dist/src/index.js.map +1 -1
- package/dist/src/server/MCPServer.d.ts +22 -6
- package/dist/src/server/MCPServer.d.ts.map +1 -1
- package/dist/src/server/MCPServer.js +47 -18
- package/dist/src/server/MCPServer.js.map +1 -1
- package/dist/src/server/StreamableHttpRuntime.d.ts +41 -0
- package/dist/src/server/StreamableHttpRuntime.d.ts.map +1 -0
- package/dist/src/server/StreamableHttpRuntime.js +315 -0
- package/dist/src/server/StreamableHttpRuntime.js.map +1 -0
- package/dist/src/server/TransportConfig.d.ts +18 -0
- package/dist/src/server/TransportConfig.d.ts.map +1 -0
- package/dist/src/server/TransportConfig.js +71 -0
- package/dist/src/server/TransportConfig.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/tests/compat/McpSdkCompatibility.test.js +4 -4
- package/dist/tests/server/MCPServer.test.js +10 -0
- package/dist/tests/server/MCPServer.test.js.map +1 -1
- package/dist/tests/server/StreamableHttpRuntime.test.d.ts +2 -0
- package/dist/tests/server/StreamableHttpRuntime.test.d.ts.map +1 -0
- package/dist/tests/server/StreamableHttpRuntime.test.js +383 -0
- package/dist/tests/server/StreamableHttpRuntime.test.js.map +1 -0
- package/dist/tests/server/StreamableHttpTransport.integration.test.d.ts +2 -0
- package/dist/tests/server/StreamableHttpTransport.integration.test.d.ts.map +1 -0
- package/dist/tests/server/StreamableHttpTransport.integration.test.js +141 -0
- package/dist/tests/server/StreamableHttpTransport.integration.test.js.map +1 -0
- package/dist/tests/server/TransportConfig.test.d.ts +2 -0
- package/dist/tests/server/TransportConfig.test.d.ts.map +1 -0
- package/dist/tests/server/TransportConfig.test.js +15 -0
- package/dist/tests/server/TransportConfig.test.js.map +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,14 +5,25 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [1.7.6] - 2026-05-03
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Streamable HTTP transport mode** with configurable host, port, path, stateless mode, JSON responses, and host/origin allowlists.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- **Refactor MCP server startup** to support explicit transport injection and shared mode-specific server creation.
|
|
15
|
+
- **Upgrade `@modelcontextprotocol/sdk` to `^1.29.0`** for newer Streamable HTTP transport support and compatibility updates.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **HTTP runtime correctness**: handle IPv6 `::1` bindings correctly, return JSON-RPC parse errors for malformed HTTP request bodies, and stop pre-session app servers when `initialize` is rejected before a session is created.
|
|
19
|
+
- **HTTP startup reporting**: log the actual bound port when `MCP_HTTP_PORT=0` assigns an ephemeral port.
|
|
20
|
+
- **Transport config scoping**: only enforce HTTP host allowlist validation when `MCP_TRANSPORT=http`, so default `stdio` startup is unaffected by HTTP-only environment variables.
|
|
9
21
|
|
|
10
22
|
## [1.7.5] - 2026-04-22
|
|
11
23
|
|
|
12
24
|
### Changed
|
|
13
25
|
- **Update hono to version 4.12.14.**
|
|
14
26
|
|
|
15
|
-
|
|
16
27
|
## [1.7.4] - 2026-04-08
|
|
17
28
|
|
|
18
29
|
### Changed
|
package/README.md
CHANGED
|
@@ -59,9 +59,37 @@ Add to your `mcpServers` config (Cursor, Claude Desktop, etc.):
|
|
|
59
59
|
| Variable | Description | Default |
|
|
60
60
|
| -------------------- | -------------------------------------------- | ---------------- |
|
|
61
61
|
| `KUBECONFIG` | Path to kubeconfig file | `~/.kube/config` |
|
|
62
|
+
| `MCP_TRANSPORT` | Transport: `stdio` (default) or `http` | `stdio` |
|
|
62
63
|
| `MCP_MODE` | Server mode: `all`, `code`, or `tools` | `all` |
|
|
63
64
|
| `MCP_LOG_LEVEL` | Log level: `error`, `warn`, `info`, `debug` | `info` |
|
|
64
65
|
| `MCP_HIDE_SENSITIVE` | Mask sensitive data globally | `false` |
|
|
66
|
+
| `MCP_HTTP_HOST` | HTTP bind host when `MCP_TRANSPORT=http` | `127.0.0.1` |
|
|
67
|
+
| `MCP_HTTP_PORT` | HTTP port when `MCP_TRANSPORT=http` | `3000` |
|
|
68
|
+
| `MCP_HTTP_PATH` | Streamable HTTP endpoint path | `/mcp` |
|
|
69
|
+
| `MCP_HTTP_STATELESS` | Disable session IDs in HTTP mode | `false` |
|
|
70
|
+
| `MCP_HTTP_JSON_RESPONSE` | Prefer JSON responses over SSE | `false` |
|
|
71
|
+
| `MCP_ALLOWED_HOSTS` | Comma-separated Host allowlist for HTTP mode | local defaults |
|
|
72
|
+
| `MCP_ALLOWED_ORIGINS`| Comma-separated Origin allowlist for HTTP mode | unset |
|
|
73
|
+
|
|
74
|
+
### Streamable HTTP Mode
|
|
75
|
+
|
|
76
|
+
KubeView can also run as a standalone **Streamable HTTP** server for hosted or manually managed deployments.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
MCP_TRANSPORT=http \
|
|
80
|
+
MCP_HTTP_HOST=127.0.0.1 \
|
|
81
|
+
MCP_HTTP_PORT=3000 \
|
|
82
|
+
npx -y kubeview-mcp
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This starts a Streamable HTTP endpoint at `http://127.0.0.1:3000/mcp`.
|
|
86
|
+
|
|
87
|
+
Notes:
|
|
88
|
+
|
|
89
|
+
- `stdio` remains the default and is still the right choice for MCP client configs such as Claude Desktop, Cursor, and Codex CLI.
|
|
90
|
+
- `MCP_HTTP_STATELESS=true` disables session IDs. That is useful for simple request/response patterns, but stateful features such as `plan_step` history are not meaningful in that mode.
|
|
91
|
+
- If you bind HTTP mode to `0.0.0.0` or `::`, you must set `MCP_ALLOWED_HOSTS`.
|
|
92
|
+
- HTTP mode is intended for manual deployment. The published MCP registry metadata still targets `stdio`.
|
|
65
93
|
|
|
66
94
|
---
|
|
67
95
|
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Kubernetes MCP Server
|
|
4
|
-
* Main entry point for the Model Context Protocol server
|
|
5
|
-
*
|
|
6
|
-
* Modes (MCP_MODE env var):
|
|
7
|
-
* - code: exposes only `run_code` for agent code execution
|
|
8
|
-
* - tools: exposes only Kubernetes, Helm, and Argo tools (no `run_code`)
|
|
9
|
-
* - all (default): exposes both tools and `run_code`
|
|
10
|
-
* per https://www.anthropic.com/engineering/code-execution-with-mcp
|
|
4
|
+
* Main entry point for the Model Context Protocol server.
|
|
11
5
|
*/
|
|
6
|
+
import { MCPServer } from './server/MCPServer.js';
|
|
12
7
|
import { VERSION } from './version.js';
|
|
13
8
|
export { VERSION };
|
|
9
|
+
type MCPMode = 'code' | 'tools' | 'all';
|
|
10
|
+
export declare function createServerForMode(mode: MCPMode): Promise<MCPServer>;
|
|
14
11
|
export declare function main(): Promise<void>;
|
|
15
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AASlD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,CAAC;AAEnB,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAqGxC,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAiB3E;AAcD,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAyB1C"}
|
package/dist/src/index.js
CHANGED
|
@@ -1,49 +1,46 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Kubernetes MCP Server
|
|
4
|
-
* Main entry point for the Model Context Protocol server
|
|
5
|
-
*
|
|
6
|
-
* Modes (MCP_MODE env var):
|
|
7
|
-
* - code: exposes only `run_code` for agent code execution
|
|
8
|
-
* - tools: exposes only Kubernetes, Helm, and Argo tools (no `run_code`)
|
|
9
|
-
* - all (default): exposes both tools and `run_code`
|
|
10
|
-
* per https://www.anthropic.com/engineering/code-execution-with-mcp
|
|
4
|
+
* Main entry point for the Model Context Protocol server.
|
|
11
5
|
*/
|
|
12
6
|
import { MCPServer } from './server/MCPServer.js';
|
|
7
|
+
import { StreamableHttpRuntime } from './server/StreamableHttpRuntime.js';
|
|
8
|
+
import { loadTransportConfig } from './server/TransportConfig.js';
|
|
13
9
|
import { KubernetesToolsPlugin } from './plugins/KubernetesToolsPlugin.js';
|
|
14
10
|
import { HelmToolsPlugin } from './plugins/HelmToolsPlugin.js';
|
|
15
11
|
import { ArgoToolsPlugin } from './plugins/ArgoToolsPlugin.js';
|
|
16
12
|
import { ArgoCDToolsPlugin } from './plugins/ArgoCDToolsPlugin.js';
|
|
17
13
|
import { RunCodeTool } from './tools/RunCodeTool.js';
|
|
14
|
+
import { loadCodeModeConfig } from './utils/CodeModeConfig.js';
|
|
18
15
|
import { VERSION } from './version.js';
|
|
19
16
|
export { VERSION };
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// Load all plugins internally (not exposed to MCP, but available for code execution)
|
|
29
|
-
const internalServer = new MCPServer({
|
|
30
|
-
skipTransportErrorHandling: true,
|
|
31
|
-
skipGracefulShutdown: true,
|
|
32
|
-
});
|
|
33
|
-
const kubernetesPlugin = new KubernetesToolsPlugin();
|
|
34
|
-
await internalServer.loadPlugin(kubernetesPlugin);
|
|
17
|
+
function getMCPMode() {
|
|
18
|
+
const mode = process.env.MCP_MODE?.toLowerCase();
|
|
19
|
+
if (mode === 'code' || mode === 'tools' || mode === 'all') {
|
|
20
|
+
return mode;
|
|
21
|
+
}
|
|
22
|
+
return 'all';
|
|
23
|
+
}
|
|
24
|
+
async function loadOptionalPlugins(server) {
|
|
35
25
|
const optionalPlugins = [new HelmToolsPlugin(), new ArgoToolsPlugin(), new ArgoCDToolsPlugin()];
|
|
36
26
|
for (const plugin of optionalPlugins) {
|
|
37
27
|
try {
|
|
38
|
-
await
|
|
28
|
+
await server.loadPlugin(plugin);
|
|
39
29
|
}
|
|
40
30
|
catch (err) {
|
|
41
31
|
const message = err instanceof Error ? err.message : String(err);
|
|
42
32
|
console.error(`Optional plugin '${plugin.name}' skipped: ${message}`);
|
|
43
33
|
}
|
|
44
34
|
}
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
}
|
|
36
|
+
async function configureCodeModeServer(server) {
|
|
37
|
+
const config = loadCodeModeConfig();
|
|
38
|
+
const internalServer = new MCPServer({
|
|
39
|
+
skipTransportErrorHandling: true,
|
|
40
|
+
skipGracefulShutdown: true,
|
|
41
|
+
});
|
|
42
|
+
await internalServer.loadPlugin(new KubernetesToolsPlugin());
|
|
43
|
+
await loadOptionalPlugins(internalServer);
|
|
47
44
|
const toolExecutor = async (qualifiedName, args) => {
|
|
48
45
|
const toolName = qualifiedName.includes('__')
|
|
49
46
|
? qualifiedName.split('__').pop()
|
|
@@ -54,14 +51,12 @@ async function startCodeMode(server) {
|
|
|
54
51
|
runCodeTool.setToolExecutor(toolExecutor);
|
|
55
52
|
runCodeTool.setTools(internalServer.getTools());
|
|
56
53
|
server.registerTool(runCodeTool.tool, (params) => runCodeTool.execute(params));
|
|
57
|
-
// Register global.d.ts resource for type definitions
|
|
58
54
|
server.registerResource({
|
|
59
55
|
uri: 'file:///sys/global.d.ts',
|
|
60
56
|
name: 'Global Type Definitions',
|
|
61
57
|
mimeType: 'application/typescript',
|
|
62
58
|
text: runCodeTool.generateGlobalDts(),
|
|
63
59
|
});
|
|
64
|
-
// Register code-mode prompt with tool overview and examples
|
|
65
60
|
server.registerPrompt({
|
|
66
61
|
name: 'code-mode',
|
|
67
62
|
description: 'Injects TypeScript definitions and API docs for Code Mode with tool overview and examples.',
|
|
@@ -73,68 +68,25 @@ async function startCodeMode(server) {
|
|
|
73
68
|
},
|
|
74
69
|
],
|
|
75
70
|
});
|
|
76
|
-
await server.start();
|
|
77
|
-
console.error(`KubeView MCP is running in code-mode. ` +
|
|
78
|
-
'Only `run_code` tool exposed; code can call all Kubernetes/Helm/Argo tools.');
|
|
79
71
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
async function startToolsMode(server) {
|
|
84
|
-
const kubernetesPlugin = new KubernetesToolsPlugin();
|
|
85
|
-
await server.loadPlugin(kubernetesPlugin);
|
|
86
|
-
const optionalPlugins = [new HelmToolsPlugin(), new ArgoToolsPlugin(), new ArgoCDToolsPlugin()];
|
|
87
|
-
for (const plugin of optionalPlugins) {
|
|
88
|
-
try {
|
|
89
|
-
await server.loadPlugin(plugin);
|
|
90
|
-
}
|
|
91
|
-
catch (err) {
|
|
92
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
93
|
-
console.error(`Optional plugin '${plugin.name}' skipped: ${message}`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
await server.start();
|
|
97
|
-
console.error(`KubeView MCP is running in tools-mode. Only Kubernetes/Helm/Argo tools exposed.`);
|
|
72
|
+
async function configureToolsModeServer(server) {
|
|
73
|
+
await server.loadPlugin(new KubernetesToolsPlugin());
|
|
74
|
+
await loadOptionalPlugins(server);
|
|
98
75
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
async function startAllMode(server) {
|
|
76
|
+
async function configureAllModeServer(server) {
|
|
77
|
+
await server.loadPlugin(new KubernetesToolsPlugin());
|
|
78
|
+
await loadOptionalPlugins(server);
|
|
103
79
|
const config = loadCodeModeConfig();
|
|
104
|
-
const kubernetesPlugin = new KubernetesToolsPlugin();
|
|
105
|
-
await server.loadPlugin(kubernetesPlugin);
|
|
106
|
-
const optionalPlugins = [new HelmToolsPlugin(), new ArgoToolsPlugin(), new ArgoCDToolsPlugin()];
|
|
107
|
-
for (const plugin of optionalPlugins) {
|
|
108
|
-
try {
|
|
109
|
-
await server.loadPlugin(plugin);
|
|
110
|
-
}
|
|
111
|
-
catch (err) {
|
|
112
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
113
|
-
console.error(`Optional plugin '${plugin.name}' skipped: ${message}`);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
// Set up run_code tool
|
|
117
|
-
const toolExecutor = async (qualifiedName, args) => {
|
|
118
|
-
return server.executeTool(qualifiedName, args);
|
|
119
|
-
};
|
|
120
80
|
const runCodeTool = new RunCodeTool(config.sandbox);
|
|
121
|
-
runCodeTool.setToolExecutor(
|
|
122
|
-
// We need to set tools for the description builder.
|
|
123
|
-
// In all mode, we can get them from the server after plugins are loaded.
|
|
124
|
-
// However, server.getTools() returns Tool[], but setTools expects Tool[] which is fine.
|
|
125
|
-
// But wait, RunCodeTool.setTools uses them to build the manifest for the description.
|
|
126
|
-
// We should do this before registering the tool so the description is correct?
|
|
127
|
-
// Actually, we can do it before starting the server.
|
|
81
|
+
runCodeTool.setToolExecutor(async (qualifiedName, args) => server.executeTool(qualifiedName, args));
|
|
128
82
|
runCodeTool.setTools(server.getTools());
|
|
129
83
|
server.registerTool(runCodeTool.tool, (params) => runCodeTool.execute(params));
|
|
130
|
-
// Register global.d.ts resource for type definitions
|
|
131
84
|
server.registerResource({
|
|
132
85
|
uri: 'file:///sys/global.d.ts',
|
|
133
86
|
name: 'Global Type Definitions',
|
|
134
87
|
mimeType: 'application/typescript',
|
|
135
88
|
text: runCodeTool.generateGlobalDts(),
|
|
136
89
|
});
|
|
137
|
-
// Register code-mode prompt with tool overview and examples
|
|
138
90
|
server.registerPrompt({
|
|
139
91
|
name: 'code-mode',
|
|
140
92
|
description: 'Injects TypeScript definitions and API docs for Code Mode with tool overview and examples.',
|
|
@@ -146,33 +98,51 @@ async function startAllMode(server) {
|
|
|
146
98
|
},
|
|
147
99
|
],
|
|
148
100
|
});
|
|
149
|
-
await server.start();
|
|
150
|
-
console.error(`KubeView MCP is running. Waiting for connections...`);
|
|
151
101
|
}
|
|
152
|
-
function
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
102
|
+
export async function createServerForMode(mode) {
|
|
103
|
+
const server = new MCPServer();
|
|
104
|
+
switch (mode) {
|
|
105
|
+
case 'code':
|
|
106
|
+
await configureCodeModeServer(server);
|
|
107
|
+
break;
|
|
108
|
+
case 'tools':
|
|
109
|
+
await configureToolsModeServer(server);
|
|
110
|
+
break;
|
|
111
|
+
case 'all':
|
|
112
|
+
default:
|
|
113
|
+
await configureAllModeServer(server);
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
return server;
|
|
117
|
+
}
|
|
118
|
+
function getReadyMessage(mode) {
|
|
119
|
+
switch (mode) {
|
|
120
|
+
case 'code':
|
|
121
|
+
return 'KubeView MCP is running in code-mode. Only `run_code` tool exposed; code can call all Kubernetes/Helm/Argo tools.';
|
|
122
|
+
case 'tools':
|
|
123
|
+
return 'KubeView MCP is running in tools-mode. Only Kubernetes/Helm/Argo tools exposed.';
|
|
124
|
+
case 'all':
|
|
125
|
+
default:
|
|
126
|
+
return 'KubeView MCP is running. Waiting for connections...';
|
|
156
127
|
}
|
|
157
|
-
return 'all'; // default
|
|
158
128
|
}
|
|
159
129
|
export async function main() {
|
|
160
130
|
console.error(`Kubernetes MCP Server v${VERSION} - Starting...`);
|
|
161
131
|
try {
|
|
162
|
-
const server = new MCPServer();
|
|
163
132
|
const mode = getMCPMode();
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
await startAllMode(server);
|
|
174
|
-
break;
|
|
133
|
+
const transportConfig = loadTransportConfig();
|
|
134
|
+
if (transportConfig.transport === 'http') {
|
|
135
|
+
const runtime = new StreamableHttpRuntime(transportConfig.http, {
|
|
136
|
+
createAppServer: () => createServerForMode(mode),
|
|
137
|
+
});
|
|
138
|
+
await runtime.start();
|
|
139
|
+
const { host, port, path } = runtime.getAddress();
|
|
140
|
+
runtime.logInfo(`${getReadyMessage(mode)} HTTP endpoint: http://${host}:${port}${path}`);
|
|
141
|
+
return;
|
|
175
142
|
}
|
|
143
|
+
const server = await createServerForMode(mode);
|
|
144
|
+
await server.start();
|
|
145
|
+
console.error(getReadyMessage(mode));
|
|
176
146
|
}
|
|
177
147
|
catch (error) {
|
|
178
148
|
console.error('Failed to start MCP server:', error);
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,CAAC;AAInB,SAAS,UAAU;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACjD,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,MAAiB;IAClD,MAAM,eAAe,GAAG,CAAC,IAAI,eAAe,EAAE,EAAE,IAAI,eAAe,EAAE,EAAE,IAAI,iBAAiB,EAAE,CAAC,CAAC;IAChG,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,IAAI,cAAc,OAAO,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,MAAiB;IACtD,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACpC,MAAM,cAAc,GAAG,IAAI,SAAS,CAAC;QACnC,0BAA0B,EAAE,IAAI;QAChC,oBAAoB,EAAE,IAAI;KAC3B,CAAC,CAAC;IAEH,MAAM,cAAc,CAAC,UAAU,CAAC,IAAI,qBAAqB,EAAE,CAAC,CAAC;IAC7D,MAAM,mBAAmB,CAAC,cAAc,CAAC,CAAC;IAE1C,MAAM,YAAY,GAAG,KAAK,EAAE,aAAqB,EAAE,IAAa,EAAE,EAAE;QAClE,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC3C,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAG;YAClC,CAAC,CAAC,aAAa,CAAC;QAClB,OAAO,cAAc,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAC1C,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEhD,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/E,MAAM,CAAC,gBAAgB,CAAC;QACtB,GAAG,EAAE,yBAAyB;QAC9B,IAAI,EAAE,yBAAyB;QAC/B,QAAQ,EAAE,wBAAwB;QAClC,IAAI,EAAE,WAAW,CAAC,iBAAiB,EAAE;KACP,CAAC,CAAC;IAClC,MAAM,CAAC,cAAc,CAAC;QACpB,IAAI,EAAE,WAAW;QACjB,WAAW,EACT,4FAA4F;QAC9F,SAAS,EAAE,EAAE;QACb,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;YACvB;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,gBAAgB,EAAE,EAAE;aAChE;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,wBAAwB,CAAC,MAAiB;IACvD,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,qBAAqB,EAAE,CAAC,CAAC;IACrD,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAC,MAAiB;IACrD,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,qBAAqB,EAAE,CAAC,CAAC;IACrD,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAElC,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACpC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,WAAW,CAAC,eAAe,CAAC,KAAK,EAAE,aAAqB,EAAE,IAAa,EAAE,EAAE,CACzE,MAAM,CAAC,WAAW,CAAC,aAAa,EAAE,IAAI,CAAC,CACxC,CAAC;IACF,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAExC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/E,MAAM,CAAC,gBAAgB,CAAC;QACtB,GAAG,EAAE,yBAAyB;QAC9B,IAAI,EAAE,yBAAyB;QAC/B,QAAQ,EAAE,wBAAwB;QAClC,IAAI,EAAE,WAAW,CAAC,iBAAiB,EAAE;KACP,CAAC,CAAC;IAClC,MAAM,CAAC,cAAc,CAAC;QACpB,IAAI,EAAE,WAAW;QACjB,WAAW,EACT,4FAA4F;QAC9F,SAAS,EAAE,EAAE;QACb,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;YACvB;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,gBAAgB,EAAE,EAAE;aAChE;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAa;IACrD,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;IAE/B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,MAAM,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM;QACR,KAAK,OAAO;YACV,MAAM,wBAAwB,CAAC,MAAM,CAAC,CAAC;YACvC,MAAM;QACR,KAAK,KAAK,CAAC;QACX;YACE,MAAM,sBAAsB,CAAC,MAAM,CAAC,CAAC;YACrC,MAAM;IACV,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CAAC,IAAa;IACpC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,OAAO,mHAAmH,CAAC;QAC7H,KAAK,OAAO;YACV,OAAO,iFAAiF,CAAC;QAC3F,KAAK,KAAK,CAAC;QACX;YACE,OAAO,qDAAqD,CAAC;IACjE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,gBAAgB,CAAC,CAAC;IAEjE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAC1B,MAAM,eAAe,GAAG,mBAAmB,EAAE,CAAC;QAE9C,IAAI,eAAe,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,qBAAqB,CAAC,eAAe,CAAC,IAAI,EAAE;gBAC9D,eAAe,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC;aACjD,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YAEtB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;YAClD,OAAO,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,0BAA0B,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;YACzF,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
2
3
|
import { Tool, Resource } from '@modelcontextprotocol/sdk/types.js';
|
|
3
4
|
import winston from 'winston';
|
|
4
5
|
/**
|
|
@@ -44,8 +45,10 @@ export interface MCPServerOptions {
|
|
|
44
45
|
export declare class MCPServer {
|
|
45
46
|
private static readonly MAX_MALFORMED_STDIN_LOGS;
|
|
46
47
|
private server;
|
|
47
|
-
private transport
|
|
48
|
+
private transport?;
|
|
48
49
|
private logger;
|
|
50
|
+
private hasLoggedStartupBegin;
|
|
51
|
+
private hasLoggedStartupSuccess;
|
|
49
52
|
private clientLoggingLevel?;
|
|
50
53
|
private tools;
|
|
51
54
|
private resources;
|
|
@@ -70,12 +73,13 @@ export declare class MCPServer {
|
|
|
70
73
|
* Remove all tracked event listeners
|
|
71
74
|
*/
|
|
72
75
|
private removeAllListeners;
|
|
76
|
+
private isStdioTransport;
|
|
73
77
|
/**
|
|
74
|
-
* Set up
|
|
78
|
+
* Set up stdio-specific error handling for the transport.
|
|
75
79
|
*/
|
|
76
|
-
private
|
|
80
|
+
private setupStdioTransportErrorHandling;
|
|
77
81
|
/**
|
|
78
|
-
* Attempt to gracefully restart the server connection
|
|
82
|
+
* Attempt to gracefully restart the stdio server connection
|
|
79
83
|
*/
|
|
80
84
|
private gracefulRestart;
|
|
81
85
|
/**
|
|
@@ -115,9 +119,13 @@ export declare class MCPServer {
|
|
|
115
119
|
*/
|
|
116
120
|
start(): Promise<void>;
|
|
117
121
|
/**
|
|
118
|
-
*
|
|
122
|
+
* Start the MCP server with an explicit transport.
|
|
119
123
|
*/
|
|
120
|
-
|
|
124
|
+
startWithTransport(transport: Transport): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Connect to stdio with improved error handling
|
|
127
|
+
*/
|
|
128
|
+
private connectStdioWithErrorHandling;
|
|
121
129
|
/**
|
|
122
130
|
* Inspect newline-delimited JSON-RPC messages and emit user-friendly diagnostics.
|
|
123
131
|
*/
|
|
@@ -143,6 +151,14 @@ export declare class MCPServer {
|
|
|
143
151
|
* Clean up resources and event listeners (useful for tests)
|
|
144
152
|
*/
|
|
145
153
|
cleanup(): void;
|
|
154
|
+
/**
|
|
155
|
+
* Emit the standard startup-begin log once, even if startup is split across phases.
|
|
156
|
+
*/
|
|
157
|
+
logStartupBegin(): void;
|
|
158
|
+
/**
|
|
159
|
+
* Emit the standard startup-success log once, even if startup is split across phases.
|
|
160
|
+
*/
|
|
161
|
+
logStartupSuccess(): void;
|
|
146
162
|
/**
|
|
147
163
|
* Build a stderr-only logger with optional file output and MCP log forwarding.
|
|
148
164
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MCPServer.d.ts","sourceRoot":"","sources":["../../../src/server/MCPServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EAWL,IAAI,EACJ,QAAQ,EAET,MAAM,oCAAoC,CAAC;AAC5C,OAAO,OAAO,MAAM,SAAS,CAAC;AAoF9B;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B;;;;OAIG;IACH,iBAAiB,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAUD;;GAEG;AACH,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC9E,WAAW,EAAE,CACX,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC1B,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC,CAAC;CAChF;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAK;IACrD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"MCPServer.d.ts","sourceRoot":"","sources":["../../../src/server/MCPServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -76,6 +76,8 @@ export class MCPServer {
|
|
|
76
76
|
server;
|
|
77
77
|
transport;
|
|
78
78
|
logger;
|
|
79
|
+
hasLoggedStartupBegin = false;
|
|
80
|
+
hasLoggedStartupSuccess = false;
|
|
79
81
|
clientLoggingLevel;
|
|
80
82
|
tools = new Map();
|
|
81
83
|
resources = new Map();
|
|
@@ -105,15 +107,9 @@ export class MCPServer {
|
|
|
105
107
|
logging: {},
|
|
106
108
|
},
|
|
107
109
|
});
|
|
108
|
-
// Initialize stdio transport
|
|
109
|
-
this.transport = new StdioServerTransport();
|
|
110
110
|
this.clientLoggingLevel = this.parseLoggingLevel(process.env.MCP_CLIENT_LOG_LEVEL);
|
|
111
111
|
// Initialize Winston logger (stderr only to avoid interfering with MCP stdout)
|
|
112
112
|
this.logger = this.createLogger();
|
|
113
|
-
// Add custom error handler to the transport (skip in tests)
|
|
114
|
-
if (!options.skipTransportErrorHandling) {
|
|
115
|
-
this.setupTransportErrorHandling();
|
|
116
|
-
}
|
|
117
113
|
// Set up handlers
|
|
118
114
|
this.setupHandlers();
|
|
119
115
|
// Set up graceful shutdown (skip in tests to avoid process listeners)
|
|
@@ -194,10 +190,13 @@ export class MCPServer {
|
|
|
194
190
|
}
|
|
195
191
|
this.eventListeners = [];
|
|
196
192
|
}
|
|
193
|
+
isStdioTransport(transport) {
|
|
194
|
+
return transport instanceof StdioServerTransport;
|
|
195
|
+
}
|
|
197
196
|
/**
|
|
198
|
-
* Set up
|
|
197
|
+
* Set up stdio-specific error handling for the transport.
|
|
199
198
|
*/
|
|
200
|
-
|
|
199
|
+
setupStdioTransportErrorHandling() {
|
|
201
200
|
// Handle connection errors in the transport
|
|
202
201
|
// StdioServerTransport uses the process stdin/stdout directly
|
|
203
202
|
this.addTrackedListener(process.stdin, 'error', (error) => {
|
|
@@ -223,10 +222,10 @@ export class MCPServer {
|
|
|
223
222
|
}
|
|
224
223
|
}
|
|
225
224
|
/**
|
|
226
|
-
* Attempt to gracefully restart the server connection
|
|
225
|
+
* Attempt to gracefully restart the stdio server connection
|
|
227
226
|
*/
|
|
228
227
|
async gracefulRestart() {
|
|
229
|
-
if (this.isShuttingDown)
|
|
228
|
+
if (this.isShuttingDown || !this.isStdioTransport(this.transport))
|
|
230
229
|
return;
|
|
231
230
|
this.logger.info('Attempting to gracefully restart server connection...');
|
|
232
231
|
try {
|
|
@@ -479,17 +478,27 @@ export class MCPServer {
|
|
|
479
478
|
* Start the MCP server
|
|
480
479
|
*/
|
|
481
480
|
async start() {
|
|
482
|
-
this.
|
|
481
|
+
await this.startWithTransport(new StdioServerTransport());
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Start the MCP server with an explicit transport.
|
|
485
|
+
*/
|
|
486
|
+
async startWithTransport(transport) {
|
|
487
|
+
this.logStartupBegin();
|
|
488
|
+
this.transport = transport;
|
|
483
489
|
try {
|
|
484
490
|
if (this.options.skipTransportErrorHandling) {
|
|
485
491
|
// Simple connection for tests
|
|
486
|
-
await this.server.connect(
|
|
492
|
+
await this.server.connect(transport);
|
|
493
|
+
}
|
|
494
|
+
else if (this.isStdioTransport(transport)) {
|
|
495
|
+
this.setupStdioTransportErrorHandling();
|
|
496
|
+
await this.connectStdioWithErrorHandling(transport);
|
|
487
497
|
}
|
|
488
498
|
else {
|
|
489
|
-
|
|
490
|
-
await this.connectWithErrorHandling();
|
|
499
|
+
await this.server.connect(transport);
|
|
491
500
|
}
|
|
492
|
-
this.
|
|
501
|
+
this.logStartupSuccess();
|
|
493
502
|
}
|
|
494
503
|
catch (error) {
|
|
495
504
|
this.logger.error('Failed to start MCP server', error);
|
|
@@ -497,9 +506,9 @@ export class MCPServer {
|
|
|
497
506
|
}
|
|
498
507
|
}
|
|
499
508
|
/**
|
|
500
|
-
* Connect to
|
|
509
|
+
* Connect to stdio with improved error handling
|
|
501
510
|
*/
|
|
502
|
-
async
|
|
511
|
+
async connectStdioWithErrorHandling(transport) {
|
|
503
512
|
// Validate incoming JSON-RPC frames without disrupting SDK listeners.
|
|
504
513
|
const validateChunk = (chunk) => {
|
|
505
514
|
try {
|
|
@@ -525,7 +534,7 @@ export class MCPServer {
|
|
|
525
534
|
this.addTrackedListener(process.stdin, 'data', validateChunk);
|
|
526
535
|
}
|
|
527
536
|
// Connect to the transport
|
|
528
|
-
await this.server.connect(
|
|
537
|
+
await this.server.connect(transport);
|
|
529
538
|
}
|
|
530
539
|
/**
|
|
531
540
|
* Inspect newline-delimited JSON-RPC messages and emit user-friendly diagnostics.
|
|
@@ -629,6 +638,26 @@ export class MCPServer {
|
|
|
629
638
|
cleanup() {
|
|
630
639
|
this.removeAllListeners();
|
|
631
640
|
}
|
|
641
|
+
/**
|
|
642
|
+
* Emit the standard startup-begin log once, even if startup is split across phases.
|
|
643
|
+
*/
|
|
644
|
+
logStartupBegin() {
|
|
645
|
+
if (this.hasLoggedStartupBegin) {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
this.hasLoggedStartupBegin = true;
|
|
649
|
+
this.logger.info('Starting MCP server...');
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Emit the standard startup-success log once, even if startup is split across phases.
|
|
653
|
+
*/
|
|
654
|
+
logStartupSuccess() {
|
|
655
|
+
if (this.hasLoggedStartupSuccess) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
this.hasLoggedStartupSuccess = true;
|
|
659
|
+
this.logger.info('MCP server started successfully');
|
|
660
|
+
}
|
|
632
661
|
/**
|
|
633
662
|
* Build a stderr-only logger with optional file output and MCP log forwarding.
|
|
634
663
|
*/
|