@likec4/language-server 1.42.1 → 1.44.0

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/browser/package.json +1 -1
  2. package/browser-worker/package.json +1 -1
  3. package/dist/LikeC4LanguageServices.d.ts +12 -19
  4. package/dist/LikeC4LanguageServices.js +182 -0
  5. package/dist/Rpc.js +245 -0
  6. package/dist/ast.d.ts +10 -6
  7. package/dist/ast.js +253 -0
  8. package/dist/browser-worker.js +4 -0
  9. package/dist/browser.js +35 -0
  10. package/dist/bundled.js +42 -0
  11. package/dist/bundled.mjs +3830 -4172
  12. package/dist/documentation/documentation-provider.js +51 -0
  13. package/dist/documentation/index.js +1 -0
  14. package/dist/empty.js +2 -0
  15. package/dist/filesystem/ChokidarWatcher.js +97 -0
  16. package/dist/filesystem/FileSystemWatcher.js +14 -0
  17. package/dist/filesystem/LikeC4FileSystem.d.ts +1 -2
  18. package/dist/filesystem/LikeC4FileSystem.js +126 -0
  19. package/dist/filesystem/index.d.ts +26 -0
  20. package/dist/filesystem/index.js +29 -0
  21. package/dist/formatting/LikeC4Formatter.js +637 -0
  22. package/dist/formatting/utils.js +18 -0
  23. package/dist/generated/ast.d.ts +19 -3
  24. package/dist/generated/ast.js +2155 -0
  25. package/dist/generated/grammar.js +7 -0
  26. package/dist/generated/module.d.ts +6 -1
  27. package/dist/generated/module.js +27 -0
  28. package/dist/generated-lib/{icons.mjs → icons.js} +11 -7
  29. package/dist/index.d.ts +7 -0
  30. package/dist/index.js +53 -0
  31. package/dist/{likec4lib.mjs → likec4lib.js} +3 -3
  32. package/dist/logger.js +81 -0
  33. package/dist/lsp/CodeActionProvider.d.ts +14 -0
  34. package/dist/lsp/CodeActionProvider.js +33 -0
  35. package/dist/lsp/CodeLensProvider.js +44 -0
  36. package/dist/lsp/CompletionProvider.d.ts +3 -1
  37. package/dist/lsp/CompletionProvider.js +200 -0
  38. package/dist/lsp/DocumentHighlightProvider.js +10 -0
  39. package/dist/lsp/DocumentLinkProvider.js +58 -0
  40. package/dist/lsp/DocumentSymbolProvider.js +306 -0
  41. package/dist/lsp/HoverProvider.js +106 -0
  42. package/dist/lsp/RenameProvider.js +6 -0
  43. package/dist/lsp/SemanticTokenProvider.d.ts +5 -0
  44. package/dist/lsp/SemanticTokenProvider.js +257 -0
  45. package/dist/lsp/index.d.ts +1 -0
  46. package/dist/lsp/index.js +9 -0
  47. package/dist/mcp/MCPServerFactory.js +73 -0
  48. package/dist/mcp/NoopLikeC4MCPServer.js +17 -0
  49. package/dist/mcp/interfaces.js +5 -0
  50. package/dist/mcp/server/StdioLikeC4MCPServer.js +47 -0
  51. package/dist/mcp/server/StreamableLikeC4MCPServer.js +145 -0
  52. package/dist/mcp/server/WithMCPServer.js +56 -0
  53. package/dist/mcp/tools/_common.d.ts +8 -7
  54. package/dist/mcp/tools/_common.js +49 -0
  55. package/dist/mcp/tools/find-relationships.d.ts +7 -8
  56. package/dist/mcp/tools/find-relationships.js +150 -0
  57. package/dist/mcp/tools/list-projects.d.ts +3 -3
  58. package/dist/mcp/tools/list-projects.js +62 -0
  59. package/dist/mcp/tools/open-view.d.ts +6 -7
  60. package/dist/mcp/tools/open-view.js +52 -0
  61. package/dist/mcp/tools/read-deployment.d.ts +6 -7
  62. package/dist/mcp/tools/read-deployment.js +132 -0
  63. package/dist/mcp/tools/read-element.d.ts +6 -7
  64. package/dist/mcp/tools/read-element.js +194 -0
  65. package/dist/mcp/tools/read-project-summary.d.ts +5 -6
  66. package/dist/mcp/tools/read-project-summary.js +176 -0
  67. package/dist/mcp/tools/read-view.d.ts +6 -7
  68. package/dist/mcp/tools/read-view.js +203 -0
  69. package/dist/mcp/tools/search-element.d.ts +3 -3
  70. package/dist/mcp/tools/search-element.js +177 -0
  71. package/dist/mcp/utils.d.ts +2 -2
  72. package/dist/mcp/utils.js +48 -0
  73. package/dist/model/builder/MergedExtends.d.ts +2 -1
  74. package/dist/model/builder/MergedExtends.js +74 -0
  75. package/dist/model/builder/MergedSpecification.js +175 -0
  76. package/dist/model/builder/buildModel.js +176 -0
  77. package/dist/model/deployments-index.js +102 -0
  78. package/dist/model/fqn-index.js +250 -0
  79. package/dist/model/index.js +6 -0
  80. package/dist/model/model-builder.d.ts +13 -11
  81. package/dist/model/model-builder.js +234 -0
  82. package/dist/model/model-locator.d.ts +6 -5
  83. package/dist/model/model-locator.js +240 -0
  84. package/dist/model/model-parser-where.js +81 -0
  85. package/dist/model/model-parser.d.ts +318 -313
  86. package/dist/model/model-parser.js +119 -0
  87. package/dist/model/parser/Base.d.ts +3 -3
  88. package/dist/model/parser/Base.js +367 -0
  89. package/dist/model/parser/DeploymentModelParser.d.ts +3 -3
  90. package/dist/model/parser/DeploymentModelParser.js +176 -0
  91. package/dist/model/parser/DeploymentViewParser.d.ts +4 -4
  92. package/dist/model/parser/DeploymentViewParser.js +86 -0
  93. package/dist/model/parser/FqnRefParser.d.ts +3 -3
  94. package/dist/model/parser/FqnRefParser.js +382 -0
  95. package/dist/model/parser/GlobalsParser.d.ts +7 -7
  96. package/dist/model/parser/GlobalsParser.js +84 -0
  97. package/dist/model/parser/ImportsParser.d.ts +12 -13
  98. package/dist/model/parser/ImportsParser.js +24 -0
  99. package/dist/model/parser/ModelParser.d.ts +3 -3
  100. package/dist/model/parser/ModelParser.js +165 -0
  101. package/dist/model/parser/PredicatesParser.d.ts +3 -3
  102. package/dist/model/parser/PredicatesParser.js +45 -0
  103. package/dist/model/parser/SpecificationParser.d.ts +3 -3
  104. package/dist/model/parser/SpecificationParser.js +109 -0
  105. package/dist/model/parser/ValueConverter.js +12 -0
  106. package/dist/model/parser/ViewsParser.d.ts +4 -4
  107. package/dist/model/parser/ViewsParser.js +477 -0
  108. package/dist/model-change/ModelChanges.d.ts +6 -3
  109. package/dist/model-change/ModelChanges.js +102 -0
  110. package/dist/model-change/changeElementStyle.js +134 -0
  111. package/dist/model-change/changeViewLayout.d.ts +2 -2
  112. package/dist/model-change/changeViewLayout.js +28 -0
  113. package/dist/model-change/removeManualLayoutV1.d.ts +7 -0
  114. package/dist/model-change/removeManualLayoutV1.js +27 -0
  115. package/dist/module.d.ts +10 -5
  116. package/dist/module.js +143 -0
  117. package/dist/protocol.d.ts +1 -17
  118. package/dist/protocol.js +114 -0
  119. package/dist/references/index.js +3 -0
  120. package/dist/references/name-provider.js +37 -0
  121. package/dist/references/scope-computation.js +288 -0
  122. package/dist/references/scope-provider.d.ts +3 -3
  123. package/dist/references/scope-provider.js +242 -0
  124. package/dist/shared/NodeKindProvider.js +57 -0
  125. package/dist/shared/{WorkspaceSymbolProvider.mjs → WorkspaceSymbolProvider.js} +1 -1
  126. package/dist/shared/index.js +2 -0
  127. package/dist/test/index.js +1 -0
  128. package/dist/test/testServices.d.ts +16 -16
  129. package/dist/test/testServices.js +210 -0
  130. package/dist/utils/disposable.js +26 -0
  131. package/dist/utils/elementRef.d.ts +1 -1
  132. package/dist/utils/elementRef.js +27 -0
  133. package/dist/utils/fqnRef.js +63 -0
  134. package/dist/utils/index.js +35 -0
  135. package/dist/utils/printDocs.js +1 -0
  136. package/dist/utils/projectId.js +16 -0
  137. package/dist/utils/stringHash.js +5 -0
  138. package/dist/validation/DocumentValidator.js +17 -0
  139. package/dist/validation/_shared.js +26 -0
  140. package/dist/validation/deployment-checks.js +140 -0
  141. package/dist/validation/dynamic-view.js +67 -0
  142. package/dist/validation/element-ref.js +12 -0
  143. package/dist/validation/element.js +49 -0
  144. package/dist/validation/imports.js +46 -0
  145. package/dist/validation/index.d.ts +1 -1
  146. package/dist/validation/index.js +157 -0
  147. package/dist/validation/property-checks.js +108 -0
  148. package/dist/validation/relation.js +55 -0
  149. package/dist/validation/specification.js +190 -0
  150. package/dist/validation/view-predicates/fqn-expr-with.js +43 -0
  151. package/dist/validation/view-predicates/fqn-ref-expr.js +51 -0
  152. package/dist/validation/view-predicates/incoming.js +16 -0
  153. package/dist/validation/view-predicates/index.js +6 -0
  154. package/dist/validation/view-predicates/outgoing.js +20 -0
  155. package/dist/validation/view-predicates/relation-expr.js +46 -0
  156. package/dist/validation/view-predicates/relation-with.js +16 -0
  157. package/dist/validation/view.d.ts +1 -1
  158. package/dist/validation/view.js +42 -0
  159. package/dist/view-utils/assignNavigateTo.js +27 -0
  160. package/dist/view-utils/index.d.ts +1 -0
  161. package/dist/view-utils/index.js +2 -0
  162. package/dist/view-utils/manual-layout.d.ts +6 -0
  163. package/dist/view-utils/manual-layout.js +151 -0
  164. package/dist/views/ConfigurableLayouter.js +51 -0
  165. package/dist/views/LikeC4ManualLayouts.d.ts +28 -0
  166. package/dist/views/LikeC4ManualLayouts.js +132 -0
  167. package/dist/views/{likec4-views.d.ts → LikeC4Views.d.ts} +9 -8
  168. package/dist/views/LikeC4Views.js +200 -0
  169. package/dist/views/index.d.ts +4 -1
  170. package/dist/views/index.js +11 -0
  171. package/dist/workspace/AstNodeDescriptionProvider.js +15 -0
  172. package/dist/workspace/IndexManager.js +21 -0
  173. package/dist/workspace/LangiumDocuments.d.ts +1 -1
  174. package/dist/workspace/LangiumDocuments.js +58 -0
  175. package/dist/workspace/ProjectsManager.d.ts +8 -3
  176. package/dist/workspace/ProjectsManager.js +373 -0
  177. package/dist/workspace/WorkspaceManager.d.ts +3 -2
  178. package/dist/workspace/WorkspaceManager.js +93 -0
  179. package/dist/workspace/index.js +5 -0
  180. package/likec4lib/package.json +1 -1
  181. package/package.json +32 -31
  182. package/protocol/package.json +1 -1
  183. package/dist/LikeC4LanguageServices.mjs +0 -197
  184. package/dist/Rpc.mjs +0 -296
  185. package/dist/ast.mjs +0 -221
  186. package/dist/browser-worker.mjs +0 -2
  187. package/dist/browser.mjs +0 -32
  188. package/dist/documentation/documentation-provider.mjs +0 -48
  189. package/dist/documentation/index.mjs +0 -1
  190. package/dist/empty.mjs +0 -1
  191. package/dist/filesystem/ChokidarWatcher.mjs +0 -68
  192. package/dist/filesystem/FileSystemWatcher.mjs +0 -11
  193. package/dist/filesystem/LikeC4FileSystem.mjs +0 -64
  194. package/dist/filesystem/index.mjs +0 -19
  195. package/dist/formatting/LikeC4Formatter.mjs +0 -511
  196. package/dist/formatting/utils.mjs +0 -15
  197. package/dist/generated/ast.mjs +0 -2118
  198. package/dist/generated/grammar.mjs +0 -3
  199. package/dist/generated/module.mjs +0 -23
  200. package/dist/index.mjs +0 -50
  201. package/dist/logger.mjs +0 -82
  202. package/dist/lsp/CodeLensProvider.mjs +0 -42
  203. package/dist/lsp/CompletionProvider.mjs +0 -208
  204. package/dist/lsp/DocumentHighlightProvider.mjs +0 -10
  205. package/dist/lsp/DocumentLinkProvider.mjs +0 -53
  206. package/dist/lsp/DocumentSymbolProvider.mjs +0 -287
  207. package/dist/lsp/HoverProvider.mjs +0 -104
  208. package/dist/lsp/RenameProvider.mjs +0 -6
  209. package/dist/lsp/SemanticTokenProvider.mjs +0 -350
  210. package/dist/lsp/index.mjs +0 -7
  211. package/dist/mcp/MCPServerFactory.mjs +0 -70
  212. package/dist/mcp/NoopLikeC4MCPServer.mjs +0 -17
  213. package/dist/mcp/interfaces.mjs +0 -4
  214. package/dist/mcp/server/StdioLikeC4MCPServer.mjs +0 -46
  215. package/dist/mcp/server/StreamableLikeC4MCPServer.mjs +0 -153
  216. package/dist/mcp/server/WithMCPServer.mjs +0 -58
  217. package/dist/mcp/tools/_common.mjs +0 -42
  218. package/dist/mcp/tools/find-relationships.mjs +0 -151
  219. package/dist/mcp/tools/list-projects.mjs +0 -62
  220. package/dist/mcp/tools/open-view.mjs +0 -52
  221. package/dist/mcp/tools/read-deployment.mjs +0 -130
  222. package/dist/mcp/tools/read-element.mjs +0 -198
  223. package/dist/mcp/tools/read-project-summary.mjs +0 -178
  224. package/dist/mcp/tools/read-view.mjs +0 -205
  225. package/dist/mcp/tools/search-element.mjs +0 -171
  226. package/dist/mcp/utils.mjs +0 -47
  227. package/dist/model/builder/MergedExtends.mjs +0 -67
  228. package/dist/model/builder/MergedSpecification.mjs +0 -205
  229. package/dist/model/builder/assignTagColors.d.ts +0 -7
  230. package/dist/model/builder/assignTagColors.mjs +0 -51
  231. package/dist/model/builder/buildModel.mjs +0 -226
  232. package/dist/model/deployments-index.mjs +0 -100
  233. package/dist/model/fqn-index.mjs +0 -243
  234. package/dist/model/index.mjs +0 -6
  235. package/dist/model/model-builder.mjs +0 -285
  236. package/dist/model/model-locator.mjs +0 -239
  237. package/dist/model/model-parser-where.mjs +0 -81
  238. package/dist/model/model-parser.mjs +0 -127
  239. package/dist/model/parser/Base.mjs +0 -342
  240. package/dist/model/parser/DeploymentModelParser.mjs +0 -212
  241. package/dist/model/parser/DeploymentViewParser.mjs +0 -95
  242. package/dist/model/parser/FqnRefParser.mjs +0 -398
  243. package/dist/model/parser/GlobalsParser.mjs +0 -82
  244. package/dist/model/parser/ImportsParser.mjs +0 -28
  245. package/dist/model/parser/ModelParser.mjs +0 -190
  246. package/dist/model/parser/PredicatesParser.mjs +0 -45
  247. package/dist/model/parser/SpecificationParser.mjs +0 -120
  248. package/dist/model/parser/ValueConverter.mjs +0 -12
  249. package/dist/model/parser/ViewsParser.mjs +0 -490
  250. package/dist/model-change/ModelChanges.mjs +0 -89
  251. package/dist/model-change/changeElementStyle.mjs +0 -143
  252. package/dist/model-change/changeViewLayout.mjs +0 -32
  253. package/dist/model-change/saveManualLayout.d.ts +0 -11
  254. package/dist/model-change/saveManualLayout.mjs +0 -27
  255. package/dist/module.mjs +0 -180
  256. package/dist/protocol.mjs +0 -65
  257. package/dist/references/index.mjs +0 -3
  258. package/dist/references/name-provider.mjs +0 -39
  259. package/dist/references/scope-computation.mjs +0 -312
  260. package/dist/references/scope-provider.mjs +0 -239
  261. package/dist/shared/NodeKindProvider.mjs +0 -110
  262. package/dist/shared/index.mjs +0 -2
  263. package/dist/test/index.mjs +0 -1
  264. package/dist/test/testServices.mjs +0 -200
  265. package/dist/utils/disposable.mjs +0 -25
  266. package/dist/utils/elementRef.mjs +0 -20
  267. package/dist/utils/fqnRef.mjs +0 -57
  268. package/dist/utils/index.mjs +0 -33
  269. package/dist/utils/printDocs.mjs +0 -1
  270. package/dist/utils/projectId.mjs +0 -16
  271. package/dist/utils/stringHash.mjs +0 -5
  272. package/dist/validation/DocumentValidator.mjs +0 -16
  273. package/dist/validation/_shared.mjs +0 -25
  274. package/dist/validation/deployment-checks.mjs +0 -146
  275. package/dist/validation/dynamic-view.mjs +0 -67
  276. package/dist/validation/element-ref.mjs +0 -12
  277. package/dist/validation/element.mjs +0 -50
  278. package/dist/validation/imports.mjs +0 -25
  279. package/dist/validation/index.mjs +0 -180
  280. package/dist/validation/property-checks.mjs +0 -107
  281. package/dist/validation/relation.mjs +0 -53
  282. package/dist/validation/specification.mjs +0 -173
  283. package/dist/validation/view-predicates/fqn-expr-with.mjs +0 -43
  284. package/dist/validation/view-predicates/fqn-ref-expr.mjs +0 -53
  285. package/dist/validation/view-predicates/incoming.mjs +0 -16
  286. package/dist/validation/view-predicates/index.mjs +0 -6
  287. package/dist/validation/view-predicates/outgoing.mjs +0 -20
  288. package/dist/validation/view-predicates/relation-expr.mjs +0 -39
  289. package/dist/validation/view-predicates/relation-with.mjs +0 -16
  290. package/dist/validation/view.mjs +0 -25
  291. package/dist/view-utils/assignNavigateTo.mjs +0 -25
  292. package/dist/view-utils/index.mjs +0 -1
  293. package/dist/view-utils/manual-layout.mjs +0 -99
  294. package/dist/views/configurable-layouter.mjs +0 -51
  295. package/dist/views/index.mjs +0 -1
  296. package/dist/views/likec4-views.mjs +0 -166
  297. package/dist/workspace/AstNodeDescriptionProvider.mjs +0 -17
  298. package/dist/workspace/IndexManager.mjs +0 -17
  299. package/dist/workspace/LangiumDocuments.mjs +0 -53
  300. package/dist/workspace/ProjectsManager.mjs +0 -360
  301. package/dist/workspace/WorkspaceManager.mjs +0 -83
  302. package/dist/workspace/index.mjs +0 -5
  303. /package/dist/views/{configurable-layouter.d.ts → ConfigurableLayouter.d.ts} +0 -0
@@ -1,7 +1,12 @@
1
1
  import type { AstNode } from 'langium';
2
2
  import { type SemanticTokenAcceptor, AbstractSemanticTokenProvider } from 'langium/lsp';
3
+ import type { LikeC4Services } from '../module';
3
4
  export declare class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
5
+ private rules;
6
+ constructor(services: LikeC4Services);
7
+ protected initRules(): void;
4
8
  protected highlightElement(node: AstNode, acceptor: SemanticTokenAcceptor): void | undefined | 'prune';
5
9
  private highlightNameAndKind;
6
10
  private highlightView;
11
+ private mark;
7
12
  }
@@ -0,0 +1,257 @@
1
+ import { invariant, isAnyOf, nonNullable } from '@likec4/core/utils';
2
+ import { AbstractSemanticTokenProvider, } from 'langium/lsp';
3
+ import { isTruthy } from 'remeda';
4
+ import { SemanticTokenModifiers, SemanticTokenTypes } from 'vscode-languageserver-types';
5
+ import { ast } from '../ast';
6
+ import { logger } from '../logger';
7
+ const SemanticTypes = { ...SemanticTokenTypes };
8
+ const SemanticModifiers = { ...SemanticTokenModifiers };
9
+ function createSemanticTypeMethods(applyHighlight) {
10
+ const modifier = [];
11
+ const self = new Proxy({}, {
12
+ get(_, prop) {
13
+ if (prop === 'modifier') {
14
+ return (mod) => {
15
+ modifier.push(mod);
16
+ return self;
17
+ };
18
+ }
19
+ if (prop in SemanticModifiers) {
20
+ modifier.push(SemanticModifiers[prop]);
21
+ return self;
22
+ }
23
+ if (prop in SemanticTypes) {
24
+ return () => applyHighlight(SemanticTypes[prop], modifier);
25
+ }
26
+ throw new Error(`Unknown semantic token type or modifier: ${prop}`);
27
+ },
28
+ });
29
+ return self;
30
+ }
31
+ const PRUNE = 'Stop Highlighting';
32
+ /**
33
+ * Used to stop further highlighting for the current node (processing of its children
34
+ */
35
+ const stopHighlight = () => {
36
+ throw PRUNE;
37
+ };
38
+ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
39
+ rules = [];
40
+ constructor(services) {
41
+ super(services);
42
+ this.initRules();
43
+ }
44
+ initRules() {
45
+ this.rules = [];
46
+ const when = (predicate, highlightFn) => {
47
+ const rule = { predicate, highlightFn };
48
+ this.rules.push(rule);
49
+ };
50
+ when(ast.isRelationshipKind, mark => {
51
+ mark.property('name').function();
52
+ });
53
+ when(isAnyOf(ast.isRelation, ast.isOutgoingRelationExpr, ast.isDeploymentRelation), mark => {
54
+ mark.property('kind').function();
55
+ });
56
+ when(ast.isLibIcon, mark => {
57
+ mark.property('name').definition.function();
58
+ stopHighlight();
59
+ });
60
+ when(isAnyOf(ast.isNavigateToProperty, ast.isRelationNavigateToProperty), mark => {
61
+ mark.property('value').readonly.definition.interface();
62
+ stopHighlight();
63
+ });
64
+ when(isAnyOf(ast.isFqnRefExpr, ast.isWildcardExpression), mark => {
65
+ mark.cst().readonly.definition.variable();
66
+ stopHighlight();
67
+ });
68
+ when(ast.isTagRef, mark => {
69
+ mark.cst().type();
70
+ stopHighlight();
71
+ });
72
+ when(ast.isRelationKindDotRef, mark => {
73
+ mark.cst().function();
74
+ stopHighlight();
75
+ });
76
+ when(ast.isWhereRelationKind, mark => {
77
+ if (isTruthy(mark.node.value)) {
78
+ mark.property('value').function();
79
+ }
80
+ });
81
+ when(isAnyOf(ast.isWhereElement, ast.isWhereRelation), mark => {
82
+ if (isTruthy(mark.node.value)) {
83
+ mark.property('value').readonly.definition.type();
84
+ }
85
+ });
86
+ when(isAnyOf(ast.isWhereRelationParticipantKind, ast.isWhereRelationParticipantTag), mark => {
87
+ mark.property('participant').keyword();
88
+ });
89
+ when(ast.isElementKindExpression, mark => {
90
+ if (isTruthy(mark.node.kind)) {
91
+ mark.property('kind').definition.type();
92
+ }
93
+ });
94
+ when(isAnyOf(ast.isGlobalStyleGroup, ast.isGlobalStyle), mark => {
95
+ mark.property('id').readonly.definition.variable();
96
+ });
97
+ when(ast.isViewRuleGlobalStyle, mark => {
98
+ mark.property('style').readonly.definition.variable();
99
+ });
100
+ when(isAnyOf(ast.isGlobalPredicateGroup, ast.isGlobalDynamicPredicateGroup), mark => {
101
+ mark.property('name').readonly.definition.variable();
102
+ });
103
+ when(ast.isViewRuleGlobalPredicateRef, mark => {
104
+ mark.property('predicate').readonly.definition.variable();
105
+ });
106
+ when(ast.isElementTagExpression, mark => {
107
+ if (isTruthy(mark.node.tag)) {
108
+ mark.property('tag').definition.type();
109
+ }
110
+ });
111
+ when(isAnyOf(ast.isFqnRef, ast.isStrictFqnRef), mark => {
112
+ mark.property('value').readonly.definition.variable();
113
+ if (!mark.node.parent) {
114
+ stopHighlight();
115
+ }
116
+ });
117
+ when(ast.isStrictFqnElementRef, mark => {
118
+ mark.property('el').readonly.definition.variable();
119
+ if (!mark.node.parent) {
120
+ stopHighlight();
121
+ }
122
+ });
123
+ when(ast.isSpecificationColor, mark => {
124
+ mark.keyword('color').keyword();
125
+ mark.property('name').readonly.declaration.type();
126
+ });
127
+ when(ast.isSpecificationTag, mark => {
128
+ if (isTruthy(mark.node.color)) {
129
+ mark.keyword('color').property();
130
+ }
131
+ });
132
+ when(isAnyOf(ast.isSpecificationElementKind, ast.isSpecificationRelationshipKind, ast.isSpecificationDeploymentNodeKind), mark => {
133
+ mark.property('kind').readonly.declaration.type();
134
+ });
135
+ when(ast.isTag, mark => {
136
+ mark.property('name').definition.type();
137
+ });
138
+ when(ast.isOpacityProperty, mark => {
139
+ mark.property('value').number();
140
+ });
141
+ when(ast.isIconProperty, mark => {
142
+ if (mark.node.libicon || mark.node.value === 'none') {
143
+ mark.property(mark.node.libicon ? 'libicon' : 'value').defaultLibrary.enum();
144
+ return;
145
+ }
146
+ mark.property('value').string();
147
+ });
148
+ when(ast.isLinkProperty, mark => {
149
+ if (isTruthy(mark.node.value)) {
150
+ mark.property('value').string();
151
+ }
152
+ });
153
+ when(ast.isColorProperty, mark => {
154
+ if (isTruthy(mark.node.customColor)) {
155
+ mark.property('customColor').enum();
156
+ }
157
+ if (isTruthy(mark.node.themeColor)) {
158
+ mark.property('themeColor').enum();
159
+ }
160
+ });
161
+ when(isAnyOf(ast.isShapeProperty, ast.isArrowProperty, ast.isLineProperty, ast.isBorderProperty, ast.isSizeProperty, ast.isDynamicViewDisplayVariantProperty), mark => {
162
+ if (isTruthy(mark.node.value)) {
163
+ mark.property('value').enum();
164
+ }
165
+ });
166
+ }
167
+ highlightElement(node, acceptor) {
168
+ try {
169
+ if (isAnyOf(ast.isElement, ast.isDeploymentNode, ast.isDeployedInstance)(node)) {
170
+ return this.highlightNameAndKind(node);
171
+ }
172
+ if (ast.isLikeC4View(node)) {
173
+ return this.highlightView(node);
174
+ }
175
+ if (ast.isAnyProperty(node) &&
176
+ !isAnyOf(ast.isMetadataProperty, ast.isElementStyleProperty, ast.isRelationStyleProperty)(node)) {
177
+ invariant(node.key);
178
+ acceptor({
179
+ node,
180
+ property: 'key',
181
+ type: SemanticTokenTypes.property,
182
+ });
183
+ }
184
+ for (const { predicate, highlightFn } of this.rules) {
185
+ if (predicate(node)) {
186
+ highlightFn(this.mark(node));
187
+ break;
188
+ }
189
+ }
190
+ }
191
+ catch (error) {
192
+ if (error === PRUNE) {
193
+ return 'prune';
194
+ }
195
+ logger.warn(`Error highlighting node of type ${node._type}`, { error });
196
+ }
197
+ }
198
+ highlightNameAndKind(node) {
199
+ const mark = this.mark(node);
200
+ mark.property('name').declaration.readonly.variable();
201
+ if (!ast.isDeployedInstance(node)) {
202
+ this.mark(node).property('kind').keyword();
203
+ }
204
+ if (ast.isElement(node)) {
205
+ if (node.props.length > 0) {
206
+ this.mark(node).property('props').string();
207
+ }
208
+ return;
209
+ }
210
+ // This is DeploymentNode
211
+ if (node.title) {
212
+ this.mark(node).property('title').string();
213
+ }
214
+ }
215
+ highlightView(node) {
216
+ if (node.name) {
217
+ const mark = this.mark(node);
218
+ mark.property('name')
219
+ .modifier('local')
220
+ .declaration
221
+ .readonly
222
+ .interface();
223
+ }
224
+ }
225
+ mark(node) {
226
+ const cst = (cstNode) => {
227
+ return createSemanticTypeMethods((type, modifier) => this.highlightToken({
228
+ range: nonNullable(cstNode ?? node.$cstNode, 'AST node has no CST node').range,
229
+ type,
230
+ modifier,
231
+ }));
232
+ };
233
+ const keyword = (keyword) => {
234
+ return createSemanticTypeMethods((type, modifier) => this.highlightKeyword({
235
+ node,
236
+ keyword,
237
+ type,
238
+ modifier,
239
+ }));
240
+ };
241
+ const property = (property, index) => {
242
+ return createSemanticTypeMethods((type, modifier) => this.highlightProperty({
243
+ node,
244
+ property,
245
+ type,
246
+ modifier,
247
+ ...(index !== undefined ? { index } : {}),
248
+ }));
249
+ };
250
+ return {
251
+ node,
252
+ cst,
253
+ keyword,
254
+ property,
255
+ };
256
+ }
257
+ }
@@ -4,4 +4,5 @@ export * from './DocumentHighlightProvider';
4
4
  export * from './DocumentLinkProvider';
5
5
  export * from './DocumentSymbolProvider';
6
6
  export * from './HoverProvider';
7
+ export * from './CodeActionProvider';
7
8
  export * from './SemanticTokenProvider';
@@ -0,0 +1,9 @@
1
+ export * from './CodeLensProvider';
2
+ export * from './CompletionProvider';
3
+ export * from './DocumentHighlightProvider';
4
+ export * from './DocumentLinkProvider';
5
+ export * from './DocumentSymbolProvider';
6
+ export * from './HoverProvider';
7
+ // export * from './RenameProvider'
8
+ export * from './CodeActionProvider';
9
+ export * from './SemanticTokenProvider';
@@ -0,0 +1,73 @@
1
+ import { loggable } from '@likec4/log';
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import packageJson from '../../package.json' with { type: 'json' };
4
+ import { logger } from '../logger';
5
+ import { findRelationships } from './tools/find-relationships';
6
+ import { listProjects } from './tools/list-projects';
7
+ import { openView } from './tools/open-view';
8
+ import { readDeployment } from './tools/read-deployment';
9
+ import { readElement } from './tools/read-element';
10
+ import { readProjectSummary } from './tools/read-project-summary';
11
+ import { readView } from './tools/read-view';
12
+ import { searchElement } from './tools/search-element';
13
+ export class LikeC4MCPServerFactory {
14
+ services;
15
+ constructor(services) {
16
+ this.services = services;
17
+ }
18
+ create(options) {
19
+ const isInEditor = this.services.shared.lsp.Connection !== undefined;
20
+ const mcp = new McpServer({
21
+ name: 'LikeC4',
22
+ version: packageJson.version,
23
+ }, {
24
+ instructions: `LikeC4 MCP – query and navigate LikeC4 models.
25
+
26
+ Conventions:
27
+ - All tools are read-only and idempotent.
28
+ - "project" is optional and defaults to "default".
29
+
30
+ Available tools:
31
+ - list-projects — List all LikeC4 projects in the workspace.
32
+ - read-project-summary — Project specification (element kinds, deployment node kinds, tags, metadata keys), all elements, deployment nodes and views. Input: { project? }.
33
+ - search-element — Search elements and deployment nodes across all projects by id/title/kind/shape/tags/metadata. Input: { search }.
34
+ - read-element — Full element details including relationships, includedInViews, deployedInstances, metadata and sourceLocation. Input: { id, project? }.
35
+ - read-deployment — Details of a deployment node or deployed instance. Input: { id, project? }.
36
+ - read-view — Full view details (nodes/edges) and sourceLocation. Input: { viewId, project? }.
37
+ - find-relationships — Direct and indirect relationships between two elements in a project. Input: { element1, element2, project? }.
38
+ ${isInEditor
39
+ ? '- open-view — Opens the LikeC4 view panel in the editor. Triggers UI; at most one preview panel at a time. Input: { viewId, project? }.'
40
+ : ''}
41
+
42
+ Instructions:
43
+ - Identify the project first
44
+ - Use "search-element" to find elements by id/title/kind/shape/tags/metadata and select the project
45
+ - Use "read-project-summary" to find all elements and deployment nodes inside the project, what kinds, tags, metadata keys are available
46
+ - Use "list-projects" to list all available projects
47
+ - If response returns "sourceLocation", provide link to this location in the editor
48
+
49
+ Full documentation: https://likec4.dev/llms-full.txt
50
+ `,
51
+ enforceStrictCapabilities: true,
52
+ ...options,
53
+ capabilities: {
54
+ tools: {},
55
+ ...options?.capabilities,
56
+ },
57
+ });
58
+ mcp.registerTool(...listProjects(this.services.likec4.LanguageServices));
59
+ mcp.registerTool(...readProjectSummary(this.services.likec4.LanguageServices));
60
+ mcp.registerTool(...readElement(this.services.likec4.LanguageServices));
61
+ mcp.registerTool(...readDeployment(this.services.likec4.LanguageServices));
62
+ mcp.registerTool(...readView(this.services.likec4.LanguageServices));
63
+ mcp.registerTool(...searchElement(this.services.likec4.LanguageServices));
64
+ mcp.registerTool(...findRelationships(this.services.likec4.LanguageServices));
65
+ if (isInEditor) {
66
+ mcp.registerTool(...openView(this.services.likec4.LanguageServices));
67
+ }
68
+ mcp.server.onerror = (err) => {
69
+ logger.error(loggable(err));
70
+ };
71
+ return mcp;
72
+ }
73
+ }
@@ -0,0 +1,17 @@
1
+ export class NoopLikeC4MCPServer {
2
+ get mcp() {
3
+ throw new Error('NoopLikeC4MCPServer does not have a McpServer');
4
+ }
5
+ get isStarted() {
6
+ return false;
7
+ }
8
+ get port() {
9
+ return NaN;
10
+ }
11
+ start() {
12
+ return Promise.resolve();
13
+ }
14
+ stop() {
15
+ return Promise.resolve();
16
+ }
17
+ }
@@ -0,0 +1,5 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { NoopLikeC4MCPServer } from './NoopLikeC4MCPServer';
3
+ export const NoMCPServer = {
4
+ mcpServer: () => new NoopLikeC4MCPServer(),
5
+ };
@@ -0,0 +1,47 @@
1
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
+ import { logger } from '../utils';
3
+ export class StdioLikeC4MCPServer {
4
+ services;
5
+ transport = undefined;
6
+ _mcp = undefined;
7
+ constructor(services) {
8
+ this.services = services;
9
+ }
10
+ get mcp() {
11
+ if (!this._mcp) {
12
+ throw new Error('MCP server is not started');
13
+ }
14
+ return this._mcp;
15
+ }
16
+ get isStarted() {
17
+ return this.transport !== undefined;
18
+ }
19
+ get port() {
20
+ return NaN;
21
+ }
22
+ async dispose() {
23
+ await this.stop();
24
+ }
25
+ async start() {
26
+ if (this.transport) {
27
+ return;
28
+ }
29
+ logger.info('Starting MCP stdio server');
30
+ this._mcp = this.services.mcp.ServerFactory.create();
31
+ this.transport = new StdioServerTransport();
32
+ await this._mcp.connect(this.transport);
33
+ logger.info('LikeC4 MCP Server running on stdio');
34
+ }
35
+ async stop() {
36
+ if (!this.transport) {
37
+ return;
38
+ }
39
+ logger.info('Stopping MCP stdio server');
40
+ await this.transport.close();
41
+ if (this._mcp) {
42
+ await this._mcp.close();
43
+ }
44
+ this._mcp = undefined;
45
+ this.transport = undefined;
46
+ }
47
+ }
@@ -0,0 +1,145 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { promiseNextTick } from '@likec4/core/utils';
3
+ import { loggable } from '@likec4/log';
4
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
5
+ import { toFetchResponse, toReqRes } from 'fetch-to-node';
6
+ import { Hono } from 'hono';
7
+ import { logger } from '../utils';
8
+ export class StreamableLikeC4MCPServer {
9
+ services;
10
+ _port;
11
+ // Store transports by session ID to send notifications
12
+ server = undefined;
13
+ constructor(services, _port = 33335) {
14
+ this.services = services;
15
+ this._port = _port;
16
+ }
17
+ get mcp() {
18
+ throw new Error('StreamableLikeC4MCPServer has access to McpServer only during the request');
19
+ }
20
+ get isStarted() {
21
+ return this.server?.listening === true;
22
+ }
23
+ get port() {
24
+ return this._port;
25
+ }
26
+ async dispose() {
27
+ await this.stop();
28
+ }
29
+ async start(port = this._port) {
30
+ try {
31
+ if (this.server) {
32
+ if (this.port === port) {
33
+ return;
34
+ }
35
+ await this.stop();
36
+ }
37
+ logger.info('Starting MCP server on port {port}', { port });
38
+ this._port = port;
39
+ await promiseNextTick();
40
+ const app = new Hono()
41
+ .post('/mcp', async (c) => {
42
+ const { req, res } = toReqRes(c.req.raw);
43
+ const server = this.services.mcp.ServerFactory.create();
44
+ try {
45
+ const transport = new StreamableHTTPServerTransport({
46
+ sessionIdGenerator: undefined,
47
+ });
48
+ // Added for extra debuggability
49
+ transport.onerror = (err) => {
50
+ logger.error(loggable(err));
51
+ };
52
+ await server.connect(transport);
53
+ await transport.handleRequest(req, res, await c.req.json());
54
+ res.on('close', async () => {
55
+ logger.debug('Request closed');
56
+ await transport.close();
57
+ await server.close();
58
+ });
59
+ return toFetchResponse(res);
60
+ }
61
+ catch (e) {
62
+ logger.error(loggable(e));
63
+ return c.json({
64
+ jsonrpc: '2.0',
65
+ error: {
66
+ code: -32603,
67
+ message: 'Internal server error',
68
+ },
69
+ id: null,
70
+ }, { status: 500 });
71
+ }
72
+ })
73
+ .get('/mcp', async (c) => {
74
+ logger.debug('Received GET MCP request');
75
+ return c.json({
76
+ jsonrpc: '2.0',
77
+ error: {
78
+ code: -32000,
79
+ message: 'Method not allowed.',
80
+ },
81
+ id: null,
82
+ }, { status: 405 });
83
+ })
84
+ .delete('/mcp', async (c) => {
85
+ logger.debug('Received DELETE MCP request');
86
+ return c.json({
87
+ jsonrpc: '2.0',
88
+ error: {
89
+ code: -32000,
90
+ message: 'Method not allowed.',
91
+ },
92
+ id: null,
93
+ }, { status: 405 });
94
+ })
95
+ .notFound((c) => {
96
+ logger.debug(`${c.req.method} ${c.req.url} not found`);
97
+ return c.json({
98
+ jsonrpc: '2.0',
99
+ error: {
100
+ code: -32000,
101
+ message: 'Method not found.',
102
+ },
103
+ id: null,
104
+ }, { status: 404 });
105
+ })
106
+ .onError((e, c) => {
107
+ logger.error(loggable(e));
108
+ return c.json({
109
+ jsonrpc: '2.0',
110
+ error: {
111
+ code: -32603,
112
+ message: 'Internal server error',
113
+ },
114
+ id: null,
115
+ }, { status: 500 });
116
+ });
117
+ this.server = serve({
118
+ fetch: app.fetch,
119
+ hostname: '0.0.0.0',
120
+ port: this._port,
121
+ }, (info) => logger.info('MCP server ready at http://0.0.0.0:{port}/mcp', { port: info.port }));
122
+ }
123
+ catch (err) {
124
+ logger.warn('Failed to start MCP server', { err });
125
+ return Promise.reject(err);
126
+ }
127
+ }
128
+ stop() {
129
+ const server = this.server;
130
+ if (!server) {
131
+ return Promise.resolve();
132
+ }
133
+ logger.info('Stopping MCP server');
134
+ this.server = undefined;
135
+ return new Promise((resolve) => {
136
+ server.close((err) => {
137
+ if (err) {
138
+ logger.error('Failed to stop MCP server', { err });
139
+ }
140
+ logger.info('MCP server stopped');
141
+ resolve();
142
+ });
143
+ });
144
+ }
145
+ }
@@ -0,0 +1,56 @@
1
+ import { loggable } from '@likec4/log';
2
+ import { isError } from 'remeda';
3
+ import { logger } from '../utils';
4
+ import { StdioLikeC4MCPServer } from './StdioLikeC4MCPServer';
5
+ import { StreamableLikeC4MCPServer } from './StreamableLikeC4MCPServer';
6
+ const streamableLikeC4MCPServer = (services, defaultPort = 33335) => {
7
+ logger.debug('Creating StreamableLikeC4MCPServer');
8
+ const server = new StreamableLikeC4MCPServer(services, defaultPort);
9
+ const langId = services.LanguageMetaData.languageId;
10
+ const connection = services.shared.lsp.Connection;
11
+ services.shared.workspace.ConfigurationProvider.onConfigurationSectionUpdate((update) => {
12
+ if (update.section !== langId) {
13
+ logger.warn('Unexpected configuration update: {update}', { update });
14
+ return;
15
+ }
16
+ logger.debug('Configuration update: {update}', { update });
17
+ const { enabled = false, port = defaultPort, } = update.configuration.mcp;
18
+ if (!enabled) {
19
+ void server.stop();
20
+ return;
21
+ }
22
+ void Promise.resolve()
23
+ .then(() => server.start(port))
24
+ .then(() => {
25
+ connection?.telemetry?.logEvent({
26
+ eventName: 'mcp-server-started',
27
+ mcpPort: port,
28
+ });
29
+ })
30
+ .catch(err => {
31
+ const message = isError(err) ? err.message : undefined;
32
+ connection?.telemetry?.logEvent({
33
+ eventName: 'mcp-server-start-failed',
34
+ mcpPort: port,
35
+ ...message && { message },
36
+ });
37
+ logger.error('Failed to start LikeC4 MCP Server', { err });
38
+ if (connection) {
39
+ connection.window.showErrorMessage(`LikeC4: Failed to start MCP Server\n\n${loggable(err)}`);
40
+ }
41
+ });
42
+ });
43
+ return server;
44
+ };
45
+ const stdioLikeC4MCPServer = (services) => {
46
+ return new StdioLikeC4MCPServer(services);
47
+ };
48
+ export const WithMCPServer = (type = 'sse') => ({
49
+ mcpServer: (services) => {
50
+ if (type === 'stdio') {
51
+ return stdioLikeC4MCPServer(services);
52
+ }
53
+ const port = typeof type === 'object' ? type.port : 33335;
54
+ return streamableLikeC4MCPServer(services, port);
55
+ },
56
+ });
@@ -1,5 +1,6 @@
1
1
  import type { LikeC4ViewModel } from '@likec4/core/model';
2
- import z from 'zod';
2
+ import type { ProjectId } from '@likec4/core/types';
3
+ import * as z from 'zod/v3';
3
4
  import type { LikeC4LanguageServices } from '../../LikeC4LanguageServices';
4
5
  import type { Locate } from '../../protocol';
5
6
  export declare const locationSchema: z.ZodNullable<z.ZodObject<{
@@ -45,6 +46,7 @@ export declare const locationSchema: z.ZodNullable<z.ZodObject<{
45
46
  };
46
47
  }>;
47
48
  }, "strip", z.ZodTypeAny, {
49
+ path: string;
48
50
  range: {
49
51
  start: {
50
52
  line: number;
@@ -55,8 +57,8 @@ export declare const locationSchema: z.ZodNullable<z.ZodObject<{
55
57
  character: number;
56
58
  };
57
59
  };
58
- path: string;
59
60
  }, {
61
+ path: string;
60
62
  range: {
61
63
  start: {
62
64
  line: number;
@@ -67,7 +69,6 @@ export declare const locationSchema: z.ZodNullable<z.ZodObject<{
67
69
  character: number;
68
70
  };
69
71
  };
70
- path: string;
71
72
  }>>;
72
73
  export declare const projectIdSchema: z.ZodDefault<z.ZodOptional<z.ZodEffects<z.ZodString, ProjectId, string>>>;
73
74
  export declare const includedInViewsSchema: z.ZodArray<z.ZodObject<{
@@ -75,13 +76,13 @@ export declare const includedInViewsSchema: z.ZodArray<z.ZodObject<{
75
76
  title: z.ZodString;
76
77
  type: z.ZodEnum<["element", "deployment", "dynamic"]>;
77
78
  }, "strip", z.ZodTypeAny, {
78
- title: string;
79
79
  id: string;
80
- type: "deployment" | "dynamic" | "element";
81
- }, {
82
80
  title: string;
81
+ type: "deployment" | "element" | "dynamic";
82
+ }, {
83
83
  id: string;
84
- type: "deployment" | "dynamic" | "element";
84
+ title: string;
85
+ type: "deployment" | "element" | "dynamic";
85
86
  }>, "many">;
86
87
  export declare const includedInViews: (views: Iterable<LikeC4ViewModel>) => z.infer<typeof includedInViewsSchema>;
87
88
  export declare const mkLocate: (languageServices: LikeC4LanguageServices, projectId: string) => (params: Locate.Params) => z.infer<typeof locationSchema>;