@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.
Files changed (303) hide show
  1. package/LICENSE +642 -0
  2. package/README.md +57 -0
  3. package/lib/index.d.ts +23 -0
  4. package/lib/index.d.ts.map +1 -0
  5. package/lib/index.js +41 -0
  6. package/lib/index.js.map +1 -0
  7. package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.d.ts +43 -0
  8. package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.d.ts.map +1 -0
  9. package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.js +96 -0
  10. package/lib/prompts/handlers/describe-diagram-mcp-prompt-handler.js.map +1 -0
  11. package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.d.ts +43 -0
  12. package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.d.ts.map +1 -0
  13. package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.js +95 -0
  14. package/lib/prompts/handlers/suggest-improvements-mcp-prompt-handler.js.map +1 -0
  15. package/lib/prompts/index.d.ts +18 -0
  16. package/lib/prompts/index.d.ts.map +1 -0
  17. package/lib/prompts/index.js +34 -0
  18. package/lib/prompts/index.js.map +1 -0
  19. package/lib/resources/handlers/diagram-png-mcp-resource-handler.d.ts +81 -0
  20. package/lib/resources/handlers/diagram-png-mcp-resource-handler.d.ts.map +1 -0
  21. package/lib/resources/handlers/diagram-png-mcp-resource-handler.js +174 -0
  22. package/lib/resources/handlers/diagram-png-mcp-resource-handler.js.map +1 -0
  23. package/lib/resources/handlers/diagram-svg-mcp-resource-handler.d.ts +52 -0
  24. package/lib/resources/handlers/diagram-svg-mcp-resource-handler.d.ts.map +1 -0
  25. package/lib/resources/handlers/diagram-svg-mcp-resource-handler.js +96 -0
  26. package/lib/resources/handlers/diagram-svg-mcp-resource-handler.js.map +1 -0
  27. package/lib/resources/index.d.ts +20 -0
  28. package/lib/resources/index.d.ts.map +1 -0
  29. package/lib/resources/index.js +36 -0
  30. package/lib/resources/index.js.map +1 -0
  31. package/lib/resources/services/element-types-provider.d.ts +65 -0
  32. package/lib/resources/services/element-types-provider.d.ts.map +1 -0
  33. package/lib/resources/services/element-types-provider.js +81 -0
  34. package/lib/resources/services/element-types-provider.js.map +1 -0
  35. package/lib/resources/services/mcp-model-serializer.d.ts +78 -0
  36. package/lib/resources/services/mcp-model-serializer.d.ts.map +1 -0
  37. package/lib/resources/services/mcp-model-serializer.js +188 -0
  38. package/lib/resources/services/mcp-model-serializer.js.map +1 -0
  39. package/lib/server/glsp-mcp-server.d.ts +82 -0
  40. package/lib/server/glsp-mcp-server.d.ts.map +1 -0
  41. package/lib/server/glsp-mcp-server.js +140 -0
  42. package/lib/server/glsp-mcp-server.js.map +1 -0
  43. package/lib/server/index.d.ts +37 -0
  44. package/lib/server/index.d.ts.map +1 -0
  45. package/lib/server/index.js +57 -0
  46. package/lib/server/index.js.map +1 -0
  47. package/lib/server/lru-event-store.d.ts +53 -0
  48. package/lib/server/lru-event-store.d.ts.map +1 -0
  49. package/lib/server/lru-event-store.js +100 -0
  50. package/lib/server/lru-event-store.js.map +1 -0
  51. package/lib/server/mcp-diagram-handler-dispatcher.d.ts +144 -0
  52. package/lib/server/mcp-diagram-handler-dispatcher.d.ts.map +1 -0
  53. package/lib/server/mcp-diagram-handler-dispatcher.js +382 -0
  54. package/lib/server/mcp-diagram-handler-dispatcher.js.map +1 -0
  55. package/lib/server/mcp-diagram-module.d.ts +123 -0
  56. package/lib/server/mcp-diagram-module.d.ts.map +1 -0
  57. package/lib/server/mcp-diagram-module.js +186 -0
  58. package/lib/server/mcp-diagram-module.js.map +1 -0
  59. package/lib/server/mcp-diagram-prompt-handler-registry.d.ts +33 -0
  60. package/lib/server/mcp-diagram-prompt-handler-registry.d.ts.map +1 -0
  61. package/lib/server/mcp-diagram-prompt-handler-registry.js +76 -0
  62. package/lib/server/mcp-diagram-prompt-handler-registry.js.map +1 -0
  63. package/lib/server/mcp-diagram-resource-handler-registry.d.ts +35 -0
  64. package/lib/server/mcp-diagram-resource-handler-registry.d.ts.map +1 -0
  65. package/lib/server/mcp-diagram-resource-handler-registry.js +94 -0
  66. package/lib/server/mcp-diagram-resource-handler-registry.js.map +1 -0
  67. package/lib/server/mcp-diagram-tool-handler-registry.d.ts +57 -0
  68. package/lib/server/mcp-diagram-tool-handler-registry.d.ts.map +1 -0
  69. package/lib/server/mcp-diagram-tool-handler-registry.js +111 -0
  70. package/lib/server/mcp-diagram-tool-handler-registry.js.map +1 -0
  71. package/lib/server/mcp-handler-shared.d.ts +142 -0
  72. package/lib/server/mcp-handler-shared.d.ts.map +1 -0
  73. package/lib/server/mcp-handler-shared.js +199 -0
  74. package/lib/server/mcp-handler-shared.js.map +1 -0
  75. package/lib/server/mcp-http-transport.d.ts +93 -0
  76. package/lib/server/mcp-http-transport.d.ts.map +1 -0
  77. package/lib/server/mcp-http-transport.js +350 -0
  78. package/lib/server/mcp-http-transport.js.map +1 -0
  79. package/lib/server/mcp-id-alias-service.d.ts +70 -0
  80. package/lib/server/mcp-id-alias-service.d.ts.map +1 -0
  81. package/lib/server/mcp-id-alias-service.js +85 -0
  82. package/lib/server/mcp-id-alias-service.js.map +1 -0
  83. package/lib/server/mcp-input-schemas.d.ts +73 -0
  84. package/lib/server/mcp-input-schemas.d.ts.map +1 -0
  85. package/lib/server/mcp-input-schemas.js +67 -0
  86. package/lib/server/mcp-input-schemas.js.map +1 -0
  87. package/lib/server/mcp-label-provider.d.ts +45 -0
  88. package/lib/server/mcp-label-provider.d.ts.map +1 -0
  89. package/lib/server/mcp-label-provider.js +42 -0
  90. package/lib/server/mcp-label-provider.js.map +1 -0
  91. package/lib/server/mcp-log-level-registry.d.ts +54 -0
  92. package/lib/server/mcp-log-level-registry.d.ts.map +1 -0
  93. package/lib/server/mcp-log-level-registry.js +80 -0
  94. package/lib/server/mcp-log-level-registry.js.map +1 -0
  95. package/lib/server/mcp-logger.d.ts +59 -0
  96. package/lib/server/mcp-logger.d.ts.map +1 -0
  97. package/lib/server/mcp-logger.js +104 -0
  98. package/lib/server/mcp-logger.js.map +1 -0
  99. package/lib/server/mcp-mime-types.d.ts +28 -0
  100. package/lib/server/mcp-mime-types.d.ts.map +1 -0
  101. package/lib/server/mcp-mime-types.js +18 -0
  102. package/lib/server/mcp-mime-types.js.map +1 -0
  103. package/lib/server/mcp-options.d.ts +39 -0
  104. package/lib/server/mcp-options.d.ts.map +1 -0
  105. package/lib/server/mcp-options.js +53 -0
  106. package/lib/server/mcp-options.js.map +1 -0
  107. package/lib/server/mcp-progress-reporter.d.ts +48 -0
  108. package/lib/server/mcp-progress-reporter.d.ts.map +1 -0
  109. package/lib/server/mcp-progress-reporter.js +66 -0
  110. package/lib/server/mcp-progress-reporter.js.map +1 -0
  111. package/lib/server/mcp-prompt-handler.d.ts +120 -0
  112. package/lib/server/mcp-prompt-handler.d.ts.map +1 -0
  113. package/lib/server/mcp-prompt-handler.js +131 -0
  114. package/lib/server/mcp-prompt-handler.js.map +1 -0
  115. package/lib/server/mcp-request-context.d.ts +37 -0
  116. package/lib/server/mcp-request-context.d.ts.map +1 -0
  117. package/lib/server/mcp-request-context.js +37 -0
  118. package/lib/server/mcp-request-context.js.map +1 -0
  119. package/lib/server/mcp-resource-handler.d.ts +212 -0
  120. package/lib/server/mcp-resource-handler.d.ts.map +1 -0
  121. package/lib/server/mcp-resource-handler.js +298 -0
  122. package/lib/server/mcp-resource-handler.js.map +1 -0
  123. package/lib/server/mcp-server-launcher.d.ts +143 -0
  124. package/lib/server/mcp-server-launcher.d.ts.map +1 -0
  125. package/lib/server/mcp-server-launcher.js +355 -0
  126. package/lib/server/mcp-server-launcher.js.map +1 -0
  127. package/lib/server/mcp-server-module.d.ts +143 -0
  128. package/lib/server/mcp-server-module.d.ts.map +1 -0
  129. package/lib/server/mcp-server-module.js +249 -0
  130. package/lib/server/mcp-server-module.js.map +1 -0
  131. package/lib/server/mcp-session.d.ts +44 -0
  132. package/lib/server/mcp-session.d.ts.map +1 -0
  133. package/lib/server/mcp-session.js +18 -0
  134. package/lib/server/mcp-session.js.map +1 -0
  135. package/lib/server/mcp-tool-handler.d.ts +259 -0
  136. package/lib/server/mcp-tool-handler.d.ts.map +1 -0
  137. package/lib/server/mcp-tool-handler.js +355 -0
  138. package/lib/server/mcp-tool-handler.js.map +1 -0
  139. package/lib/tools/handlers/count-elements-mcp-tool-handler.d.ts +46 -0
  140. package/lib/tools/handlers/count-elements-mcp-tool-handler.d.ts.map +1 -0
  141. package/lib/tools/handlers/count-elements-mcp-tool-handler.js +76 -0
  142. package/lib/tools/handlers/count-elements-mcp-tool-handler.js.map +1 -0
  143. package/lib/tools/handlers/create-edges-mcp-tool-handler.d.ts +112 -0
  144. package/lib/tools/handlers/create-edges-mcp-tool-handler.d.ts.map +1 -0
  145. package/lib/tools/handlers/create-edges-mcp-tool-handler.js +190 -0
  146. package/lib/tools/handlers/create-edges-mcp-tool-handler.js.map +1 -0
  147. package/lib/tools/handlers/create-nodes-mcp-tool-handler.d.ts +81 -0
  148. package/lib/tools/handlers/create-nodes-mcp-tool-handler.d.ts.map +1 -0
  149. package/lib/tools/handlers/create-nodes-mcp-tool-handler.js +123 -0
  150. package/lib/tools/handlers/create-nodes-mcp-tool-handler.js.map +1 -0
  151. package/lib/tools/handlers/delete-elements-mcp-tool-handler.d.ts +52 -0
  152. package/lib/tools/handlers/delete-elements-mcp-tool-handler.d.ts.map +1 -0
  153. package/lib/tools/handlers/delete-elements-mcp-tool-handler.js +73 -0
  154. package/lib/tools/handlers/delete-elements-mcp-tool-handler.js.map +1 -0
  155. package/lib/tools/handlers/diagram-model-mcp-tool-handler.d.ts +59 -0
  156. package/lib/tools/handlers/diagram-model-mcp-tool-handler.d.ts.map +1 -0
  157. package/lib/tools/handlers/diagram-model-mcp-tool-handler.js +78 -0
  158. package/lib/tools/handlers/diagram-model-mcp-tool-handler.js.map +1 -0
  159. package/lib/tools/handlers/element-types-mcp-tool-handler.d.ts +97 -0
  160. package/lib/tools/handlers/element-types-mcp-tool-handler.d.ts.map +1 -0
  161. package/lib/tools/handlers/element-types-mcp-tool-handler.js +155 -0
  162. package/lib/tools/handlers/element-types-mcp-tool-handler.js.map +1 -0
  163. package/lib/tools/handlers/get-selection-mcp-tool-handler.d.ts +43 -0
  164. package/lib/tools/handlers/get-selection-mcp-tool-handler.d.ts.map +1 -0
  165. package/lib/tools/handlers/get-selection-mcp-tool-handler.js +68 -0
  166. package/lib/tools/handlers/get-selection-mcp-tool-handler.js.map +1 -0
  167. package/lib/tools/handlers/layout-mcp-tool-handler.d.ts +43 -0
  168. package/lib/tools/handlers/layout-mcp-tool-handler.d.ts.map +1 -0
  169. package/lib/tools/handlers/layout-mcp-tool-handler.js +71 -0
  170. package/lib/tools/handlers/layout-mcp-tool-handler.js.map +1 -0
  171. package/lib/tools/handlers/modify-edges-mcp-tool-handler.d.ts +78 -0
  172. package/lib/tools/handlers/modify-edges-mcp-tool-handler.d.ts.map +1 -0
  173. package/lib/tools/handlers/modify-edges-mcp-tool-handler.js +136 -0
  174. package/lib/tools/handlers/modify-edges-mcp-tool-handler.js.map +1 -0
  175. package/lib/tools/handlers/modify-nodes-mcp-tool-handler.d.ts +92 -0
  176. package/lib/tools/handlers/modify-nodes-mcp-tool-handler.d.ts.map +1 -0
  177. package/lib/tools/handlers/modify-nodes-mcp-tool-handler.js +125 -0
  178. package/lib/tools/handlers/modify-nodes-mcp-tool-handler.js.map +1 -0
  179. package/lib/tools/handlers/query-elements-mcp-tool-handler.d.ts +102 -0
  180. package/lib/tools/handlers/query-elements-mcp-tool-handler.d.ts.map +1 -0
  181. package/lib/tools/handlers/query-elements-mcp-tool-handler.js +158 -0
  182. package/lib/tools/handlers/query-elements-mcp-tool-handler.js.map +1 -0
  183. package/lib/tools/handlers/redo-mcp-tool-handler.d.ts +45 -0
  184. package/lib/tools/handlers/redo-mcp-tool-handler.d.ts.map +1 -0
  185. package/lib/tools/handlers/redo-mcp-tool-handler.js +73 -0
  186. package/lib/tools/handlers/redo-mcp-tool-handler.js.map +1 -0
  187. package/lib/tools/handlers/save-model-mcp-tool-handler.d.ts +55 -0
  188. package/lib/tools/handlers/save-model-mcp-tool-handler.d.ts.map +1 -0
  189. package/lib/tools/handlers/save-model-mcp-tool-handler.js +91 -0
  190. package/lib/tools/handlers/save-model-mcp-tool-handler.js.map +1 -0
  191. package/lib/tools/handlers/session-info-mcp-tool-handler.d.ts +65 -0
  192. package/lib/tools/handlers/session-info-mcp-tool-handler.d.ts.map +1 -0
  193. package/lib/tools/handlers/session-info-mcp-tool-handler.js +108 -0
  194. package/lib/tools/handlers/session-info-mcp-tool-handler.js.map +1 -0
  195. package/lib/tools/handlers/set-selection-mcp-tool-handler.d.ts +60 -0
  196. package/lib/tools/handlers/set-selection-mcp-tool-handler.d.ts.map +1 -0
  197. package/lib/tools/handlers/set-selection-mcp-tool-handler.js +103 -0
  198. package/lib/tools/handlers/set-selection-mcp-tool-handler.js.map +1 -0
  199. package/lib/tools/handlers/set-view-mcp-tool-handler.d.ts +110 -0
  200. package/lib/tools/handlers/set-view-mcp-tool-handler.d.ts.map +1 -0
  201. package/lib/tools/handlers/set-view-mcp-tool-handler.js +142 -0
  202. package/lib/tools/handlers/set-view-mcp-tool-handler.js.map +1 -0
  203. package/lib/tools/handlers/undo-mcp-tool-handler.d.ts +45 -0
  204. package/lib/tools/handlers/undo-mcp-tool-handler.d.ts.map +1 -0
  205. package/lib/tools/handlers/undo-mcp-tool-handler.js +74 -0
  206. package/lib/tools/handlers/undo-mcp-tool-handler.js.map +1 -0
  207. package/lib/tools/handlers/validate-diagram-mcp-tool-handler.d.ts +66 -0
  208. package/lib/tools/handlers/validate-diagram-mcp-tool-handler.d.ts.map +1 -0
  209. package/lib/tools/handlers/validate-diagram-mcp-tool-handler.js +0 -0
  210. package/lib/tools/handlers/validate-diagram-mcp-tool-handler.js.map +1 -0
  211. package/lib/tools/index.d.ts +34 -0
  212. package/lib/tools/index.d.ts.map +1 -0
  213. package/lib/tools/index.js +50 -0
  214. package/lib/tools/index.js.map +1 -0
  215. package/lib/util/index.d.ts +18 -0
  216. package/lib/util/index.d.ts.map +1 -0
  217. package/lib/util/index.js +34 -0
  218. package/lib/util/index.js.map +1 -0
  219. package/lib/util/markdown-util.d.ts +20 -0
  220. package/lib/util/markdown-util.d.ts.map +1 -0
  221. package/lib/util/markdown-util.js +45 -0
  222. package/lib/util/markdown-util.js.map +1 -0
  223. package/lib/util/mcp-util.d.ts +22 -0
  224. package/lib/util/mcp-util.d.ts.map +1 -0
  225. package/lib/util/mcp-util.js +29 -0
  226. package/lib/util/mcp-util.js.map +1 -0
  227. package/package.json +63 -0
  228. package/src/index.ts +24 -0
  229. package/src/prompts/handlers/describe-diagram-mcp-prompt-handler.ts +89 -0
  230. package/src/prompts/handlers/suggest-improvements-mcp-prompt-handler.ts +86 -0
  231. package/src/prompts/index.ts +18 -0
  232. package/src/resources/handlers/diagram-png-mcp-resource-handler.ts +181 -0
  233. package/src/resources/handlers/diagram-svg-mcp-resource-handler.ts +89 -0
  234. package/src/resources/index.ts +20 -0
  235. package/src/resources/services/element-types-provider.ts +105 -0
  236. package/src/resources/services/mcp-model-serializer.ts +211 -0
  237. package/src/server/glsp-mcp-server.spec.ts +73 -0
  238. package/src/server/glsp-mcp-server.ts +196 -0
  239. package/src/server/index.ts +42 -0
  240. package/src/server/lru-event-store.spec.ts +121 -0
  241. package/src/server/lru-event-store.ts +112 -0
  242. package/src/server/mcp-diagram-handler-dispatcher.spec.ts +231 -0
  243. package/src/server/mcp-diagram-handler-dispatcher.ts +459 -0
  244. package/src/server/mcp-diagram-module.ts +248 -0
  245. package/src/server/mcp-diagram-prompt-handler-registry.ts +59 -0
  246. package/src/server/mcp-diagram-resource-handler-registry.ts +73 -0
  247. package/src/server/mcp-diagram-tool-handler-registry.ts +97 -0
  248. package/src/server/mcp-handler-shared.spec.ts +53 -0
  249. package/src/server/mcp-handler-shared.ts +247 -0
  250. package/src/server/mcp-http-transport-e2e.spec.ts +151 -0
  251. package/src/server/mcp-http-transport.spec.ts +385 -0
  252. package/src/server/mcp-http-transport.ts +368 -0
  253. package/src/server/mcp-id-alias-service.spec.ts +106 -0
  254. package/src/server/mcp-id-alias-service.ts +104 -0
  255. package/src/server/mcp-input-schemas.ts +82 -0
  256. package/src/server/mcp-label-provider.ts +52 -0
  257. package/src/server/mcp-log-level-registry.spec.ts +75 -0
  258. package/src/server/mcp-log-level-registry.ts +90 -0
  259. package/src/server/mcp-logger.spec.ts +227 -0
  260. package/src/server/mcp-logger.ts +91 -0
  261. package/src/server/mcp-mime-types.ts +31 -0
  262. package/src/server/mcp-options.ts +43 -0
  263. package/src/server/mcp-progress-reporter.spec.ts +93 -0
  264. package/src/server/mcp-progress-reporter.ts +67 -0
  265. package/src/server/mcp-prompt-handler.ts +157 -0
  266. package/src/server/mcp-request-context.ts +39 -0
  267. package/src/server/mcp-resource-handler.ts +389 -0
  268. package/src/server/mcp-server-launcher.spec.ts +173 -0
  269. package/src/server/mcp-server-launcher.ts +369 -0
  270. package/src/server/mcp-server-module.ts +287 -0
  271. package/src/server/mcp-session.ts +45 -0
  272. package/src/server/mcp-tool-handler.spec.ts +182 -0
  273. package/src/server/mcp-tool-handler.ts +431 -0
  274. package/src/server/raw-http.spec.ts +59 -0
  275. package/src/tools/handlers/count-elements-mcp-tool-handler.spec.ts +99 -0
  276. package/src/tools/handlers/count-elements-mcp-tool-handler.ts +66 -0
  277. package/src/tools/handlers/create-edges-mcp-tool-handler.spec.ts +196 -0
  278. package/src/tools/handlers/create-edges-mcp-tool-handler.ts +205 -0
  279. package/src/tools/handlers/create-nodes-mcp-tool-handler.spec.ts +197 -0
  280. package/src/tools/handlers/create-nodes-mcp-tool-handler.ts +131 -0
  281. package/src/tools/handlers/delete-elements-mcp-tool-handler.ts +73 -0
  282. package/src/tools/handlers/diagram-model-mcp-tool-handler.ts +66 -0
  283. package/src/tools/handlers/element-types-mcp-tool-handler.ts +151 -0
  284. package/src/tools/handlers/get-selection-mcp-tool-handler.ts +54 -0
  285. package/src/tools/handlers/layout-mcp-tool-handler.ts +56 -0
  286. package/src/tools/handlers/modify-edges-mcp-tool-handler.ts +148 -0
  287. package/src/tools/handlers/modify-nodes-mcp-tool-handler.ts +140 -0
  288. package/src/tools/handlers/query-elements-mcp-tool-handler.spec.ts +210 -0
  289. package/src/tools/handlers/query-elements-mcp-tool-handler.ts +161 -0
  290. package/src/tools/handlers/redo-mcp-tool-handler.ts +62 -0
  291. package/src/tools/handlers/save-model-mcp-tool-handler.ts +71 -0
  292. package/src/tools/handlers/session-info-mcp-tool-handler.spec.ts +152 -0
  293. package/src/tools/handlers/session-info-mcp-tool-handler.ts +97 -0
  294. package/src/tools/handlers/set-selection-mcp-tool-handler.spec.ts +118 -0
  295. package/src/tools/handlers/set-selection-mcp-tool-handler.ts +90 -0
  296. package/src/tools/handlers/set-view-mcp-tool-handler.ts +162 -0
  297. package/src/tools/handlers/undo-mcp-tool-handler.ts +61 -0
  298. package/src/tools/handlers/validate-diagram-mcp-tool-handler.ts +0 -0
  299. package/src/tools/index.ts +34 -0
  300. package/src/tools/tool-annotations.spec.ts +141 -0
  301. package/src/util/index.ts +18 -0
  302. package/src/util/markdown-util.ts +44 -0
  303. package/src/util/mcp-util.ts +25 -0
@@ -0,0 +1,45 @@
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 type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
18
+
19
+ /**
20
+ * **Note on terminology** — the word "session" is overloaded in this codebase. Two
21
+ * independent concepts exist and must not be conflated:
22
+ *
23
+ * 1. **MCP session** (this file): one MCP client connection to the MCP HTTP endpoint, tracked by
24
+ * {@link McpHttpTransport.sessions} keyed by the SDK-issued `mcp-session-id` HTTP header.
25
+ * Created in `onsessioninitialized`, supports resumability across reconnects via
26
+ * `Last-Event-ID`. Each {@link McpSession} corresponds to one underlying SDK `McpServer`
27
+ * instance — multiple LLM clients can connect simultaneously, each with its own MCP session
28
+ * and its own SDK server.
29
+ *
30
+ * 2. **GLSP client session** (core): one open diagram, tracked by core's `ClientSessionManager`
31
+ * and represented by `ClientSession`. Tools/resources/prompts that target a specific diagram
32
+ * receive the GLSP session id via `params.sessionId` in their input schema.
33
+ *
34
+ * The two are independent in lifetime and cardinality: a single MCP session sees ALL open GLSP
35
+ * sessions; a single GLSP session is visible to every connected MCP session. Names in this
36
+ * package distinguish them: anything with the `Mcp` prefix in {@link mcp-session.ts} or
37
+ * `mcp-http-transport.ts` is MCP-side; anything talking about diagrams (`AbstractMcpDiagram*`,
38
+ * `requireGlspSession`, `GlspSession`) is GLSP-side.
39
+ */
40
+ export type McpSessionId = string;
41
+
42
+ export type WithSessionId<T> = T & { get sessionId(): McpSessionId };
43
+
44
+ /** SDK {@link Transport} widened with the session-id accessor every concrete MCP transport carries post-handshake. */
45
+ export type McpSession = WithSessionId<Transport>;
@@ -0,0 +1,182 @@
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 { expect } from 'chai';
18
+ import * as z from 'zod/v4';
19
+ import { McpToolResult } from './mcp-handler-shared';
20
+ import { CreateEdgesMcpToolHandler, CreateEdgesOutputSchema } from '../tools/handlers/create-edges-mcp-tool-handler';
21
+ import { CreateNodesMcpToolHandler, CreateNodesOutputSchema } from '../tools/handlers/create-nodes-mcp-tool-handler';
22
+ import { DeleteElementsMcpToolHandler, DeleteElementsOutputSchema } from '../tools/handlers/delete-elements-mcp-tool-handler';
23
+ import { GetSelectionMcpToolHandler, GetSelectionOutputSchema } from '../tools/handlers/get-selection-mcp-tool-handler';
24
+ import { LayoutMcpToolHandler, LayoutOutputSchema } from '../tools/handlers/layout-mcp-tool-handler';
25
+ import { ModifyEdgesMcpToolHandler, ModifyEdgesOutputSchema } from '../tools/handlers/modify-edges-mcp-tool-handler';
26
+ import { ModifyNodesMcpToolHandler, ModifyNodesOutputSchema } from '../tools/handlers/modify-nodes-mcp-tool-handler';
27
+ import { QueryElementsMcpToolHandler, QueryElementsOutputSchema } from '../tools/handlers/query-elements-mcp-tool-handler';
28
+ import { RedoMcpToolHandler, RedoOutputSchema } from '../tools/handlers/redo-mcp-tool-handler';
29
+ import { SaveModelMcpToolHandler, SaveModelOutputSchema } from '../tools/handlers/save-model-mcp-tool-handler';
30
+ import { SetViewMcpToolHandler, SetViewOutputSchema } from '../tools/handlers/set-view-mcp-tool-handler';
31
+ import { UndoMcpToolHandler, UndoOutputSchema } from '../tools/handlers/undo-mcp-tool-handler';
32
+ import { ValidateDiagramMcpToolHandler, ValidateDiagramOutputSchema } from '../tools/handlers/validate-diagram-mcp-tool-handler';
33
+ import { AbstractMcpToolHandler } from './mcp-tool-handler';
34
+
35
+ // ─── Framework: BaseMcpToolHandler.success(...) and toRegistrationConfig() ────────────────────
36
+
37
+ class WithoutOutputSchemaHandler extends AbstractMcpToolHandler {
38
+ readonly name = 'no-schema';
39
+ readonly description = 'no-schema';
40
+ readonly inputSchema = z.object({});
41
+
42
+ protected createResult(): McpToolResult {
43
+ return this.success('plain');
44
+ }
45
+
46
+ /** Test exposure of the protected helper. `BaseMcpToolHandler` doesn't read `logger` here. */
47
+ public testSuccess(message: string, structured?: Record<string, unknown>): McpToolResult {
48
+ return this.success(message, structured);
49
+ }
50
+ }
51
+
52
+ class WithOutputSchemaHandler extends AbstractMcpToolHandler {
53
+ readonly name = 'with-schema';
54
+ readonly description = 'with-schema';
55
+ readonly inputSchema = z.object({});
56
+ override readonly outputSchema = z.object({ ok: z.boolean() });
57
+
58
+ protected createResult(): McpToolResult {
59
+ return this.success('with', { ok: true });
60
+ }
61
+ }
62
+
63
+ describe('Dual-emit framework', () => {
64
+ it('success(message) without structured payload omits structuredContent', () => {
65
+ const result = new WithoutOutputSchemaHandler().testSuccess('hi');
66
+ expect(result.content).to.deep.equal([{ type: 'text', text: 'hi' }]);
67
+ expect(result.structuredContent).to.equal(undefined);
68
+ expect(result.isError).to.equal(false);
69
+ });
70
+
71
+ it('success(message, structured) emits structuredContent', () => {
72
+ const result = new WithoutOutputSchemaHandler().testSuccess('hi', { count: 3, ids: ['a'] });
73
+ expect(result.content).to.deep.equal([{ type: 'text', text: 'hi' }]);
74
+ expect(result.structuredContent).to.deep.equal({ count: 3, ids: ['a'] });
75
+ });
76
+
77
+ it('toRegistrationConfig() omits outputSchema when not declared', () => {
78
+ const config = new WithoutOutputSchemaHandler().toRegistrationConfig();
79
+ expect(config.outputSchema).to.equal(undefined);
80
+ });
81
+
82
+ it('toRegistrationConfig() forwards outputSchema when declared', () => {
83
+ const config = new WithOutputSchemaHandler().toRegistrationConfig();
84
+ expect(config.outputSchema).to.not.equal(undefined);
85
+ // The SDK accepts a full `ZodObject` (or its raw shape); we pass the wrapped object so
86
+ // strict-mode rejection of unknown keys can extend uniformly to outputs.
87
+ expect(Object.keys(config.outputSchema!.shape)).to.deep.equal(['ok']);
88
+ });
89
+ });
90
+
91
+ // ─── Per-handler schema matrix ────────────────────────────────────────────────────────────────
92
+
93
+ /**
94
+ * Each entry binds a handler constructor to its declared `OutputSchema` + a representative
95
+ * structured payload. The expectations:
96
+ * - Constructor's `outputSchema` field matches the exported schema (same reference).
97
+ * - The schema accepts the representative payload (zod parse passes).
98
+ */
99
+ const matrix: Array<{
100
+ name: string;
101
+ Constructor: new () => { outputSchema?: unknown };
102
+ schema: z.ZodObject;
103
+ sample: Record<string, unknown>;
104
+ }> = [
105
+ {
106
+ name: 'create-nodes',
107
+ Constructor: CreateNodesMcpToolHandler,
108
+ schema: CreateNodesOutputSchema,
109
+ sample: { createdNodes: [{ id: 'n1', elementTypeId: 'node:foo' }], errors: [], warnings: [] }
110
+ },
111
+ {
112
+ name: 'create-edges',
113
+ Constructor: CreateEdgesMcpToolHandler,
114
+ schema: CreateEdgesOutputSchema,
115
+ sample: { createdEdges: [{ id: 'e1', elementTypeId: 'edge' }], errors: [] }
116
+ },
117
+ {
118
+ name: 'modify-nodes',
119
+ Constructor: ModifyNodesMcpToolHandler,
120
+ schema: ModifyNodesOutputSchema,
121
+ sample: { modifiedNodes: [{ id: 'n1', elementTypeId: 'node:foo' }], dispatchedCommands: 1, warnings: [] }
122
+ },
123
+ {
124
+ name: 'modify-edges',
125
+ Constructor: ModifyEdgesMcpToolHandler,
126
+ schema: ModifyEdgesOutputSchema,
127
+ sample: { modifiedEdges: [{ id: 'e1', elementTypeId: 'edge' }], dispatchedCommands: 1, errors: [] }
128
+ },
129
+ {
130
+ name: 'delete-elements',
131
+ Constructor: DeleteElementsMcpToolHandler,
132
+ schema: DeleteElementsOutputSchema,
133
+ sample: { deletedElements: [{ id: 'n1', elementTypeId: 'node:foo' }], deletedCount: 3 }
134
+ },
135
+ { name: 'undo', Constructor: UndoMcpToolHandler, schema: UndoOutputSchema, sample: { commandsUndone: 2 } },
136
+ { name: 'redo', Constructor: RedoMcpToolHandler, schema: RedoOutputSchema, sample: { commandsRedone: 2 } },
137
+ { name: 'layout', Constructor: LayoutMcpToolHandler, schema: LayoutOutputSchema, sample: { applied: true } },
138
+ {
139
+ name: 'validate-diagram',
140
+ Constructor: ValidateDiagramMcpToolHandler,
141
+ schema: ValidateDiagramOutputSchema,
142
+ sample: { markers: [{ kind: 'error', label: 'bad', description: 'bad bad', elementId: 'n1' }] }
143
+ },
144
+ {
145
+ name: 'get-selection',
146
+ Constructor: GetSelectionMcpToolHandler,
147
+ schema: GetSelectionOutputSchema,
148
+ sample: { selectedElementIds: ['n1', 'n2'] }
149
+ },
150
+ {
151
+ name: 'query-elements',
152
+ Constructor: QueryElementsMcpToolHandler,
153
+ schema: QueryElementsOutputSchema,
154
+ sample: { mode: 'inspect', elements: [{ id: 'n1', type: 'node:foo', position: { x: 0, y: 0 } }] }
155
+ },
156
+ {
157
+ name: 'save-model',
158
+ Constructor: SaveModelMcpToolHandler,
159
+ schema: SaveModelOutputSchema,
160
+ sample: { saved: true, fileUri: 'file:///a' }
161
+ },
162
+ {
163
+ name: 'set-view',
164
+ Constructor: SetViewMcpToolHandler,
165
+ schema: SetViewOutputSchema,
166
+ sample: { action: 'fit-to-screen', targetIds: ['n1'] }
167
+ }
168
+ ];
169
+
170
+ describe('Tool output schemas · per-handler matrix', () => {
171
+ matrix.forEach(({ name, Constructor, schema, sample }) => {
172
+ describe(name, () => {
173
+ it('declares outputSchema referencing the exported schema constant', () => {
174
+ expect(new Constructor().outputSchema).to.equal(schema);
175
+ });
176
+
177
+ it('schema accepts a representative structured payload', () => {
178
+ expect(() => schema.parse(sample)).to.not.throw();
179
+ });
180
+ });
181
+ });
182
+ });
@@ -0,0 +1,431 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2025-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 {
18
+ ActionDispatcher,
19
+ ClientId,
20
+ GModelElement,
21
+ Logger,
22
+ MaybePromise,
23
+ ModelState,
24
+ RequestAction,
25
+ ResponseAction
26
+ } from '@eclipse-glsp/server';
27
+ import { ToolAnnotations } from '@modelcontextprotocol/sdk/types';
28
+ import { inject, injectable, interfaces } from 'inversify';
29
+ import { ZodObject, ZodRawShape } from 'zod/v4';
30
+ import { GLSPMcpServer } from './glsp-mcp-server';
31
+ import {
32
+ McpElementsNotFoundError,
33
+ McpReadOnlyError,
34
+ McpStructuredContent,
35
+ McpToolError,
36
+ McpToolErrorCode,
37
+ McpToolErrorCodes,
38
+ McpToolResult,
39
+ errorCodeFor,
40
+ extractErrorMessage,
41
+ requestActionOrFail,
42
+ toolErrorResult
43
+ } from './mcp-handler-shared';
44
+ import { McpIdAliasService } from './mcp-id-alias-service';
45
+ import { ElementIdentity, McpDiagramScopedInput } from './mcp-input-schemas';
46
+ import { McpLabelProvider } from './mcp-label-provider';
47
+ import { mcpRequestContext } from './mcp-request-context';
48
+
49
+ /**
50
+ * Multi-binding key for **server-scope** tool handlers — singletons that don't target a
51
+ * specific GLSP client session. Adopters extend {@link AbstractMcpToolHandler} and bind their
52
+ * subclass against this symbol; the launcher invokes `registerTool(server)` on each at
53
+ * MCP-session-init.
54
+ *
55
+ * Diagram-scope tools (one instance per open diagram) use the separate
56
+ * {@link McpDiagramToolHandlerConstructor} multi-binding instead — see `mcp-session.ts` for
57
+ * the MCP-session vs GLSP-session terminology.
58
+ *
59
+ * @experimental
60
+ */
61
+ export interface McpToolHandler {
62
+ registerTool(server: GLSPMcpServer): void;
63
+ }
64
+ export const McpToolHandler = Symbol('McpToolHandler');
65
+
66
+ /**
67
+ * Shared infrastructure for both server- and diagram-scope tool handlers — exported so adopters
68
+ * who want to factor common helpers across server-scope and diagram-scope tools can extend a
69
+ * single ancestor instead of duplicating logic. Most adopters extend the more specific siblings
70
+ * ({@link AbstractMcpToolHandler}, {@link AbstractMcpDiagramToolHandler},
71
+ * {@link OperationMcpDiagramToolHandler}); reach for this base only when a helper is genuinely
72
+ * scope-agnostic.
73
+ *
74
+ * @experimental
75
+ */
76
+ @injectable()
77
+ export abstract class BaseMcpToolHandler {
78
+ @inject(Logger) protected logger: Logger;
79
+
80
+ /**
81
+ * Tool identifier exposed to the MCP client. Also used to reference this tool from other
82
+ * handlers' prompt or description text — wire via `static readonly NAME = '…'` and
83
+ * `readonly name = ClassName.NAME` so those cross-references survive renames.
84
+ */
85
+ abstract readonly name: string;
86
+ /** LLM-facing explanation surfaced in the tool catalog — clients pass this verbatim to the model. Keep concise and behavioral. */
87
+ abstract readonly description: string;
88
+ /** Adopter writes `z.object({ ... })`; the base passes `.shape` to the SDK. */
89
+ abstract readonly inputSchema: ZodObject<ZodRawShape>;
90
+ /**
91
+ * Optional dual-emit schema. When set, pass the matching `structured` payload to
92
+ * {@link success} so the framework forwards it as `structuredContent` alongside the
93
+ * human-readable text. The MCP spec says clients SHOULD validate `structuredContent`
94
+ * against the declared schema, so the two MUST stay in sync.
95
+ */
96
+ readonly outputSchema?: ZodObject<ZodRawShape>;
97
+ /** Optional human-friendly display name for UIs that render a friendlier label than `name`. */
98
+ readonly title?: string;
99
+
100
+ // ─── Tool annotations (MCP spec: server/tools) ───────────────────────────────
101
+ // Surfaced as flat fields rather than a nested `annotations` object so adopters can
102
+ // override one hint with a one-line `override readonly destructiveHint = true;` instead of
103
+ // re-declaring the whole quartet. **Untrusted** unless from a trusted server — clients
104
+ // MUST treat these as advisory.
105
+
106
+ /**
107
+ * Tool does not modify its environment. Defaults to `true` here on the common base;
108
+ * overridden to `false` on {@link OperationMcpDiagramToolHandler} since write-style tools
109
+ * dispatch model-mutating operations.
110
+ */
111
+ readonly readOnlyHint: boolean = true;
112
+ /**
113
+ * Tool may perform destructive *updates* (irreversible deletion, data loss). Only meaningful
114
+ * when `readOnlyHint: false`. Set explicitly on the concrete handler when it applies (e.g.
115
+ * `delete-elements`).
116
+ */
117
+ readonly destructiveHint?: boolean;
118
+ /**
119
+ * Repeated calls with the same arguments have no additional effect. Only meaningful when
120
+ * `readOnlyHint: false`.
121
+ */
122
+ readonly idempotentHint?: boolean;
123
+ /**
124
+ * Tool interacts with an "open world" of external entities (web search, external APIs).
125
+ * Default in this codebase: `false` — diagram ops are bounded to the GLSP client. Set
126
+ * `true` for tools that reach off-process.
127
+ */
128
+ readonly openWorldHint: boolean = false;
129
+
130
+ /**
131
+ * SDK-facing registration config; consumed by both the server-scope `registerTool` flow and
132
+ * the launcher's diagram-scope dispatcher. Assembles the {@link ToolAnnotations} object from
133
+ * the flat-field surface so adopters compose annotations via field overrides, not by
134
+ * redeclaring the whole annotations literal.
135
+ */
136
+ toRegistrationConfig(): {
137
+ title?: string;
138
+ description: string;
139
+ inputSchema: ZodObject<ZodRawShape>;
140
+ outputSchema?: ZodObject<ZodRawShape>;
141
+ annotations: ToolAnnotations;
142
+ } {
143
+ // `.strict()` rejects unknown keys at the SDK boundary instead of silently stripping them
144
+ // — turns an LLM mis-typed field name into a self-correctable JSON-RPC validation error
145
+ // rather than a misleading "no-op success".
146
+ //
147
+ // The `as unknown as ZodObject<ZodRawShape>` bridge is needed because `.strict()` returns
148
+ // a `ZodObject<…, $strict>` whose `$strict` marker generic is not assignable to the
149
+ // shape-only `ZodObject<ZodRawShape>` expected here. The SDK accepts both shapes
150
+ // structurally, so the cast is type-only — no runtime mismatch.
151
+ return {
152
+ title: this.title,
153
+ description: this.description,
154
+ inputSchema: this.inputSchema.strict() as unknown as ZodObject<ZodRawShape>,
155
+ outputSchema: this.outputSchema as ZodObject<ZodRawShape> | undefined,
156
+ annotations: {
157
+ readOnlyHint: this.readOnlyHint,
158
+ destructiveHint: this.destructiveHint,
159
+ idempotentHint: this.idempotentHint,
160
+ openWorldHint: this.openWorldHint
161
+ }
162
+ };
163
+ }
164
+
165
+ protected error(message: string, code?: McpToolErrorCode): McpToolResult {
166
+ return toolErrorResult(message, code);
167
+ }
168
+
169
+ /**
170
+ * Convention: `message` is a short, referenceable summary (ids, types, counts); `structured`
171
+ * carries the full payload. The two complement rather than duplicate — balancing token usage
172
+ * across the heterogeneous client landscape.
173
+ *
174
+ * The MCP spec (2025-06-18) recommends mirroring `structuredContent` into a TextContent
175
+ * block, but in-flight discussion is softening that — `content` and `structuredContent` are
176
+ * increasingly model-oriented vs. machine-oriented surfaces that should be semantically
177
+ * equivalent, not byte-identical.
178
+ *
179
+ * Client behavior is uneven, so summary-in-content + payload-in-structured is a deliberate
180
+ * hedge: some clients only forward `structuredContent`, some only `content`, some forward
181
+ * both verbatim and double the per-call context budget.
182
+ *
183
+ * Pass `structured` whenever {@link outputSchema} is declared (the spec says clients SHOULD
184
+ * validate against the declared shape). Omit for plain text-only responses.
185
+ */
186
+ protected success(message: string, structured?: McpStructuredContent): McpToolResult {
187
+ return { isError: false, content: [{ type: 'text', text: message }], structuredContent: structured };
188
+ }
189
+
190
+ /** Catches `McpToolError` (→ `isError: true` result) and unexpected errors; tags known errors via {@link errorCodeFor}. */
191
+ protected async execute(producer: () => MaybePromise<McpToolResult>): Promise<McpToolResult> {
192
+ try {
193
+ return await producer();
194
+ } catch (err: unknown) {
195
+ const code = errorCodeFor(err);
196
+ if (err instanceof McpToolError) {
197
+ return this.error(err.message, code);
198
+ }
199
+ const message = extractErrorMessage(err);
200
+ // Session-disposed races aren't programming errors — log at warn so they don't drown the error feed.
201
+ if (code === McpToolErrorCodes.SessionDisposed) {
202
+ this.logger.warn(`Session disposed mid-call in tool '${this.name}': ${message}`);
203
+ } else {
204
+ this.logger.error(`Unexpected error in tool '${this.name}': ${message}`, err);
205
+ }
206
+ return this.error(message, code);
207
+ }
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Server-scope tool base — for tools that don't target a specific GLSP client session
213
+ * (e.g., listing all sessions). Bound under {@link McpToolHandler} as a server-scope singleton;
214
+ * the launcher invokes `registerTool(server)` once per MCP session.
215
+ *
216
+ * @experimental
217
+ */
218
+ @injectable()
219
+ export abstract class AbstractMcpToolHandler<T = Record<string, unknown>> extends BaseMcpToolHandler implements McpToolHandler {
220
+ /** Throw {@link McpToolError} for expected, user-facing errors; the base wraps. */
221
+ protected abstract createResult(params: T): MaybePromise<McpToolResult>;
222
+
223
+ registerTool(server: GLSPMcpServer): void {
224
+ server.registerTool(this.name, this.toRegistrationConfig(), async (params, extra) =>
225
+ mcpRequestContext.run(extra, () => this.execute(() => this.createResult(params as T)))
226
+ );
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Shared per-session implementation for diagram-scope tool handlers. Adopters don't extend this
232
+ * directly — extend {@link AbstractMcpDiagramToolHandler} (read) or {@link OperationMcpDiagramToolHandler}
233
+ * (write). Exported only as the upper bound for the {@link McpDiagramToolHandlerConstructor}
234
+ * multi-binding.
235
+ *
236
+ * `@inject(...)` fields resolve against the live `ClientSession.container` because instances are
237
+ * created at GLSP-session-open by `McpDiagramToolHandlerRegistryInitializer`.
238
+ *
239
+ * Read-side handlers access `modelState.index` directly. Synchronous reads are atomic, but a
240
+ * concurrent tool that awaits `actionDispatcher.dispatch(...)` may expose a half-committed
241
+ * model — write-then-read tool sequences must serialize the write before the read.
242
+ *
243
+ * @experimental
244
+ */
245
+ @injectable()
246
+ export abstract class BaseMcpDiagramToolHandler<T extends McpDiagramScopedInput = McpDiagramScopedInput> extends BaseMcpToolHandler {
247
+ @inject(ClientId) protected clientId: string;
248
+ @inject(ModelState) protected modelState: ModelState;
249
+ @inject(McpIdAliasService) protected aliasService: McpIdAliasService;
250
+ @inject(McpLabelProvider) protected labelProvider: McpLabelProvider;
251
+
252
+ /** Throw {@link McpToolError} for expected errors; the base wraps. */
253
+ protected abstract createResult(params: T): MaybePromise<McpToolResult>;
254
+
255
+ /**
256
+ * Public dispatch entry point invoked by {@link McpServerLauncher}'s registered SDK
257
+ * callback. Each sibling sets its own policy — {@link AbstractMcpDiagramToolHandler}
258
+ * passes through; {@link OperationMcpDiagramToolHandler} enforces the readonly gate.
259
+ * Adopters don't call this directly.
260
+ */
261
+ abstract handle(params: T): Promise<McpToolResult>;
262
+
263
+ /** Override to opt out of registration when a runtime dependency is missing. Default: `true`. */
264
+ canRegister(): boolean {
265
+ return true;
266
+ }
267
+
268
+ /** Translates (alias-or-real) ids to real ids; partitions ids absent from the model into `missingIds`. */
269
+ protected resolveIds(ids: string[]): { realIds: string[]; missingIds: string[] } {
270
+ const realIds: string[] = [];
271
+ const missingIds: string[] = [];
272
+ for (const id of ids) {
273
+ const realId = this.aliasService.lookup(id);
274
+ if (this.modelState.index.find(realId)) {
275
+ realIds.push(realId);
276
+ } else {
277
+ missingIds.push(id);
278
+ }
279
+ }
280
+ return { realIds, missingIds };
281
+ }
282
+
283
+ /** Like {@link resolveIds} but throws {@link McpElementsNotFoundError} when any input id is absent. */
284
+ protected resolveExistingIds(ids: string[] | undefined): string[] {
285
+ if (!ids || ids.length === 0) {
286
+ return [];
287
+ }
288
+ const { realIds, missingIds } = this.resolveIds(ids);
289
+ if (missingIds.length > 0) {
290
+ throw new McpElementsNotFoundError(missingIds);
291
+ }
292
+ return realIds;
293
+ }
294
+
295
+ /**
296
+ * Resolves a list of structured inputs against the model: each input's id is looked up via the
297
+ * alias service and the resolved element is retrieved from the index. Throws
298
+ * {@link McpElementsNotFoundError} if any input's id is absent. The returned tuples preserve
299
+ * caller's input/element pairing for downstream processing (e.g. type-checks per kind).
300
+ */
301
+ protected lookupElements<I>(inputs: I[], extractId: (input: I) => string): Array<[I, GModelElement]> {
302
+ const found: Array<[I, GModelElement]> = [];
303
+ const missing: string[] = [];
304
+ for (const input of inputs) {
305
+ const inputId = extractId(input);
306
+ const realId = this.aliasService.lookup(inputId);
307
+ const element = this.modelState.index.find(realId);
308
+ if (element) {
309
+ found.push([input, element]);
310
+ } else {
311
+ missing.push(inputId);
312
+ }
313
+ }
314
+ if (missing.length > 0) {
315
+ throw new McpElementsNotFoundError(missing);
316
+ }
317
+ return found;
318
+ }
319
+
320
+ /** Encodes real ids to alias ids (passthrough when {@link NullMcpIdAliasService} is bound). */
321
+ protected encodeIds(ids: string[]): string[] {
322
+ return ids.map(id => this.aliasService.alias(id));
323
+ }
324
+
325
+ /**
326
+ * Compact identity for an element — `{ id, elementTypeId, label? }`. Mutating tools (create
327
+ * / modify / delete) echo this so the LLM can refer to the element by label or type in
328
+ * user-facing prose without a follow-up `query-elements` call. Returns `undefined` when
329
+ * the element is no longer in the model (e.g. just deleted).
330
+ */
331
+ protected describeElement(aliasOrRealId: string): ElementIdentity | undefined {
332
+ const realId = this.aliasService.lookup(aliasOrRealId);
333
+ const element = this.modelState.index.find(realId);
334
+ return element ? this.describeResolvedElement(element) : undefined;
335
+ }
336
+
337
+ /** Describe an already-resolved {@link GModelElement} — skips the model-lookup round-trip. */
338
+ protected describeResolvedElement(element: GModelElement): ElementIdentity {
339
+ const label = this.labelProvider.getLabel(element)?.text;
340
+ // Conditional spread keeps `label` absent (not `undefined`) when the element has none —
341
+ // matches Zod's `.optional()` semantics so the structured payload is clean.
342
+ return { id: this.aliasService.alias(element.id), elementTypeId: element.type, ...(label !== undefined ? { label } : {}) };
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Diagram-scope tool base for **query-style** tools that read the model without mutating it
348
+ * (validate, get-selection, set-view, query-elements). Sibling of
349
+ * {@link OperationMcpDiagramToolHandler} — extend that one when the tool dispatches a
350
+ * model-mutating Operation.
351
+ *
352
+ * @experimental
353
+ */
354
+ @injectable()
355
+ export abstract class AbstractMcpDiagramToolHandler<
356
+ T extends McpDiagramScopedInput = McpDiagramScopedInput
357
+ > extends BaseMcpDiagramToolHandler<T> {
358
+ handle(params: T): Promise<McpToolResult> {
359
+ return this.execute(() => this.createResult(params));
360
+ }
361
+ }
362
+
363
+ /**
364
+ * Diagram-scope tool base for **operation-style** tools that mutate the model by dispatching a
365
+ * GLSP `Operation` (or other model-mutating `Action` like `UndoAction` / `RedoAction`) on
366
+ * behalf of the LLM — create, modify, delete, undo, redo. Sibling of
367
+ * {@link AbstractMcpDiagramToolHandler}.
368
+ *
369
+ * The base bakes in two pieces beyond the read sibling:
370
+ * - `@inject(ActionDispatcher)`. Every adopter extending this base dispatches, so the
371
+ * dispatcher belongs on the base, not in per-handler boilerplate.
372
+ * - Throws {@link McpReadOnlyError} when `modelState.isReadonly`, surfacing a hard failure
373
+ * to the LLM. The MCP-side gate is necessary even though core's `OperationActionHandler`
374
+ * checks readonly itself: core's gate is a *soft* warning (returns a `MessageAction`, the
375
+ * dispatch resolves successfully and the tool body would otherwise report success while
376
+ * nothing changed), and `UndoRedoActionHandler` doesn't gate readonly at all.
377
+ *
378
+ * Parallels core's `OperationHandler` (sibling to `ActionHandler`, not a refinement) — but
379
+ * note the role flip: core's `OperationHandler` is downstream of dispatch and only needs
380
+ * `ModelState`; ours is upstream of dispatch (the LLM-side handler that triggers the Operation)
381
+ * and so additionally injects `ActionDispatcher`.
382
+ *
383
+ * @experimental
384
+ */
385
+ @injectable()
386
+ export abstract class OperationMcpDiagramToolHandler<
387
+ T extends McpDiagramScopedInput = McpDiagramScopedInput
388
+ > extends BaseMcpDiagramToolHandler<T> {
389
+ @inject(ActionDispatcher) protected actionDispatcher: ActionDispatcher;
390
+
391
+ // Operation tools mutate the model — flip the read defaults. Concrete handlers override
392
+ // `destructiveHint` / `idempotentHint` (one line each) where it applies; the explicit `false`
393
+ // defaults below override the MCP spec's "true if unset" semantics so non-destructive,
394
+ // non-idempotent writes don't trigger overzealous client-side confirmation prompts.
395
+ override readonly readOnlyHint = false;
396
+ override readonly destructiveHint: boolean = false;
397
+ override readonly idempotentHint: boolean = false;
398
+
399
+ handle(params: T): Promise<McpToolResult> {
400
+ return this.execute(() => {
401
+ if (this.modelState.isReadonly) {
402
+ throw new McpReadOnlyError();
403
+ }
404
+ return this.createResult(params);
405
+ });
406
+ }
407
+
408
+ /**
409
+ * Convenience for tools that initiate a `RequestAction` round-trip (rather than the
410
+ * fire-and-forget operation dispatch this base is named for) — wraps
411
+ * {@link requestActionOrFail} with `this.actionDispatcher` and a default label of
412
+ * `this.name`. Pass an explicit label only when the tool handles multiple distinct
413
+ * round-trips and wants to disambiguate them in error messages.
414
+ */
415
+ protected requestAction<R extends ResponseAction>(request: RequestAction<R>, timeoutMs: number, label: string = this.name): Promise<R> {
416
+ return requestActionOrFail(this.actionDispatcher, request, timeoutMs, label);
417
+ }
418
+ }
419
+
420
+ /**
421
+ * Multi-binding identifier for diagram-scope tool handler constructors — covers both
422
+ * {@link AbstractMcpDiagramToolHandler} and {@link OperationMcpDiagramToolHandler}. Bound via
423
+ * `AbstractMcpDiagramModule.configureToolHandlers`; the per-GLSP-session registry initializer
424
+ * reads the list at session-open and resolves each constructor against the session container.
425
+ *
426
+ * Mirrors core's `OperationHandlerConstructor` pattern: instance fields (`readonly name = '…'`)
427
+ * are read off `new Constructor()` at MCP-session-init for SDK catalog registration, the same
428
+ * trick `bindOperations` uses to read `operationType`.
429
+ */
430
+ export type McpDiagramToolHandlerConstructor = interfaces.Newable<BaseMcpDiagramToolHandler<any>>;
431
+ export const McpDiagramToolHandlerConstructor = Symbol('McpDiagramToolHandlerConstructor');