@eclipse-glsp/server-mcp 2.7.0-next.9
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 +642 -0
- package/README.md +57 -0
- package/lib/index.d.ts +23 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +41 -0
- package/lib/index.js.map +1 -0
- package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.d.ts +43 -0
- package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.d.ts.map +1 -0
- package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.js +96 -0
- package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.js.map +1 -0
- package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.d.ts +43 -0
- package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.d.ts.map +1 -0
- package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.js +95 -0
- package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.js.map +1 -0
- package/lib/prompts/index.d.ts +18 -0
- package/lib/prompts/index.d.ts.map +1 -0
- package/lib/prompts/index.js +34 -0
- package/lib/prompts/index.js.map +1 -0
- package/lib/resources/handlers/diagram-png-mcp-resource-handler.d.ts +81 -0
- package/lib/resources/handlers/diagram-png-mcp-resource-handler.d.ts.map +1 -0
- package/lib/resources/handlers/diagram-png-mcp-resource-handler.js +174 -0
- package/lib/resources/handlers/diagram-png-mcp-resource-handler.js.map +1 -0
- package/lib/resources/handlers/diagram-svg-mcp-resource-handler.d.ts +52 -0
- package/lib/resources/handlers/diagram-svg-mcp-resource-handler.d.ts.map +1 -0
- package/lib/resources/handlers/diagram-svg-mcp-resource-handler.js +96 -0
- package/lib/resources/handlers/diagram-svg-mcp-resource-handler.js.map +1 -0
- package/lib/resources/index.d.ts +20 -0
- package/lib/resources/index.d.ts.map +1 -0
- package/lib/resources/index.js +36 -0
- package/lib/resources/index.js.map +1 -0
- package/lib/resources/services/element-types-provider.d.ts +65 -0
- package/lib/resources/services/element-types-provider.d.ts.map +1 -0
- package/lib/resources/services/element-types-provider.js +81 -0
- package/lib/resources/services/element-types-provider.js.map +1 -0
- package/lib/resources/services/mcp-model-serializer.d.ts +78 -0
- package/lib/resources/services/mcp-model-serializer.d.ts.map +1 -0
- package/lib/resources/services/mcp-model-serializer.js +188 -0
- package/lib/resources/services/mcp-model-serializer.js.map +1 -0
- package/lib/server/glsp-mcp-server.d.ts +82 -0
- package/lib/server/glsp-mcp-server.d.ts.map +1 -0
- package/lib/server/glsp-mcp-server.js +140 -0
- package/lib/server/glsp-mcp-server.js.map +1 -0
- package/lib/server/index.d.ts +37 -0
- package/lib/server/index.d.ts.map +1 -0
- package/lib/server/index.js +57 -0
- package/lib/server/index.js.map +1 -0
- package/lib/server/lru-event-store.d.ts +53 -0
- package/lib/server/lru-event-store.d.ts.map +1 -0
- package/lib/server/lru-event-store.js +100 -0
- package/lib/server/lru-event-store.js.map +1 -0
- package/lib/server/mcp-diagram-handler-dispatcher.d.ts +144 -0
- package/lib/server/mcp-diagram-handler-dispatcher.d.ts.map +1 -0
- package/lib/server/mcp-diagram-handler-dispatcher.js +382 -0
- package/lib/server/mcp-diagram-handler-dispatcher.js.map +1 -0
- package/lib/server/mcp-diagram-module.d.ts +123 -0
- package/lib/server/mcp-diagram-module.d.ts.map +1 -0
- package/lib/server/mcp-diagram-module.js +186 -0
- package/lib/server/mcp-diagram-module.js.map +1 -0
- package/lib/server/mcp-diagram-prompt-handler-registry.d.ts +33 -0
- package/lib/server/mcp-diagram-prompt-handler-registry.d.ts.map +1 -0
- package/lib/server/mcp-diagram-prompt-handler-registry.js +76 -0
- package/lib/server/mcp-diagram-prompt-handler-registry.js.map +1 -0
- package/lib/server/mcp-diagram-resource-handler-registry.d.ts +35 -0
- package/lib/server/mcp-diagram-resource-handler-registry.d.ts.map +1 -0
- package/lib/server/mcp-diagram-resource-handler-registry.js +94 -0
- package/lib/server/mcp-diagram-resource-handler-registry.js.map +1 -0
- package/lib/server/mcp-diagram-tool-handler-registry.d.ts +57 -0
- package/lib/server/mcp-diagram-tool-handler-registry.d.ts.map +1 -0
- package/lib/server/mcp-diagram-tool-handler-registry.js +111 -0
- package/lib/server/mcp-diagram-tool-handler-registry.js.map +1 -0
- package/lib/server/mcp-handler-shared.d.ts +142 -0
- package/lib/server/mcp-handler-shared.d.ts.map +1 -0
- package/lib/server/mcp-handler-shared.js +199 -0
- package/lib/server/mcp-handler-shared.js.map +1 -0
- package/lib/server/mcp-http-transport.d.ts +93 -0
- package/lib/server/mcp-http-transport.d.ts.map +1 -0
- package/lib/server/mcp-http-transport.js +350 -0
- package/lib/server/mcp-http-transport.js.map +1 -0
- package/lib/server/mcp-id-alias-service.d.ts +70 -0
- package/lib/server/mcp-id-alias-service.d.ts.map +1 -0
- package/lib/server/mcp-id-alias-service.js +85 -0
- package/lib/server/mcp-id-alias-service.js.map +1 -0
- package/lib/server/mcp-input-schemas.d.ts +73 -0
- package/lib/server/mcp-input-schemas.d.ts.map +1 -0
- package/lib/server/mcp-input-schemas.js +67 -0
- package/lib/server/mcp-input-schemas.js.map +1 -0
- package/lib/server/mcp-label-provider.d.ts +45 -0
- package/lib/server/mcp-label-provider.d.ts.map +1 -0
- package/lib/server/mcp-label-provider.js +42 -0
- package/lib/server/mcp-label-provider.js.map +1 -0
- package/lib/server/mcp-log-level-registry.d.ts +54 -0
- package/lib/server/mcp-log-level-registry.d.ts.map +1 -0
- package/lib/server/mcp-log-level-registry.js +80 -0
- package/lib/server/mcp-log-level-registry.js.map +1 -0
- package/lib/server/mcp-logger.d.ts +59 -0
- package/lib/server/mcp-logger.d.ts.map +1 -0
- package/lib/server/mcp-logger.js +104 -0
- package/lib/server/mcp-logger.js.map +1 -0
- package/lib/server/mcp-mime-types.d.ts +28 -0
- package/lib/server/mcp-mime-types.d.ts.map +1 -0
- package/lib/server/mcp-mime-types.js +18 -0
- package/lib/server/mcp-mime-types.js.map +1 -0
- package/lib/server/mcp-options.d.ts +39 -0
- package/lib/server/mcp-options.d.ts.map +1 -0
- package/lib/server/mcp-options.js +53 -0
- package/lib/server/mcp-options.js.map +1 -0
- package/lib/server/mcp-progress-reporter.d.ts +48 -0
- package/lib/server/mcp-progress-reporter.d.ts.map +1 -0
- package/lib/server/mcp-progress-reporter.js +66 -0
- package/lib/server/mcp-progress-reporter.js.map +1 -0
- package/lib/server/mcp-prompt-handler.d.ts +120 -0
- package/lib/server/mcp-prompt-handler.d.ts.map +1 -0
- package/lib/server/mcp-prompt-handler.js +131 -0
- package/lib/server/mcp-prompt-handler.js.map +1 -0
- package/lib/server/mcp-request-context.d.ts +37 -0
- package/lib/server/mcp-request-context.d.ts.map +1 -0
- package/lib/server/mcp-request-context.js +37 -0
- package/lib/server/mcp-request-context.js.map +1 -0
- package/lib/server/mcp-resource-handler.d.ts +212 -0
- package/lib/server/mcp-resource-handler.d.ts.map +1 -0
- package/lib/server/mcp-resource-handler.js +298 -0
- package/lib/server/mcp-resource-handler.js.map +1 -0
- package/lib/server/mcp-server-launcher.d.ts +143 -0
- package/lib/server/mcp-server-launcher.d.ts.map +1 -0
- package/lib/server/mcp-server-launcher.js +355 -0
- package/lib/server/mcp-server-launcher.js.map +1 -0
- package/lib/server/mcp-server-module.d.ts +143 -0
- package/lib/server/mcp-server-module.d.ts.map +1 -0
- package/lib/server/mcp-server-module.js +249 -0
- package/lib/server/mcp-server-module.js.map +1 -0
- package/lib/server/mcp-session.d.ts +44 -0
- package/lib/server/mcp-session.d.ts.map +1 -0
- package/lib/server/mcp-session.js +18 -0
- package/lib/server/mcp-session.js.map +1 -0
- package/lib/server/mcp-tool-handler.d.ts +259 -0
- package/lib/server/mcp-tool-handler.d.ts.map +1 -0
- package/lib/server/mcp-tool-handler.js +355 -0
- package/lib/server/mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/count-elements-mcp-tool-handler.d.ts +46 -0
- package/lib/tools/handlers/count-elements-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/count-elements-mcp-tool-handler.js +76 -0
- package/lib/tools/handlers/count-elements-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/create-edges-mcp-tool-handler.d.ts +112 -0
- package/lib/tools/handlers/create-edges-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/create-edges-mcp-tool-handler.js +190 -0
- package/lib/tools/handlers/create-edges-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/create-nodes-mcp-tool-handler.d.ts +81 -0
- package/lib/tools/handlers/create-nodes-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/create-nodes-mcp-tool-handler.js +123 -0
- package/lib/tools/handlers/create-nodes-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/delete-elements-mcp-tool-handler.d.ts +52 -0
- package/lib/tools/handlers/delete-elements-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/delete-elements-mcp-tool-handler.js +73 -0
- package/lib/tools/handlers/delete-elements-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/diagram-model-mcp-tool-handler.d.ts +59 -0
- package/lib/tools/handlers/diagram-model-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/diagram-model-mcp-tool-handler.js +78 -0
- package/lib/tools/handlers/diagram-model-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/element-types-mcp-tool-handler.d.ts +97 -0
- package/lib/tools/handlers/element-types-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/element-types-mcp-tool-handler.js +155 -0
- package/lib/tools/handlers/element-types-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/get-selection-mcp-tool-handler.d.ts +43 -0
- package/lib/tools/handlers/get-selection-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/get-selection-mcp-tool-handler.js +68 -0
- package/lib/tools/handlers/get-selection-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/layout-mcp-tool-handler.d.ts +43 -0
- package/lib/tools/handlers/layout-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/layout-mcp-tool-handler.js +71 -0
- package/lib/tools/handlers/layout-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/modify-edges-mcp-tool-handler.d.ts +78 -0
- package/lib/tools/handlers/modify-edges-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/modify-edges-mcp-tool-handler.js +136 -0
- package/lib/tools/handlers/modify-edges-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/modify-nodes-mcp-tool-handler.d.ts +92 -0
- package/lib/tools/handlers/modify-nodes-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/modify-nodes-mcp-tool-handler.js +125 -0
- package/lib/tools/handlers/modify-nodes-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/query-elements-mcp-tool-handler.d.ts +102 -0
- package/lib/tools/handlers/query-elements-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/query-elements-mcp-tool-handler.js +158 -0
- package/lib/tools/handlers/query-elements-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/redo-mcp-tool-handler.d.ts +45 -0
- package/lib/tools/handlers/redo-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/redo-mcp-tool-handler.js +73 -0
- package/lib/tools/handlers/redo-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/save-model-mcp-tool-handler.d.ts +55 -0
- package/lib/tools/handlers/save-model-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/save-model-mcp-tool-handler.js +91 -0
- package/lib/tools/handlers/save-model-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/session-info-mcp-tool-handler.d.ts +65 -0
- package/lib/tools/handlers/session-info-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/session-info-mcp-tool-handler.js +108 -0
- package/lib/tools/handlers/session-info-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/set-selection-mcp-tool-handler.d.ts +60 -0
- package/lib/tools/handlers/set-selection-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/set-selection-mcp-tool-handler.js +103 -0
- package/lib/tools/handlers/set-selection-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/set-view-mcp-tool-handler.d.ts +110 -0
- package/lib/tools/handlers/set-view-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/set-view-mcp-tool-handler.js +142 -0
- package/lib/tools/handlers/set-view-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/undo-mcp-tool-handler.d.ts +45 -0
- package/lib/tools/handlers/undo-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/undo-mcp-tool-handler.js +74 -0
- package/lib/tools/handlers/undo-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/validate-diagram-mcp-tool-handler.d.ts +66 -0
- package/lib/tools/handlers/validate-diagram-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/validate-diagram-mcp-tool-handler.js +0 -0
- package/lib/tools/handlers/validate-diagram-mcp-tool-handler.js.map +1 -0
- package/lib/tools/index.d.ts +34 -0
- package/lib/tools/index.d.ts.map +1 -0
- package/lib/tools/index.js +50 -0
- package/lib/tools/index.js.map +1 -0
- package/lib/util/index.d.ts +18 -0
- package/lib/util/index.d.ts.map +1 -0
- package/lib/util/index.js +34 -0
- package/lib/util/index.js.map +1 -0
- package/lib/util/markdown-util.d.ts +20 -0
- package/lib/util/markdown-util.d.ts.map +1 -0
- package/lib/util/markdown-util.js +45 -0
- package/lib/util/markdown-util.js.map +1 -0
- package/lib/util/mcp-util.d.ts +22 -0
- package/lib/util/mcp-util.d.ts.map +1 -0
- package/lib/util/mcp-util.js +29 -0
- package/lib/util/mcp-util.js.map +1 -0
- package/package.json +63 -0
- package/src/index.ts +24 -0
- package/src/prompts/handlers/describe-diagram-mcp-prompt-handler.ts +89 -0
- package/src/prompts/handlers/suggest-improvements-mcp-prompt-handler.ts +86 -0
- package/src/prompts/index.ts +18 -0
- package/src/resources/handlers/diagram-png-mcp-resource-handler.ts +181 -0
- package/src/resources/handlers/diagram-svg-mcp-resource-handler.ts +89 -0
- package/src/resources/index.ts +20 -0
- package/src/resources/services/element-types-provider.ts +105 -0
- package/src/resources/services/mcp-model-serializer.ts +211 -0
- package/src/server/glsp-mcp-server.spec.ts +73 -0
- package/src/server/glsp-mcp-server.ts +196 -0
- package/src/server/index.ts +42 -0
- package/src/server/lru-event-store.spec.ts +121 -0
- package/src/server/lru-event-store.ts +112 -0
- package/src/server/mcp-diagram-handler-dispatcher.spec.ts +231 -0
- package/src/server/mcp-diagram-handler-dispatcher.ts +459 -0
- package/src/server/mcp-diagram-module.ts +248 -0
- package/src/server/mcp-diagram-prompt-handler-registry.ts +59 -0
- package/src/server/mcp-diagram-resource-handler-registry.ts +73 -0
- package/src/server/mcp-diagram-tool-handler-registry.ts +97 -0
- package/src/server/mcp-handler-shared.spec.ts +53 -0
- package/src/server/mcp-handler-shared.ts +247 -0
- package/src/server/mcp-http-transport-e2e.spec.ts +151 -0
- package/src/server/mcp-http-transport.spec.ts +385 -0
- package/src/server/mcp-http-transport.ts +368 -0
- package/src/server/mcp-id-alias-service.spec.ts +106 -0
- package/src/server/mcp-id-alias-service.ts +104 -0
- package/src/server/mcp-input-schemas.ts +82 -0
- package/src/server/mcp-label-provider.ts +52 -0
- package/src/server/mcp-log-level-registry.spec.ts +75 -0
- package/src/server/mcp-log-level-registry.ts +90 -0
- package/src/server/mcp-logger.spec.ts +227 -0
- package/src/server/mcp-logger.ts +91 -0
- package/src/server/mcp-mime-types.ts +31 -0
- package/src/server/mcp-options.ts +43 -0
- package/src/server/mcp-progress-reporter.spec.ts +93 -0
- package/src/server/mcp-progress-reporter.ts +67 -0
- package/src/server/mcp-prompt-handler.ts +157 -0
- package/src/server/mcp-request-context.ts +39 -0
- package/src/server/mcp-resource-handler.ts +389 -0
- package/src/server/mcp-server-launcher.spec.ts +173 -0
- package/src/server/mcp-server-launcher.ts +369 -0
- package/src/server/mcp-server-module.ts +287 -0
- package/src/server/mcp-session.ts +45 -0
- package/src/server/mcp-tool-handler.spec.ts +182 -0
- package/src/server/mcp-tool-handler.ts +431 -0
- package/src/server/raw-http.spec.ts +59 -0
- package/src/tools/handlers/count-elements-mcp-tool-handler.spec.ts +99 -0
- package/src/tools/handlers/count-elements-mcp-tool-handler.ts +66 -0
- package/src/tools/handlers/create-edges-mcp-tool-handler.spec.ts +196 -0
- package/src/tools/handlers/create-edges-mcp-tool-handler.ts +205 -0
- package/src/tools/handlers/create-nodes-mcp-tool-handler.spec.ts +197 -0
- package/src/tools/handlers/create-nodes-mcp-tool-handler.ts +131 -0
- package/src/tools/handlers/delete-elements-mcp-tool-handler.ts +73 -0
- package/src/tools/handlers/diagram-model-mcp-tool-handler.ts +66 -0
- package/src/tools/handlers/element-types-mcp-tool-handler.ts +151 -0
- package/src/tools/handlers/get-selection-mcp-tool-handler.ts +54 -0
- package/src/tools/handlers/layout-mcp-tool-handler.ts +56 -0
- package/src/tools/handlers/modify-edges-mcp-tool-handler.ts +148 -0
- package/src/tools/handlers/modify-nodes-mcp-tool-handler.ts +140 -0
- package/src/tools/handlers/query-elements-mcp-tool-handler.spec.ts +210 -0
- package/src/tools/handlers/query-elements-mcp-tool-handler.ts +161 -0
- package/src/tools/handlers/redo-mcp-tool-handler.ts +62 -0
- package/src/tools/handlers/save-model-mcp-tool-handler.ts +71 -0
- package/src/tools/handlers/session-info-mcp-tool-handler.spec.ts +152 -0
- package/src/tools/handlers/session-info-mcp-tool-handler.ts +97 -0
- package/src/tools/handlers/set-selection-mcp-tool-handler.spec.ts +118 -0
- package/src/tools/handlers/set-selection-mcp-tool-handler.ts +90 -0
- package/src/tools/handlers/set-view-mcp-tool-handler.ts +162 -0
- package/src/tools/handlers/undo-mcp-tool-handler.ts +61 -0
- package/src/tools/handlers/validate-diagram-mcp-tool-handler.ts +0 -0
- package/src/tools/index.ts +34 -0
- package/src/tools/tool-annotations.spec.ts +141 -0
- package/src/util/index.ts +18 -0
- package/src/util/markdown-util.ts +44 -0
- package/src/util/mcp-util.ts +25 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
*
|
|
8
|
+
* This Source Code may also be made available under the following Secondary
|
|
9
|
+
* Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
* with the GNU Classpath Exception which is available at
|
|
12
|
+
* https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
*
|
|
14
|
+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
********************************************************************************/
|
|
16
|
+
|
|
17
|
+
import { Logger, NullLogger } from '@eclipse-glsp/server';
|
|
18
|
+
import { expect } from 'chai';
|
|
19
|
+
import { Container, ContainerModule } from 'inversify';
|
|
20
|
+
import { McpHttpTransport } from './mcp-http-transport';
|
|
21
|
+
import { McpServerOptions } from './mcp-options';
|
|
22
|
+
import { rawHttpRequest } from './raw-http.spec';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Builds a transport instance with a configurable `McpServerOptions` binding so tests can
|
|
26
|
+
* exercise the SDK-level host allowlist (forwarded via `createMcpExpressApp`) and our own
|
|
27
|
+
* Origin allowlist (installed in `configureExpressApp`).
|
|
28
|
+
*/
|
|
29
|
+
function buildTransport(optionValues: McpServerOptions['values'] = {}): McpHttpTransport {
|
|
30
|
+
const container = new Container();
|
|
31
|
+
container.load(
|
|
32
|
+
new ContainerModule(bind => {
|
|
33
|
+
bind(Logger).toConstantValue(new NullLogger());
|
|
34
|
+
const opts = new McpServerOptions();
|
|
35
|
+
opts.values = optionValues;
|
|
36
|
+
bind(McpServerOptions).toConstantValue(opts);
|
|
37
|
+
bind(McpHttpTransport).toSelf().inSingletonScope();
|
|
38
|
+
})
|
|
39
|
+
);
|
|
40
|
+
return container.get<McpHttpTransport>(McpHttpTransport);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe('McpHttpTransport (startup smoke test)', () => {
|
|
44
|
+
let httpServer: McpHttpTransport | undefined;
|
|
45
|
+
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
// Always tear down so a failing assertion does not leak the listening socket.
|
|
48
|
+
httpServer?.dispose();
|
|
49
|
+
httpServer = undefined;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('binds an HTTP server on a resolvable port and 127.0.0.1 host', async () => {
|
|
53
|
+
httpServer = buildTransport();
|
|
54
|
+
|
|
55
|
+
const endpoint = await httpServer.start({
|
|
56
|
+
port: 0,
|
|
57
|
+
host: '127.0.0.1',
|
|
58
|
+
route: '/mcp',
|
|
59
|
+
name: 'test',
|
|
60
|
+
options: { dataMode: 'tools' }
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
expect(endpoint.url).to.match(/^http:\/\/127\.0\.0\.1:\d+\/mcp$/);
|
|
64
|
+
|
|
65
|
+
const address = await httpServer.getAddress();
|
|
66
|
+
expect(address.address).to.equal('127.0.0.1');
|
|
67
|
+
expect(address.port).to.be.a('number');
|
|
68
|
+
expect(address.port).to.be.greaterThan(0);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('exposes the underlying http.Server and Express app after start', async () => {
|
|
72
|
+
httpServer = buildTransport();
|
|
73
|
+
|
|
74
|
+
await httpServer.start({
|
|
75
|
+
port: 0,
|
|
76
|
+
host: '127.0.0.1',
|
|
77
|
+
route: '/mcp',
|
|
78
|
+
name: 'test',
|
|
79
|
+
options: { dataMode: 'tools' }
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(httpServer.app).to.not.be.undefined;
|
|
83
|
+
expect(httpServer.server).to.not.be.undefined;
|
|
84
|
+
expect(httpServer.server!.listening).to.equal(true);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('closes the underlying http.Server on dispose()', async () => {
|
|
88
|
+
const local = buildTransport();
|
|
89
|
+
|
|
90
|
+
await local.start({
|
|
91
|
+
port: 0,
|
|
92
|
+
host: '127.0.0.1',
|
|
93
|
+
route: '/mcp',
|
|
94
|
+
name: 'test',
|
|
95
|
+
options: { dataMode: 'tools' }
|
|
96
|
+
});
|
|
97
|
+
const underlying = local.server!;
|
|
98
|
+
expect(underlying.listening).to.equal(true);
|
|
99
|
+
|
|
100
|
+
local.dispose();
|
|
101
|
+
|
|
102
|
+
// `Server.close()` is asynchronous — wait for the actual close event.
|
|
103
|
+
await new Promise<void>(resolve => {
|
|
104
|
+
if (!underlying.listening) {
|
|
105
|
+
resolve();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
underlying.once('close', () => resolve());
|
|
109
|
+
});
|
|
110
|
+
expect(underlying.listening).to.equal(false);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('rejects start() with an actionable error when the requested port is already in use', async () => {
|
|
114
|
+
// First transport: bind a random port so we know exactly which port is taken.
|
|
115
|
+
const first = buildTransport();
|
|
116
|
+
await first.start({
|
|
117
|
+
port: 0,
|
|
118
|
+
host: '127.0.0.1',
|
|
119
|
+
route: '/mcp',
|
|
120
|
+
name: 'first',
|
|
121
|
+
options: { dataMode: 'tools' }
|
|
122
|
+
});
|
|
123
|
+
const taken = (await first.getAddress()).port;
|
|
124
|
+
|
|
125
|
+
// Second transport: try to bind the same port → EADDRINUSE.
|
|
126
|
+
const second = buildTransport();
|
|
127
|
+
try {
|
|
128
|
+
await expectStartToReject(second, taken);
|
|
129
|
+
} finally {
|
|
130
|
+
first.dispose();
|
|
131
|
+
second.dispose();
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
async function expectStartToReject(transport: McpHttpTransport, takenPort: number): Promise<void> {
|
|
136
|
+
let error: Error | undefined;
|
|
137
|
+
try {
|
|
138
|
+
await transport.start({
|
|
139
|
+
port: takenPort,
|
|
140
|
+
host: '127.0.0.1',
|
|
141
|
+
route: '/mcp',
|
|
142
|
+
name: 'second',
|
|
143
|
+
options: { dataMode: 'tools' }
|
|
144
|
+
});
|
|
145
|
+
} catch (err: unknown) {
|
|
146
|
+
error = err as Error;
|
|
147
|
+
}
|
|
148
|
+
expect(error, 'expected start() to reject').to.not.equal(undefined);
|
|
149
|
+
// The actionable hint must name the offending host:port AND point at the override path.
|
|
150
|
+
expect(error!.message).to.include(`127.0.0.1:${takenPort}`);
|
|
151
|
+
expect(error!.message).to.include('mcpServer.port');
|
|
152
|
+
expect(error!.message).to.match(/already in use/);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('McpHttpTransport (Origin/Host validation — DNS-rebinding mitigation)', () => {
|
|
157
|
+
let httpServer: McpHttpTransport | undefined;
|
|
158
|
+
|
|
159
|
+
afterEach(() => {
|
|
160
|
+
httpServer?.dispose();
|
|
161
|
+
httpServer = undefined;
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('rejects requests with a Host header outside the allowlist', async () => {
|
|
165
|
+
httpServer = buildTransport({ allowedHosts: ['127.0.0.1', 'localhost'] });
|
|
166
|
+
await httpServer.start({ port: 0, host: '127.0.0.1', route: '/mcp', name: 'test', options: {} });
|
|
167
|
+
const port = (await httpServer.getAddress()).port;
|
|
168
|
+
|
|
169
|
+
const res = await rawHttpRequest(port, 'POST', { Host: 'evil.example' }, {});
|
|
170
|
+
|
|
171
|
+
expect(res.status).to.equal(403);
|
|
172
|
+
expect(res.body).to.match(/Host/);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('accepts requests whose Host header matches the allowlist', async () => {
|
|
176
|
+
httpServer = buildTransport({ allowedHosts: ['127.0.0.1', 'localhost'] });
|
|
177
|
+
await httpServer.start({ port: 0, host: '127.0.0.1', route: '/mcp', name: 'test', options: {} });
|
|
178
|
+
const port = (await httpServer.getAddress()).port;
|
|
179
|
+
|
|
180
|
+
// No `mcp-session-id` header on a non-init body → session-id gate rejects with 400
|
|
181
|
+
// (not the middleware's 403). What matters here is that we got *past* the middleware.
|
|
182
|
+
const res = await rawHttpRequest(port, 'POST', { Host: `127.0.0.1:${port}` }, {});
|
|
183
|
+
|
|
184
|
+
expect(res.status).to.not.equal(403);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('rejects requests whose Origin header is outside an explicit allowlist', async () => {
|
|
188
|
+
httpServer = buildTransport({
|
|
189
|
+
allowedHosts: ['127.0.0.1', 'localhost'],
|
|
190
|
+
allowedOrigins: ['https://my-frontend.example']
|
|
191
|
+
});
|
|
192
|
+
await httpServer.start({ port: 0, host: '127.0.0.1', route: '/mcp', name: 'test', options: {} });
|
|
193
|
+
const port = (await httpServer.getAddress()).port;
|
|
194
|
+
|
|
195
|
+
const res = await rawHttpRequest(port, 'POST', { Host: '127.0.0.1', Origin: 'https://evil.example' }, {});
|
|
196
|
+
|
|
197
|
+
expect(res.status).to.equal(403);
|
|
198
|
+
expect(res.body).to.match(/Origin/);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('skips Origin checks when allowedOrigins is undefined (desktop-IDE default)', async () => {
|
|
202
|
+
httpServer = buildTransport({ allowedHosts: ['127.0.0.1', 'localhost'] });
|
|
203
|
+
await httpServer.start({ port: 0, host: '127.0.0.1', route: '/mcp', name: 'test', options: {} });
|
|
204
|
+
const port = (await httpServer.getAddress()).port;
|
|
205
|
+
|
|
206
|
+
// With allowedOrigins undefined, ANY Origin (or none) is allowed past the middleware.
|
|
207
|
+
const res = await rawHttpRequest(port, 'POST', { Host: '127.0.0.1', Origin: 'https://anything.example' }, {});
|
|
208
|
+
|
|
209
|
+
expect(res.status).to.not.equal(403);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('McpHttpTransport (session-id validation per MCP Streamable HTTP § Session Management)', () => {
|
|
214
|
+
let httpServer: McpHttpTransport | undefined;
|
|
215
|
+
|
|
216
|
+
afterEach(() => {
|
|
217
|
+
httpServer?.dispose();
|
|
218
|
+
httpServer = undefined;
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
async function startTransport(): Promise<number> {
|
|
222
|
+
httpServer = buildTransport({ allowedHosts: ['127.0.0.1', 'localhost'] });
|
|
223
|
+
await httpServer.start({ port: 0, host: '127.0.0.1', route: '/mcp', name: 'test', options: {} });
|
|
224
|
+
return (await httpServer.getAddress()).port;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
it('rejects a non-initialize POST without an Mcp-Session-Id header with 400 (§ #2)', async () => {
|
|
228
|
+
const port = await startTransport();
|
|
229
|
+
|
|
230
|
+
const res = await rawHttpRequest(port, 'POST', {}, { jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} });
|
|
231
|
+
|
|
232
|
+
expect(res.status).to.equal(400);
|
|
233
|
+
const payload = JSON.parse(res.body);
|
|
234
|
+
expect(payload.jsonrpc).to.equal('2.0');
|
|
235
|
+
// eslint-disable-next-line no-null/no-null -- JSON-RPC 2.0 § 5 mandates `null` for unattributable error responses.
|
|
236
|
+
expect(payload.id).to.equal(null);
|
|
237
|
+
expect(payload.error.code).to.equal(-32000);
|
|
238
|
+
expect(payload.error.message).to.match(/No valid session ID/);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('rejects a POST with an unknown Mcp-Session-Id with 404 (§ #3)', async () => {
|
|
242
|
+
const port = await startTransport();
|
|
243
|
+
|
|
244
|
+
const res = await rawHttpRequest(
|
|
245
|
+
port,
|
|
246
|
+
'POST',
|
|
247
|
+
{ 'mcp-session-id': 'no-such-session' },
|
|
248
|
+
{ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} }
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
expect(res.status).to.equal(404);
|
|
252
|
+
const payload = JSON.parse(res.body);
|
|
253
|
+
expect(payload.jsonrpc).to.equal('2.0');
|
|
254
|
+
// eslint-disable-next-line no-null/no-null -- JSON-RPC 2.0 § 5 mandates `null` for unattributable error responses.
|
|
255
|
+
expect(payload.id).to.equal(null);
|
|
256
|
+
expect(payload.error.code).to.equal(-32001);
|
|
257
|
+
expect(payload.error.message).to.match(/Session not found/i);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it('rejects an initialize POST that carries an unknown Mcp-Session-Id with 404 (§ #3 — must not silently mint)', async () => {
|
|
261
|
+
const port = await startTransport();
|
|
262
|
+
|
|
263
|
+
const initBody = {
|
|
264
|
+
jsonrpc: '2.0',
|
|
265
|
+
id: 1,
|
|
266
|
+
method: 'initialize',
|
|
267
|
+
params: {
|
|
268
|
+
protocolVersion: '2025-06-18',
|
|
269
|
+
capabilities: {},
|
|
270
|
+
clientInfo: { name: 'test', version: '0.0.1' }
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const res = await rawHttpRequest(port, 'POST', { 'mcp-session-id': 'stale-session' }, initBody);
|
|
275
|
+
|
|
276
|
+
expect(res.status).to.equal(404);
|
|
277
|
+
const payload = JSON.parse(res.body);
|
|
278
|
+
expect(payload.error.code).to.equal(-32001);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('rejects a GET (SSE stream) with an unknown Mcp-Session-Id with the JSON-RPC envelope', async () => {
|
|
282
|
+
const port = await startTransport();
|
|
283
|
+
|
|
284
|
+
const res = await rawHttpRequest(port, 'GET', { 'mcp-session-id': 'no-such-session' });
|
|
285
|
+
|
|
286
|
+
expect(res.status).to.equal(404);
|
|
287
|
+
const payload = JSON.parse(res.body);
|
|
288
|
+
expect(payload.error.code).to.equal(-32001);
|
|
289
|
+
// eslint-disable-next-line no-null/no-null -- JSON-RPC 2.0 § 5 mandates `null` for unattributable error responses.
|
|
290
|
+
expect(payload.id).to.equal(null);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('rejects a DELETE without an Mcp-Session-Id header with the JSON-RPC envelope', async () => {
|
|
294
|
+
const port = await startTransport();
|
|
295
|
+
|
|
296
|
+
const res = await rawHttpRequest(port, 'DELETE', {});
|
|
297
|
+
|
|
298
|
+
expect(res.status).to.equal(400);
|
|
299
|
+
const payload = JSON.parse(res.body);
|
|
300
|
+
expect(payload.error.code).to.equal(-32000);
|
|
301
|
+
// eslint-disable-next-line no-null/no-null -- JSON-RPC 2.0 § 5 mandates `null` for unattributable error responses.
|
|
302
|
+
expect(payload.id).to.equal(null);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// Happy path (initialize POST without session id ⇒ new session) is exercised end-to-end
|
|
306
|
+
// by `mcp-http-transport-e2e.spec.ts` against a real SDK client; not duplicated here
|
|
307
|
+
// because asserting it inline requires wiring up an `McpServer` to actually respond.
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
describe('McpHttpTransport (MCP-Protocol-Version header validation)', () => {
|
|
311
|
+
let httpServer: McpHttpTransport | undefined;
|
|
312
|
+
|
|
313
|
+
afterEach(() => {
|
|
314
|
+
httpServer?.dispose();
|
|
315
|
+
httpServer = undefined;
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
async function startTransport(): Promise<number> {
|
|
319
|
+
httpServer = buildTransport({ allowedHosts: ['127.0.0.1', 'localhost'] });
|
|
320
|
+
await httpServer.start({ port: 0, host: '127.0.0.1', route: '/mcp', name: 'test', options: {} });
|
|
321
|
+
return (await httpServer.getAddress()).port;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
it('rejects a non-initialize POST whose MCP-Protocol-Version is unsupported with HTTP 400', async () => {
|
|
325
|
+
const port = await startTransport();
|
|
326
|
+
|
|
327
|
+
const res = await rawHttpRequest(
|
|
328
|
+
port,
|
|
329
|
+
'POST',
|
|
330
|
+
{ 'mcp-session-id': 'doesnt-matter', 'mcp-protocol-version': '1999-01-01' },
|
|
331
|
+
{ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} }
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
expect(res.status).to.equal(400);
|
|
335
|
+
const payload = JSON.parse(res.body);
|
|
336
|
+
expect(payload.jsonrpc).to.equal('2.0');
|
|
337
|
+
// eslint-disable-next-line no-null/no-null -- JSON-RPC 2.0 § 5 mandates `null` for unattributable error responses.
|
|
338
|
+
expect(payload.id).to.equal(null);
|
|
339
|
+
expect(payload.error.code).to.equal(-32000);
|
|
340
|
+
expect(payload.error.message).to.match(/Unsupported MCP-Protocol-Version/);
|
|
341
|
+
expect(payload.error.message).to.match(/1999-01-01/);
|
|
342
|
+
expect(payload.error.message).to.match(/Supported versions/);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('rejects a GET whose MCP-Protocol-Version is unsupported with HTTP 400 (header validated before session lookup)', async () => {
|
|
346
|
+
const port = await startTransport();
|
|
347
|
+
|
|
348
|
+
const res = await rawHttpRequest(port, 'GET', { 'mcp-session-id': 'any', 'mcp-protocol-version': 'bogus' });
|
|
349
|
+
|
|
350
|
+
expect(res.status).to.equal(400);
|
|
351
|
+
const payload = JSON.parse(res.body);
|
|
352
|
+
expect(payload.error.message).to.match(/Unsupported MCP-Protocol-Version/);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('passes a non-initialize POST through when the MCP-Protocol-Version header is absent (spec defaults to 2025-03-26)', async () => {
|
|
356
|
+
// Without the header, the protocol-version middleware must let the request through to
|
|
357
|
+
// the next layer (which then enforces session-id rules). Asserting we hit the 400
|
|
358
|
+
// session-id error — not the 400 protocol-version error — proves the middleware
|
|
359
|
+
// didn't short-circuit.
|
|
360
|
+
const port = await startTransport();
|
|
361
|
+
|
|
362
|
+
const res = await rawHttpRequest(port, 'POST', {}, { jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} });
|
|
363
|
+
|
|
364
|
+
expect(res.status).to.equal(400);
|
|
365
|
+
const payload = JSON.parse(res.body);
|
|
366
|
+
expect(payload.error.message).to.match(/No valid session ID/);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('passes a non-initialize POST through when the MCP-Protocol-Version is one of the supported versions', async () => {
|
|
370
|
+
// Header is supported → middleware passes → we hit the 400 session-id check, not the
|
|
371
|
+
// 400 protocol-version check.
|
|
372
|
+
const port = await startTransport();
|
|
373
|
+
|
|
374
|
+
const res = await rawHttpRequest(
|
|
375
|
+
port,
|
|
376
|
+
'POST',
|
|
377
|
+
{ 'mcp-protocol-version': '2025-06-18' },
|
|
378
|
+
{ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} }
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
expect(res.status).to.equal(400);
|
|
382
|
+
const payload = JSON.parse(res.body);
|
|
383
|
+
expect(payload.error.message).to.match(/No valid session ID/);
|
|
384
|
+
});
|
|
385
|
+
});
|