@eclipse-glsp/server-mcp 2.7.0-next.10
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 +66 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +82 -0
- package/lib/index.js.map +1 -0
- package/lib/modules/mcp-diagram-module.d.ts +123 -0
- package/lib/modules/mcp-diagram-module.d.ts.map +1 -0
- package/lib/modules/mcp-diagram-module.js +202 -0
- package/lib/modules/mcp-diagram-module.js.map +1 -0
- package/lib/modules/mcp-server-module.d.ts +143 -0
- package/lib/modules/mcp-server-module.d.ts.map +1 -0
- package/lib/modules/mcp-server-module.js +251 -0
- package/lib/modules/mcp-server-module.js.map +1 -0
- package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.d.ts +44 -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 +102 -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 +44 -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 +99 -0
- package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.js.map +1 -0
- package/lib/resources/handlers/diagram-png-mcp-resource-handler.d.ts +84 -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 +177 -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 +55 -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 +99 -0
- package/lib/resources/handlers/diagram-svg-mcp-resource-handler.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/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-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-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 +47 -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 +77 -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 +113 -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 +191 -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 +82 -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 +124 -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 +53 -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 +74 -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 +60 -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 +79 -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 +98 -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 +156 -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 +44 -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 +70 -0
- package/lib/tools/handlers/get-selection-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/layout-mcp-tool-handler.d.ts +44 -0
- package/lib/tools/handlers/layout-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/layout-mcp-tool-handler.js +72 -0
- package/lib/tools/handlers/layout-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/modify-edges-mcp-tool-handler.d.ts +79 -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 +138 -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 +93 -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 +127 -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 +103 -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 +160 -0
- package/lib/tools/handlers/query-elements-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/redo-mcp-tool-handler.d.ts +46 -0
- package/lib/tools/handlers/redo-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/redo-mcp-tool-handler.js +75 -0
- package/lib/tools/handlers/redo-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/save-model-mcp-tool-handler.d.ts +57 -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 +93 -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 +66 -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 +109 -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 +61 -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 +104 -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 +111 -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 +144 -0
- package/lib/tools/handlers/set-view-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/undo-mcp-tool-handler.d.ts +46 -0
- package/lib/tools/handlers/undo-mcp-tool-handler.d.ts.map +1 -0
- package/lib/tools/handlers/undo-mcp-tool-handler.js +76 -0
- package/lib/tools/handlers/undo-mcp-tool-handler.js.map +1 -0
- package/lib/tools/handlers/validate-diagram-mcp-tool-handler.d.ts +67 -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/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 +65 -0
- package/src/modules/mcp-diagram-module.ts +247 -0
- package/src/modules/mcp-server-module.ts +289 -0
- package/src/prompts/handlers/describe-diagram-mcp-prompt-handler.ts +88 -0
- package/src/prompts/handlers/suggest-improvements-mcp-prompt-handler.ts +85 -0
- package/src/resources/handlers/diagram-png-mcp-resource-handler.ts +177 -0
- package/src/resources/handlers/diagram-svg-mcp-resource-handler.ts +85 -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/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-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-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 +101 -0
- package/src/tools/handlers/count-elements-mcp-tool-handler.ts +68 -0
- package/src/tools/handlers/create-edges-mcp-tool-handler.spec.ts +198 -0
- package/src/tools/handlers/create-edges-mcp-tool-handler.ts +200 -0
- package/src/tools/handlers/create-nodes-mcp-tool-handler.spec.ts +199 -0
- package/src/tools/handlers/create-nodes-mcp-tool-handler.ts +126 -0
- package/src/tools/handlers/delete-elements-mcp-tool-handler.ts +69 -0
- package/src/tools/handlers/diagram-model-mcp-tool-handler.ts +68 -0
- package/src/tools/handlers/element-types-mcp-tool-handler.ts +152 -0
- package/src/tools/handlers/get-selection-mcp-tool-handler.ts +56 -0
- package/src/tools/handlers/layout-mcp-tool-handler.ts +58 -0
- package/src/tools/handlers/modify-edges-mcp-tool-handler.ts +142 -0
- package/src/tools/handlers/modify-nodes-mcp-tool-handler.ts +134 -0
- package/src/tools/handlers/query-elements-mcp-tool-handler.spec.ts +212 -0
- package/src/tools/handlers/query-elements-mcp-tool-handler.ts +157 -0
- package/src/tools/handlers/redo-mcp-tool-handler.ts +64 -0
- package/src/tools/handlers/save-model-mcp-tool-handler.ts +74 -0
- package/src/tools/handlers/session-info-mcp-tool-handler.spec.ts +152 -0
- package/src/tools/handlers/session-info-mcp-tool-handler.ts +98 -0
- package/src/tools/handlers/set-selection-mcp-tool-handler.spec.ts +120 -0
- package/src/tools/handlers/set-selection-mcp-tool-handler.ts +92 -0
- package/src/tools/handlers/set-view-mcp-tool-handler.ts +156 -0
- package/src/tools/handlers/undo-mcp-tool-handler.ts +63 -0
- package/src/tools/handlers/validate-diagram-mcp-tool-handler.ts +0 -0
- package/src/tools/tool-annotations.spec.ts +141 -0
- package/src/util/markdown-util.ts +44 -0
- package/src/util/mcp-util.ts +25 -0
|
@@ -0,0 +1,88 @@
|
|
|
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 { ClientSessionManager } from '@eclipse-glsp/server';
|
|
18
|
+
import { inject, injectable } from 'inversify';
|
|
19
|
+
import * as z from 'zod/v4';
|
|
20
|
+
import { McpPromptResult, resolveActiveSessionId } from '../../server/mcp-handler-shared';
|
|
21
|
+
import { AbstractMcpPromptHandler } from '../../server/mcp-prompt-handler';
|
|
22
|
+
import { CountElementsMcpToolHandler } from '../../tools/handlers/count-elements-mcp-tool-handler';
|
|
23
|
+
import { DiagramModelMcpToolHandler } from '../../tools/handlers/diagram-model-mcp-tool-handler';
|
|
24
|
+
import { ElementTypesMcpToolHandler } from '../../tools/handlers/element-types-mcp-tool-handler';
|
|
25
|
+
import { QueryElementsMcpToolHandler } from '../../tools/handlers/query-elements-mcp-tool-handler';
|
|
26
|
+
import { SetSelectionMcpToolHandler } from '../../tools/handlers/set-selection-mcp-tool-handler';
|
|
27
|
+
import { SetViewMcpToolHandler } from '../../tools/handlers/set-view-mcp-tool-handler';
|
|
28
|
+
|
|
29
|
+
export const DescribeDiagramArgsSchema = z.object({
|
|
30
|
+
sessionId: z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe('GLSP client session id (open diagram). Defaults to the only open session; required when multiple are open.')
|
|
34
|
+
});
|
|
35
|
+
export type DescribeDiagramArgs = z.infer<typeof DescribeDiagramArgsSchema>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Prompt template that instructs the agent to produce a structured description of a diagram.
|
|
39
|
+
* Pre-baked starting point invokable from the MCP-client UI; the agent then orchestrates the
|
|
40
|
+
* necessary tool calls on its own.
|
|
41
|
+
*
|
|
42
|
+
* Server-scope on purpose — the prompt itself has no per-session state, so we avoid forcing
|
|
43
|
+
* the user to type a sessionId in the common single-diagram case.
|
|
44
|
+
*/
|
|
45
|
+
@injectable()
|
|
46
|
+
export class DescribeDiagramMcpPromptHandler extends AbstractMcpPromptHandler<DescribeDiagramArgs> {
|
|
47
|
+
static readonly NAME = 'describe-diagram';
|
|
48
|
+
readonly name = DescribeDiagramMcpPromptHandler.NAME;
|
|
49
|
+
override readonly title = 'Describe Diagram';
|
|
50
|
+
readonly description =
|
|
51
|
+
'Produce a structured, skim-friendly description of an open diagram. ' +
|
|
52
|
+
'The agent picks the right tools to gather data (overview, element-type breakdown, structure, notable elements) ' +
|
|
53
|
+
'and writes the description in its own words. ' +
|
|
54
|
+
'Use this as a starting point when the user asks "what does this diagram show?" or wants a documentation-style summary. ' +
|
|
55
|
+
'`sessionId` is optional — defaults to the only open session.';
|
|
56
|
+
readonly argsSchema = DescribeDiagramArgsSchema;
|
|
57
|
+
|
|
58
|
+
@inject(ClientSessionManager) protected clientSessionManager: ClientSessionManager;
|
|
59
|
+
|
|
60
|
+
override referencedToolNames(): string[] {
|
|
61
|
+
return [
|
|
62
|
+
CountElementsMcpToolHandler.NAME,
|
|
63
|
+
ElementTypesMcpToolHandler.NAME,
|
|
64
|
+
DiagramModelMcpToolHandler.NAME,
|
|
65
|
+
QueryElementsMcpToolHandler.NAME,
|
|
66
|
+
SetSelectionMcpToolHandler.NAME,
|
|
67
|
+
SetViewMcpToolHandler.NAME
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
protected createResult(args: DescribeDiagramArgs): McpPromptResult {
|
|
72
|
+
const sessionId = resolveActiveSessionId(this.clientSessionManager, args.sessionId);
|
|
73
|
+
const text =
|
|
74
|
+
`Describe the diagram for session \`${sessionId}\`. Include:\n\n` +
|
|
75
|
+
`1. **Overview** — diagram type and total element count (use \`${CountElementsMcpToolHandler.NAME}\`).\n` +
|
|
76
|
+
`2. **Element-type breakdown** — what kinds of elements are present and how many of each ` +
|
|
77
|
+
`(use \`${ElementTypesMcpToolHandler.NAME}\` and \`${CountElementsMcpToolHandler.NAME}\`).\n` +
|
|
78
|
+
`3. **Structure** — load the model with \`${DiagramModelMcpToolHandler.NAME}\` and summarize the ` +
|
|
79
|
+
`hierarchy and major connections.\n` +
|
|
80
|
+
`4. **Notable elements** — call out anything that stands out (unconnected nodes, deeply ` +
|
|
81
|
+
`nested groups, missing labels). Use \`${QueryElementsMcpToolHandler.NAME}\` to locate specific cases.\n\n` +
|
|
82
|
+
`Keep the description concise and skim-friendly. ` +
|
|
83
|
+
`When mentioning an element, prefer its label or type, with the alias appended in parens — e.g. ` +
|
|
84
|
+
`"the 'Brew' task (#7)" or "the decision node (#9)" — never the bare alias alone, since aliases mean nothing to the user. ` +
|
|
85
|
+
`Use \`${SetSelectionMcpToolHandler.NAME}\` or \`${SetViewMcpToolHandler.NAME} → 'center-on-elements'\` to draw the user's attention.`;
|
|
86
|
+
return { messages: [{ role: 'user', content: { type: 'text', text } }] };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
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 { ClientSessionManager } from '@eclipse-glsp/server';
|
|
18
|
+
import { inject, injectable } from 'inversify';
|
|
19
|
+
import * as z from 'zod/v4';
|
|
20
|
+
import { McpPromptResult, resolveActiveSessionId } from '../../server/mcp-handler-shared';
|
|
21
|
+
import { AbstractMcpPromptHandler } from '../../server/mcp-prompt-handler';
|
|
22
|
+
import { DiagramModelMcpToolHandler } from '../../tools/handlers/diagram-model-mcp-tool-handler';
|
|
23
|
+
import { QueryElementsMcpToolHandler } from '../../tools/handlers/query-elements-mcp-tool-handler';
|
|
24
|
+
import { SetSelectionMcpToolHandler } from '../../tools/handlers/set-selection-mcp-tool-handler';
|
|
25
|
+
import { ValidateDiagramMcpToolHandler } from '../../tools/handlers/validate-diagram-mcp-tool-handler';
|
|
26
|
+
|
|
27
|
+
export const SuggestImprovementsArgsSchema = z.object({
|
|
28
|
+
sessionId: z
|
|
29
|
+
.string()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('GLSP client session id (open diagram). Defaults to the only open session; required when multiple are open.')
|
|
32
|
+
});
|
|
33
|
+
export type SuggestImprovementsArgs = z.infer<typeof SuggestImprovementsArgsSchema>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Prompt template that asks the agent to review the diagram and propose concrete improvements
|
|
37
|
+
* (validation issues, structural smells, missing labels, etc.). The agent orchestrates the
|
|
38
|
+
* tool calls; this prompt only frames the task.
|
|
39
|
+
*
|
|
40
|
+
* Server-scope on purpose — the prompt itself has no per-session state, so we avoid forcing
|
|
41
|
+
* the user to type a sessionId in the common single-diagram case.
|
|
42
|
+
*/
|
|
43
|
+
@injectable()
|
|
44
|
+
export class SuggestImprovementsMcpPromptHandler extends AbstractMcpPromptHandler<SuggestImprovementsArgs> {
|
|
45
|
+
static readonly NAME = 'suggest-improvements';
|
|
46
|
+
readonly name = SuggestImprovementsMcpPromptHandler.NAME;
|
|
47
|
+
override readonly title = 'Suggest Diagram Improvements';
|
|
48
|
+
readonly description =
|
|
49
|
+
'Review an open diagram and propose concrete improvements grouped by severity ' +
|
|
50
|
+
'(must-fix vs. nice-to-have). The agent runs validation, checks connectivity, looks for unclear labels, ' +
|
|
51
|
+
'and flags structural inconsistencies, then names the specific element ids for each suggestion so the user ' +
|
|
52
|
+
'can act on them. Read-only by intent — the prompt instructs the agent not to modify the diagram, only propose. ' +
|
|
53
|
+
'`sessionId` is optional — defaults to the only open session.';
|
|
54
|
+
readonly argsSchema = SuggestImprovementsArgsSchema;
|
|
55
|
+
|
|
56
|
+
@inject(ClientSessionManager) protected clientSessionManager: ClientSessionManager;
|
|
57
|
+
|
|
58
|
+
override referencedToolNames(): string[] {
|
|
59
|
+
return [
|
|
60
|
+
ValidateDiagramMcpToolHandler.NAME,
|
|
61
|
+
DiagramModelMcpToolHandler.NAME,
|
|
62
|
+
QueryElementsMcpToolHandler.NAME,
|
|
63
|
+
SetSelectionMcpToolHandler.NAME
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
protected createResult(args: SuggestImprovementsArgs): McpPromptResult {
|
|
68
|
+
const sessionId = resolveActiveSessionId(this.clientSessionManager, args.sessionId);
|
|
69
|
+
const text =
|
|
70
|
+
`Review the diagram for session \`${sessionId}\` and propose concrete improvements. Focus on:\n\n` +
|
|
71
|
+
`1. **Validation issues** — run \`${ValidateDiagramMcpToolHandler.NAME}\` and surface any markers.\n` +
|
|
72
|
+
`2. **Connectivity** — load the model (\`${DiagramModelMcpToolHandler.NAME}\`) and flag unconnected ` +
|
|
73
|
+
`nodes or orphaned subgraphs.\n` +
|
|
74
|
+
`3. **Labelling** — use \`${QueryElementsMcpToolHandler.NAME}\` to find nodes that lack a meaningful ` +
|
|
75
|
+
`label, and edges with missing or unclear text.\n` +
|
|
76
|
+
`4. **Structure** — call out elements whose type or placement looks inconsistent with ` +
|
|
77
|
+
`the rest of the diagram.\n\n` +
|
|
78
|
+
`Group findings by severity (must-fix vs. nice-to-have). ` +
|
|
79
|
+
`When naming elements, prefer their label or type with the alias in parens — e.g. ` +
|
|
80
|
+
`"the 'Brew' task (#7)" or "the decision node (#9)" — never the bare alias alone, since aliases mean nothing to the user. ` +
|
|
81
|
+
`Point at each suggestion via \`${SetSelectionMcpToolHandler.NAME}\` so the user can navigate. ` +
|
|
82
|
+
`Do not modify the diagram — only propose.`;
|
|
83
|
+
return { messages: [{ role: 'user', content: { type: 'text', text } }] };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
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 { ClientActionKinds, isGBoundsAware, RequestExportAction } from '@eclipse-glsp/server';
|
|
18
|
+
import { Role } from '@modelcontextprotocol/sdk/types.js';
|
|
19
|
+
import { inject, injectable } from 'inversify';
|
|
20
|
+
import * as z from 'zod/v4';
|
|
21
|
+
import { McpResourceContent, McpToolError } from '../../server/mcp-handler-shared';
|
|
22
|
+
import { McpDiagramScopedInputSchema } from '../../server/mcp-input-schemas';
|
|
23
|
+
import { McpMimeType } from '../../server/mcp-mime-types';
|
|
24
|
+
import { McpProgressReporter } from '../../server/mcp-progress-reporter';
|
|
25
|
+
import { AbstractMcpDiagramResourceHandler, McpResourceUri } from '../../server/mcp-resource-handler';
|
|
26
|
+
|
|
27
|
+
export const DiagramPngInputSchema = McpDiagramScopedInputSchema.extend({
|
|
28
|
+
scale: z
|
|
29
|
+
.number()
|
|
30
|
+
.min(0.1)
|
|
31
|
+
.max(4)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe(
|
|
34
|
+
"Multiplier applied to the diagram's natural extent (range 0.1..4). Use values >1 for " +
|
|
35
|
+
'sharper-than-default renders, <1 for thumbnails. Ignored when `width` or `height` is supplied.'
|
|
36
|
+
),
|
|
37
|
+
width: z
|
|
38
|
+
.number()
|
|
39
|
+
.int()
|
|
40
|
+
.min(1)
|
|
41
|
+
.max(8192)
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('Override the rendered width in pixels. When given alone, the height is derived from the diagram aspect ratio.'),
|
|
44
|
+
height: z
|
|
45
|
+
.number()
|
|
46
|
+
.int()
|
|
47
|
+
.min(1)
|
|
48
|
+
.max(8192)
|
|
49
|
+
.optional()
|
|
50
|
+
.describe('Override the rendered height in pixels. When given alone, the width is derived from the diagram aspect ratio.'),
|
|
51
|
+
timeoutMs: z
|
|
52
|
+
.number()
|
|
53
|
+
.int()
|
|
54
|
+
.min(100)
|
|
55
|
+
.max(60000)
|
|
56
|
+
.optional()
|
|
57
|
+
.describe('Override the default render timeout in milliseconds (100–60000). Useful for very large diagrams.')
|
|
58
|
+
});
|
|
59
|
+
export type DiagramPngInput = z.infer<typeof DiagramPngInputSchema>;
|
|
60
|
+
|
|
61
|
+
/** Rendering lives on the client — `RequestExportAction('png')` routes to the registered PNG exporter, which returns base64 via `ExportResultAction`. */
|
|
62
|
+
@injectable()
|
|
63
|
+
export class DiagramPngMcpResourceHandler extends AbstractMcpDiagramResourceHandler<DiagramPngInput> {
|
|
64
|
+
/** Default timeout (in ms) used when the call doesn't override `timeoutMs`. Override via subclass + rebind. */
|
|
65
|
+
protected readonly defaultTimeoutMs: number = 5000;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Default `scale` multiplier when the caller doesn't pin `width`/`height`/`scale`. `1` means
|
|
69
|
+
* "render at the diagram's natural extent" — sharp because the client rasterises the SVG
|
|
70
|
+
* at the requested size. Adopters override (e.g. to `2` for a high-DPI deployment) via
|
|
71
|
+
* subclass + rebind.
|
|
72
|
+
*/
|
|
73
|
+
protected readonly defaultScale: number = 1;
|
|
74
|
+
|
|
75
|
+
static readonly NAME = 'diagram-png';
|
|
76
|
+
readonly name = DiagramPngMcpResourceHandler.NAME;
|
|
77
|
+
override readonly title = 'Diagram Model PNG';
|
|
78
|
+
readonly description =
|
|
79
|
+
'Render the session diagram as a base64-encoded PNG screenshot of its current visible state. ' +
|
|
80
|
+
'Includes all nodes, edges, and their styling — useful when a visual answer would help the agent ' +
|
|
81
|
+
'(layout reasoning, confirming a recently-created element looks right, sharing the diagram with the user). ' +
|
|
82
|
+
"Defaults to a sharp render at the diagram's natural extent; pass `scale` to multiply, " +
|
|
83
|
+
'or `width`/`height` to pin specific dimensions. ' +
|
|
84
|
+
'Requires a connected frontend client to perform the render and is subject to a timeout if no response arrives. ' +
|
|
85
|
+
'For a structured-text view of the model use `diagram-model` instead; for vector output use `diagram-svg`.';
|
|
86
|
+
readonly mimeType: McpMimeType = 'image/png';
|
|
87
|
+
readonly uri: McpResourceUri = { template: 'glsp://diagrams/{sessionId}/png' };
|
|
88
|
+
/** Both the user (visual artifact) and the assistant (visual reasoning) consume the rendered diagram. */
|
|
89
|
+
override readonly audience: Role[] = ['user', 'assistant'];
|
|
90
|
+
/** Useful when relevant, but not always-relevant — clients may skip when text-only reasoning suffices. */
|
|
91
|
+
override readonly priority = 0.6;
|
|
92
|
+
// `lastModified` intentionally omitted: we have no cheap, accurate freshness signal for the
|
|
93
|
+
// rendered PNG (the model state doesn't track a "rendered at" timestamp), and a stale value
|
|
94
|
+
// would mislead clients.
|
|
95
|
+
override readonly toolAlternativeInputSchema = DiagramPngInputSchema;
|
|
96
|
+
|
|
97
|
+
@inject(McpProgressReporter) protected progress: McpProgressReporter;
|
|
98
|
+
|
|
99
|
+
@inject(ClientActionKinds) protected clientActionKinds: Set<string>;
|
|
100
|
+
|
|
101
|
+
/** Skip-bind when the GLSP client doesn't speak `RequestExportAction` — every read would otherwise time out. */
|
|
102
|
+
override canRegister(): boolean {
|
|
103
|
+
return this.clientActionKinds.has(RequestExportAction.KIND);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
protected async createResult({ scale, width, height, timeoutMs }: DiagramPngInput): Promise<McpResourceContent> {
|
|
107
|
+
const resolved = this.resolveSize(scale, width, height);
|
|
108
|
+
// Best-effort beat for clients that opted in via `_meta.progressToken`; no-ops otherwise.
|
|
109
|
+
await this.progress.emit({ progress: 0, message: 'Awaiting client-side PNG render…' });
|
|
110
|
+
const response = await this.requestAction(
|
|
111
|
+
RequestExportAction.create('png', { formatOptions: { width: resolved.width, height: resolved.height } }),
|
|
112
|
+
timeoutMs ?? this.defaultTimeoutMs
|
|
113
|
+
);
|
|
114
|
+
// A misbehaving exporter strategy returning text-encoded data here would silently corrupt the blob; fail loudly instead.
|
|
115
|
+
if (response.encoding !== 'base64') {
|
|
116
|
+
throw new McpToolError(`PNG export returned unexpected encoding '${response.encoding}'; expected 'base64'.`);
|
|
117
|
+
}
|
|
118
|
+
return { blob: response.data };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Resolve the final render size with this precedence:
|
|
123
|
+
* - `width` and `height` both given → use as-is.
|
|
124
|
+
* - only one of `width`/`height` given → derive the other from the diagram aspect ratio.
|
|
125
|
+
* - neither dimension given → natural × (`scale` ?? {@link defaultScale}).
|
|
126
|
+
*/
|
|
127
|
+
protected resolveSize(
|
|
128
|
+
scale: number | undefined,
|
|
129
|
+
width: number | undefined,
|
|
130
|
+
height: number | undefined
|
|
131
|
+
): { width: number; height: number } {
|
|
132
|
+
if (width !== undefined && height !== undefined) {
|
|
133
|
+
return { width, height };
|
|
134
|
+
}
|
|
135
|
+
const natural = this.computeNaturalSize();
|
|
136
|
+
if (width !== undefined) {
|
|
137
|
+
return { width, height: Math.max(1, Math.round(width * (natural.height / natural.width))) };
|
|
138
|
+
}
|
|
139
|
+
if (height !== undefined) {
|
|
140
|
+
return { width: Math.max(1, Math.round(height * (natural.width / natural.height))), height };
|
|
141
|
+
}
|
|
142
|
+
const factor = scale ?? this.defaultScale;
|
|
143
|
+
return {
|
|
144
|
+
width: Math.max(1, Math.round(natural.width * factor)),
|
|
145
|
+
height: Math.max(1, Math.round(natural.height * factor))
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Compute the diagram's natural extent as the bounding box of every {@link isGBoundsAware}
|
|
151
|
+
* element with both `position` and `size`. Throws when the model has no positioned elements
|
|
152
|
+
* — a 1×1 PNG of an empty diagram is technically renderable but useless, and surfacing it
|
|
153
|
+
* as a self-correctable error lets the LLM react (e.g. wait for layout, ask the user).
|
|
154
|
+
*/
|
|
155
|
+
protected computeNaturalSize(): { width: number; height: number } {
|
|
156
|
+
let maxX = 0;
|
|
157
|
+
let maxY = 0;
|
|
158
|
+
for (const id of this.modelState.index.allIds()) {
|
|
159
|
+
const element = this.modelState.index.get(id);
|
|
160
|
+
if (!element || !isGBoundsAware(element)) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const position = element.position;
|
|
164
|
+
const size = element.size;
|
|
165
|
+
if (position && size && size.width > 0 && size.height > 0) {
|
|
166
|
+
maxX = Math.max(maxX, position.x + size.width);
|
|
167
|
+
maxY = Math.max(maxY, position.y + size.height);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (maxX <= 0 || maxY <= 0) {
|
|
171
|
+
throw new McpToolError(
|
|
172
|
+
'Diagram has no positioned elements yet — render once after layout completes, or pass `width` / `height` explicitly.'
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
return { width: Math.ceil(maxX), height: Math.ceil(maxY) };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
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 { ClientActionKinds, RequestExportAction } from '@eclipse-glsp/server';
|
|
18
|
+
import { Role } from '@modelcontextprotocol/sdk/types.js';
|
|
19
|
+
import { inject, injectable } from 'inversify';
|
|
20
|
+
import * as z from 'zod/v4';
|
|
21
|
+
import { McpResourceContent, McpToolError } from '../../server/mcp-handler-shared';
|
|
22
|
+
import { McpDiagramScopedInputSchema } from '../../server/mcp-input-schemas';
|
|
23
|
+
import { McpMimeType } from '../../server/mcp-mime-types';
|
|
24
|
+
import { McpProgressReporter } from '../../server/mcp-progress-reporter';
|
|
25
|
+
import { AbstractMcpDiagramResourceHandler, McpResourceUri } from '../../server/mcp-resource-handler';
|
|
26
|
+
|
|
27
|
+
export const DiagramSvgInputSchema = McpDiagramScopedInputSchema.extend({
|
|
28
|
+
timeoutMs: z
|
|
29
|
+
.number()
|
|
30
|
+
.int()
|
|
31
|
+
.min(100)
|
|
32
|
+
.max(60000)
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('Override the default render timeout in milliseconds (100–60000). Useful for very large diagrams.')
|
|
35
|
+
});
|
|
36
|
+
export type DiagramSvgInput = z.infer<typeof DiagramSvgInputSchema>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Vector counterpart of {@link DiagramPngMcpResourceHandler}. Emits the diagram as raw SVG
|
|
40
|
+
* markup (text-encoded). No `width`/`height` knobs because SVG is vector — clients (and
|
|
41
|
+
* downstream rasterisers) scale it freely.
|
|
42
|
+
*/
|
|
43
|
+
@injectable()
|
|
44
|
+
export class DiagramSvgMcpResourceHandler extends AbstractMcpDiagramResourceHandler<DiagramSvgInput> {
|
|
45
|
+
/** Default timeout (in ms) used when the call doesn't override `timeoutMs`. Override via subclass + rebind. */
|
|
46
|
+
protected readonly defaultTimeoutMs: number = 5000;
|
|
47
|
+
|
|
48
|
+
static readonly NAME = 'diagram-svg';
|
|
49
|
+
readonly name = DiagramSvgMcpResourceHandler.NAME;
|
|
50
|
+
override readonly title = 'Diagram Model SVG';
|
|
51
|
+
readonly description =
|
|
52
|
+
'Render the session diagram as SVG markup of its current visible state. ' +
|
|
53
|
+
'Vector format — scales without quality loss, ideal for embedding in documentation, ' +
|
|
54
|
+
'further programmatic processing, or post-export rasterisation at arbitrary resolutions. ' +
|
|
55
|
+
'Requires a connected frontend client to perform the render and is subject to a timeout if no response arrives. ' +
|
|
56
|
+
'Use `diagram-png` instead when you need a ready-to-display raster image; ' +
|
|
57
|
+
'`diagram-model` is the structured-text alternative for content-only reasoning.';
|
|
58
|
+
readonly mimeType: McpMimeType = 'image/svg+xml';
|
|
59
|
+
readonly uri: McpResourceUri = { template: 'glsp://diagrams/{sessionId}/svg' };
|
|
60
|
+
/** Both the user (visual artifact) and the assistant (visual reasoning) consume the rendered diagram. */
|
|
61
|
+
override readonly audience: Role[] = ['user', 'assistant'];
|
|
62
|
+
/** Useful when relevant, but not always-relevant — clients may skip when text-only reasoning suffices. */
|
|
63
|
+
override readonly priority = 0.6;
|
|
64
|
+
override readonly toolAlternativeInputSchema = DiagramSvgInputSchema;
|
|
65
|
+
|
|
66
|
+
@inject(McpProgressReporter) protected progress: McpProgressReporter;
|
|
67
|
+
|
|
68
|
+
@inject(ClientActionKinds) protected clientActionKinds: Set<string>;
|
|
69
|
+
|
|
70
|
+
/** Skip-bind when the GLSP client doesn't speak `RequestExportAction`. */
|
|
71
|
+
override canRegister(): boolean {
|
|
72
|
+
return this.clientActionKinds.has(RequestExportAction.KIND);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
protected async createResult({ timeoutMs }: DiagramSvgInput): Promise<McpResourceContent> {
|
|
76
|
+
// Best-effort beat for clients that opted in via `_meta.progressToken`; no-ops otherwise.
|
|
77
|
+
await this.progress.emit({ progress: 0, message: 'Awaiting client-side SVG render…' });
|
|
78
|
+
const response = await this.requestAction(RequestExportAction.create('svg'), timeoutMs ?? this.defaultTimeoutMs);
|
|
79
|
+
// SVG is text-encoded — base64 encoding here would mean an exporter mis-classified its payload.
|
|
80
|
+
if (response.encoding !== 'text') {
|
|
81
|
+
throw new McpToolError(`SVG export returned unexpected encoding '${response.encoding}'; expected 'text'.`);
|
|
82
|
+
}
|
|
83
|
+
return { text: response.data };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
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 { CreateEdgeOperation, CreateNodeOperation } from '@eclipse-glsp/protocol';
|
|
18
|
+
import {
|
|
19
|
+
CreateEdgeOperationHandler,
|
|
20
|
+
CreateNodeOperationHandler,
|
|
21
|
+
CreateOperationHandler,
|
|
22
|
+
Logger,
|
|
23
|
+
OperationHandlerRegistry
|
|
24
|
+
} from '@eclipse-glsp/server';
|
|
25
|
+
import { inject, injectable } from 'inversify';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A discoverable creatable element type emitted by the `element-types` tool handler. Adopters
|
|
29
|
+
* may add further passthrough fields beyond these — the tool handler's structured output schema
|
|
30
|
+
* is `loose()`.
|
|
31
|
+
*
|
|
32
|
+
* @experimental
|
|
33
|
+
*/
|
|
34
|
+
export interface ElementTypeEntry {
|
|
35
|
+
id: string;
|
|
36
|
+
/** Human-readable display name for the element TYPE (e.g. `Manual Task`). */
|
|
37
|
+
label: string;
|
|
38
|
+
/** Adopter-supplied human-readable description; absent on the default scrape impl. */
|
|
39
|
+
description?: string;
|
|
40
|
+
/** Whether create-* / modify-* tools should pass a `text` arg for this type. Absent ⇒ unknown. */
|
|
41
|
+
acceptsText?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Node + edge types creatable in a given diagram type. */
|
|
45
|
+
export interface ElementTypes {
|
|
46
|
+
nodeTypes: ElementTypeEntry[];
|
|
47
|
+
edgeTypes: ElementTypeEntry[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Per-diagram-type provider of creatable element types. Bound on the diagram (per-GLSP-session)
|
|
52
|
+
* container so each diagram type can supply its own list. Adopters with explicit type info
|
|
53
|
+
* typically rebind to a constant-value provider; the default scrapes
|
|
54
|
+
* {@link OperationHandlerRegistry} for backwards compatibility with adopters that haven't
|
|
55
|
+
* declared their types yet.
|
|
56
|
+
*
|
|
57
|
+
* @experimental
|
|
58
|
+
*/
|
|
59
|
+
export interface ElementTypesProvider {
|
|
60
|
+
get(): ElementTypes;
|
|
61
|
+
}
|
|
62
|
+
export const ElementTypesProvider = Symbol('ElementTypesProvider');
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Default {@link ElementTypesProvider} that scrapes the per-session {@link OperationHandlerRegistry}
|
|
66
|
+
* for {@link CreateNodeOperationHandler} / {@link CreateEdgeOperationHandler} instances and reads
|
|
67
|
+
* their `elementTypeIds`.
|
|
68
|
+
*/
|
|
69
|
+
@injectable()
|
|
70
|
+
export class DefaultElementTypesProvider implements ElementTypesProvider {
|
|
71
|
+
@inject(OperationHandlerRegistry) protected operationHandlerRegistry: OperationHandlerRegistry;
|
|
72
|
+
|
|
73
|
+
@inject(Logger) protected logger: Logger;
|
|
74
|
+
|
|
75
|
+
/** Already-warned operation types, deduped so the warn fires once per type. */
|
|
76
|
+
protected readonly warnedTypes = new Set<string>();
|
|
77
|
+
|
|
78
|
+
get(): ElementTypes {
|
|
79
|
+
const nodeTypes: ElementTypeEntry[] = [];
|
|
80
|
+
const edgeTypes: ElementTypeEntry[] = [];
|
|
81
|
+
for (const handler of this.operationHandlerRegistry.getAll()) {
|
|
82
|
+
if (CreateNodeOperationHandler.is(handler)) {
|
|
83
|
+
handler.elementTypeIds.forEach(id => nodeTypes.push({ id, label: handler.label }));
|
|
84
|
+
} else if (CreateEdgeOperationHandler.is(handler)) {
|
|
85
|
+
handler.elementTypeIds.forEach(id => edgeTypes.push({ id, label: handler.label }));
|
|
86
|
+
} else if (CreateOperationHandler.is(handler)) {
|
|
87
|
+
this.warnUnrecognizedOperationType(handler);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { nodeTypes, edgeTypes };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Once-per-type warn when a `CreateOperationHandler` carries an unrecognized `operationType`. */
|
|
94
|
+
protected warnUnrecognizedOperationType(handler: CreateOperationHandler): void {
|
|
95
|
+
const operationType = handler.operationType;
|
|
96
|
+
if (this.warnedTypes.has(operationType)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this.warnedTypes.add(operationType);
|
|
100
|
+
this.logger.warn(
|
|
101
|
+
`DefaultElementTypesProvider: ignoring CreateOperationHandler with operationType '${operationType}' — ` +
|
|
102
|
+
`expected '${CreateNodeOperation.KIND}' or '${CreateEdgeOperation.KIND}'. Rebind ElementTypesProvider for custom operation types.`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|