@likec4/language-server 1.37.0 → 1.38.1
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/dist/LikeC4LanguageServices.d.ts +8 -4
- package/dist/LikeC4LanguageServices.js +12 -2
- package/dist/Rpc.js +2 -2
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +1 -1
- package/dist/bundled.mjs +4259 -3106
- package/dist/empty.d.ts +2 -0
- package/dist/empty.js +1 -0
- package/dist/filesystem/ChokidarWatcher.d.ts +14 -0
- package/dist/filesystem/ChokidarWatcher.js +64 -0
- package/dist/filesystem/FileSystemWatcher.d.ts +19 -0
- package/dist/filesystem/FileSystemWatcher.js +11 -0
- package/dist/filesystem/LikeC4FileSystem.d.ts +5 -0
- package/dist/filesystem/LikeC4FileSystem.js +56 -0
- package/dist/filesystem/index.d.ts +20 -0
- package/dist/filesystem/index.js +16 -0
- package/dist/index.d.ts +18 -4
- package/dist/index.js +23 -10
- package/dist/mcp/{sseserver/MCPServerFactory.d.ts → MCPServerFactory.d.ts} +1 -1
- package/dist/mcp/MCPServerFactory.js +69 -0
- package/dist/mcp/NoopLikeC4MCPServer.d.ts +4 -10
- package/dist/mcp/NoopLikeC4MCPServer.js +5 -10
- package/dist/mcp/interfaces.d.ts +7 -5
- package/dist/mcp/interfaces.js +4 -0
- package/dist/mcp/server/StdioLikeC4MCPServer.d.ts +16 -0
- package/dist/mcp/server/StdioLikeC4MCPServer.js +43 -0
- package/dist/mcp/{sseserver/MCPServer.d.ts → server/StreamableLikeC4MCPServer.d.ts} +3 -2
- package/dist/mcp/server/StreamableLikeC4MCPServer.js +156 -0
- package/dist/mcp/server/WithMCPServer.d.ts +2 -0
- package/dist/mcp/server/WithMCPServer.js +57 -0
- package/dist/mcp/tools/_common.d.ts +24 -5
- package/dist/mcp/tools/_common.js +31 -3
- package/dist/mcp/tools/find-relationships.d.ts +13 -0
- package/dist/mcp/tools/find-relationships.js +151 -0
- package/dist/mcp/tools/list-projects.js +40 -12
- package/dist/mcp/tools/open-view.d.ts +4 -3
- package/dist/mcp/tools/open-view.js +37 -14
- package/dist/mcp/tools/{read-project-elements.d.ts → read-deployment.d.ts} +6 -3
- package/dist/mcp/tools/read-deployment.js +130 -0
- package/dist/mcp/tools/read-element.d.ts +4 -3
- package/dist/mcp/tools/read-element.js +114 -51
- package/dist/mcp/tools/read-project-summary.d.ts +3 -2
- package/dist/mcp/tools/read-project-summary.js +139 -32
- package/dist/mcp/tools/read-view.d.ts +4 -3
- package/dist/mcp/tools/read-view.js +146 -105
- package/dist/mcp/tools/search-element.js +81 -30
- package/dist/mcp/utils.js +7 -4
- package/dist/model/builder/MergedSpecification.d.ts +1 -1
- package/dist/model/builder/buildModel.d.ts +1 -1
- package/dist/module.d.ts +9 -9
- package/dist/module.js +24 -29
- package/dist/protocol.d.ts +1 -1
- package/dist/protocol.js +1 -1
- package/dist/test/testServices.js +3 -2
- package/dist/workspace/LangiumDocuments.d.ts +4 -1
- package/dist/workspace/LangiumDocuments.js +15 -0
- package/dist/workspace/ProjectsManager.d.ts +1 -1
- package/dist/workspace/ProjectsManager.js +18 -19
- package/dist/workspace/WorkspaceManager.d.ts +9 -2
- package/dist/workspace/WorkspaceManager.js +30 -39
- package/package.json +16 -12
- package/dist/LikeC4FileSystem.d.ts +0 -14
- package/dist/LikeC4FileSystem.js +0 -39
- package/dist/mcp/sseserver/MCPServer.js +0 -80
- package/dist/mcp/sseserver/MCPServerFactory.js +0 -50
- package/dist/mcp/sseserver/WithMCPServer.d.ts +0 -9
- package/dist/mcp/sseserver/WithMCPServer.js +0 -53
- package/dist/mcp/tools/read-project-elements.js +0 -93
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { invariant } from "@likec4/core";
|
|
2
1
|
import z from "zod";
|
|
3
|
-
import { safeCall } from "../../utils/index.js";
|
|
4
|
-
import { ProjectsManager } from "../../workspace/index.js";
|
|
5
2
|
import { likec4Tool } from "../utils.js";
|
|
6
|
-
import { locationSchema } from "./_common.js";
|
|
3
|
+
import { locationSchema, mkLocate, projectIdSchema } from "./_common.js";
|
|
7
4
|
const modelRef = (node) => {
|
|
8
5
|
if (node.hasElement()) {
|
|
9
6
|
return node.element.id;
|
|
@@ -13,152 +10,196 @@ const modelRef = (node) => {
|
|
|
13
10
|
}
|
|
14
11
|
return null;
|
|
15
12
|
};
|
|
13
|
+
const nodeSchema = z.discriminatedUnion("type", [
|
|
14
|
+
z.object({
|
|
15
|
+
type: z.literal("element"),
|
|
16
|
+
id: z.string().describe("Node ID"),
|
|
17
|
+
elementId: z.string().describe("Element ID (FQN)"),
|
|
18
|
+
kind: z.string().describe("Element kind"),
|
|
19
|
+
title: z.string().describe("Node title"),
|
|
20
|
+
description: z.string().nullable(),
|
|
21
|
+
technology: z.string().nullable(),
|
|
22
|
+
children: z.array(z.string()).describe("Children nodes, array of node IDs"),
|
|
23
|
+
shape: z.string().describe("Rendered shape"),
|
|
24
|
+
color: z.string().describe("Rendered color"),
|
|
25
|
+
tags: z.array(z.string())
|
|
26
|
+
}),
|
|
27
|
+
z.object({
|
|
28
|
+
type: z.literal("deployment-node"),
|
|
29
|
+
id: z.string().describe("Node ID"),
|
|
30
|
+
deploymentId: z.string().describe("Deployment entity ID (FQN)"),
|
|
31
|
+
kind: z.string().describe("Deployment kind"),
|
|
32
|
+
title: z.string().describe("Node title"),
|
|
33
|
+
description: z.string().nullable(),
|
|
34
|
+
technology: z.string().nullable(),
|
|
35
|
+
children: z.array(z.string()).describe("Children nodes, array of node IDs"),
|
|
36
|
+
shape: z.string().describe("Rendered shape"),
|
|
37
|
+
color: z.string().describe("Rendered color"),
|
|
38
|
+
tags: z.array(z.string())
|
|
39
|
+
}),
|
|
40
|
+
z.object({
|
|
41
|
+
type: z.literal("deployed-instance"),
|
|
42
|
+
id: z.string().describe("Node ID"),
|
|
43
|
+
deploymentId: z.string().describe("Deployment entity ID (FQN)"),
|
|
44
|
+
title: z.string().describe("Node title"),
|
|
45
|
+
description: z.string().nullable(),
|
|
46
|
+
technology: z.string().nullable(),
|
|
47
|
+
referencedElement: z.object({
|
|
48
|
+
id: z.string().describe("Element ID (FQN)"),
|
|
49
|
+
kind: z.string().describe("Element kind"),
|
|
50
|
+
title: z.string().describe("Element title")
|
|
51
|
+
}),
|
|
52
|
+
shape: z.string().describe("Rendered shape"),
|
|
53
|
+
color: z.string().describe("Rendered color"),
|
|
54
|
+
tags: z.array(z.string())
|
|
55
|
+
})
|
|
56
|
+
]);
|
|
16
57
|
export const readView = likec4Tool({
|
|
17
58
|
name: "read-view",
|
|
18
59
|
description: `
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
- project
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
|
|
60
|
+
Read detailed information about a LikeC4 view.
|
|
61
|
+
|
|
62
|
+
Request:
|
|
63
|
+
- viewId: string \u2014 view id (name)
|
|
64
|
+
- project: string (optional) \u2014 project id. Defaults to "default" if omitted.
|
|
65
|
+
|
|
66
|
+
Response (JSON object):
|
|
67
|
+
- id: string \u2014 view id
|
|
68
|
+
- type: "element" | "deployment" | "dynamic" \u2014 view type
|
|
69
|
+
- title: string \u2014 view title (falls back to id if not set)
|
|
70
|
+
- description: string|null \u2014 optional description
|
|
71
|
+
- tags: string[] \u2014 view tags
|
|
72
|
+
- project: string \u2014 project id this view belongs to
|
|
73
|
+
- nodes: Node[] \u2014 nodes included in the view
|
|
74
|
+
- edges: Edge[] \u2014 relationships between nodes
|
|
75
|
+
- sourceLocation: { path: string, range: { start: { line: number, character: number }, end: { line: number, character: number } } } | null \u2014 source location if available
|
|
76
|
+
|
|
77
|
+
Node (discriminated union by "type"):
|
|
78
|
+
- type = "element": { id: string, elementId: string, kind: string, title: string, description: string|null, technology: string|null, children: string[], shape: string, color: string, tags: string[] }
|
|
79
|
+
- type = "deployment-node": { id: string, deploymentId: string, kind: string, title: string, description: string|null, technology: string|null, children: string[], shape: string, color: string, tags: string[] }
|
|
80
|
+
- type = "deployed-instance": { id: string, deploymentId: string, title: string, description: string|null, technology: string|null, referencedElement: { id: string, kind: string, title: string }, shape: string, color: string, tags: string[] }
|
|
81
|
+
|
|
82
|
+
Edge object:
|
|
83
|
+
- { source: string, target: string, label: string|null, description: string|null, technology: string|null, tags: string[] }
|
|
84
|
+
|
|
85
|
+
Notes:
|
|
86
|
+
- Read-only, idempotent, no side effects.
|
|
87
|
+
|
|
88
|
+
Example response:
|
|
89
|
+
{
|
|
90
|
+
"id": "system-overview",
|
|
91
|
+
"type": "element",
|
|
92
|
+
"title": "System Overview",
|
|
93
|
+
"description": null,
|
|
94
|
+
"tags": [],
|
|
95
|
+
"project": "default",
|
|
96
|
+
"nodes": [
|
|
97
|
+
{ "type": "logical", "id": "n1", "elementId": "shop.frontend", "kind": "container", "title": "Frontend", "description": null, "technology": "React", "children": [], "shape": "rounded-rectangle", "color": "#2F80ED", "tags": [] }
|
|
98
|
+
],
|
|
99
|
+
"edges": [
|
|
100
|
+
{ "source": "n1", "target": "n2", "label": "calls", "description": null, "technology": "HTTPS", "tags": [] }
|
|
101
|
+
],
|
|
102
|
+
"sourceLocation": {
|
|
103
|
+
"path": "/abs/path/project/model.c4",
|
|
104
|
+
"range": { "start": { "line": 10, "character": 0 }, "end": { "line": 30, "character": 0 } }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
`,
|
|
29
108
|
annotations: {
|
|
30
|
-
readOnlyHint: true
|
|
109
|
+
readOnlyHint: true,
|
|
110
|
+
idempotentHint: true,
|
|
111
|
+
title: "Read view"
|
|
31
112
|
},
|
|
32
113
|
inputSchema: {
|
|
33
114
|
viewId: z.string().describe("View id (name)"),
|
|
34
|
-
project:
|
|
115
|
+
project: projectIdSchema
|
|
35
116
|
},
|
|
36
117
|
outputSchema: {
|
|
37
118
|
id: z.string(),
|
|
38
|
-
type: z.enum(["element", "deployment", "dynamic"]),
|
|
39
|
-
title: z.string()
|
|
40
|
-
description: z.string().
|
|
119
|
+
type: z.enum(["element", "deployment", "dynamic"]).describe("View type"),
|
|
120
|
+
title: z.string(),
|
|
121
|
+
description: z.string().nullable(),
|
|
41
122
|
tags: z.array(z.string()),
|
|
42
123
|
project: z.string(),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
z.object({
|
|
46
|
-
type: z.literal("logical"),
|
|
47
|
-
id: z.string().describe("Element ID (FQN)"),
|
|
48
|
-
kind: z.string().describe("Element kind"),
|
|
49
|
-
title: z.string().describe("Element title"),
|
|
50
|
-
description: z.string().nullish(),
|
|
51
|
-
technology: z.string().nullish(),
|
|
52
|
-
children: z.array(z.string()),
|
|
53
|
-
shape: z.string().describe("Element shape"),
|
|
54
|
-
tags: z.array(z.string())
|
|
55
|
-
}),
|
|
56
|
-
z.object({
|
|
57
|
-
type: z.literal("deployment-node"),
|
|
58
|
-
id: z.string().describe("Deployment ID (FQN)"),
|
|
59
|
-
kind: z.string().describe("Deployment kind"),
|
|
60
|
-
title: z.string().describe("Deployment title"),
|
|
61
|
-
description: z.string().nullish(),
|
|
62
|
-
technology: z.string().nullish(),
|
|
63
|
-
children: z.array(z.string()),
|
|
64
|
-
shape: z.string().describe("Deployment shape"),
|
|
65
|
-
tags: z.array(z.string())
|
|
66
|
-
}),
|
|
67
|
-
z.object({
|
|
68
|
-
type: z.literal("deployed-instance"),
|
|
69
|
-
id: z.string().describe("Deployment ID (FQN)"),
|
|
70
|
-
title: z.string().describe("Deployment title"),
|
|
71
|
-
description: z.string().nullish(),
|
|
72
|
-
technology: z.string().nullish(),
|
|
73
|
-
logicalElementId: z.string().describe("Logical element ID (FQN)"),
|
|
74
|
-
shape: z.string().describe("Deployment shape"),
|
|
75
|
-
tags: z.array(z.string())
|
|
76
|
-
})
|
|
77
|
-
])
|
|
78
|
-
).describe("Elements in this view"),
|
|
79
|
-
relationships: z.array(
|
|
124
|
+
nodes: z.array(nodeSchema),
|
|
125
|
+
edges: z.array(
|
|
80
126
|
z.object({
|
|
81
|
-
source: z.string().describe("Source
|
|
82
|
-
target: z.string().describe("Target
|
|
83
|
-
|
|
84
|
-
description: z.string().
|
|
85
|
-
technology: z.string().
|
|
127
|
+
source: z.string().describe("Source node"),
|
|
128
|
+
target: z.string().describe("Target node"),
|
|
129
|
+
label: z.string().nullable(),
|
|
130
|
+
description: z.string().nullable(),
|
|
131
|
+
technology: z.string().nullable(),
|
|
86
132
|
tags: z.array(z.string())
|
|
87
133
|
})
|
|
88
|
-
).describe("
|
|
89
|
-
|
|
90
|
-
sourceLocation: locationSchema.nullish()
|
|
134
|
+
).describe("Edge represents relationship between nodes"),
|
|
135
|
+
sourceLocation: locationSchema
|
|
91
136
|
}
|
|
92
137
|
}, async (languageServices, args) => {
|
|
93
|
-
const projectId = args.project
|
|
94
|
-
const project = languageServices.
|
|
95
|
-
|
|
96
|
-
const model = await languageServices.computedModel(project.id);
|
|
138
|
+
const projectId = languageServices.projectsManager.ensureProjectId(args.project);
|
|
139
|
+
const project = languageServices.project(projectId);
|
|
140
|
+
const model = await languageServices.computedModel(projectId);
|
|
97
141
|
const view = model.findView(args.viewId);
|
|
98
142
|
if (!view) {
|
|
99
143
|
throw new Error(`View with ID '${args.viewId}' not found in project ${project.id}`);
|
|
100
144
|
}
|
|
145
|
+
const locate = mkLocate(languageServices, project.id);
|
|
101
146
|
return {
|
|
102
147
|
id: view.id,
|
|
103
148
|
type: view.$view._type,
|
|
104
|
-
title: view.title,
|
|
149
|
+
title: view.title ?? view.id,
|
|
105
150
|
description: view.description.text,
|
|
106
151
|
tags: [...view.tags],
|
|
107
152
|
project: project.id,
|
|
108
|
-
|
|
153
|
+
nodes: [...view.nodes()].flatMap((node) => {
|
|
154
|
+
const base = {
|
|
155
|
+
id: node.id,
|
|
156
|
+
title: node.title,
|
|
157
|
+
description: node.description.text,
|
|
158
|
+
technology: node.technology,
|
|
159
|
+
shape: node.shape,
|
|
160
|
+
color: node.color,
|
|
161
|
+
tags: [...node.tags]
|
|
162
|
+
};
|
|
109
163
|
if (node.hasDeployedInstance()) {
|
|
110
164
|
return {
|
|
165
|
+
...base,
|
|
111
166
|
type: "deployed-instance",
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
tags: [...node.tags]
|
|
167
|
+
deploymentId: node.deployment.id,
|
|
168
|
+
referencedElement: {
|
|
169
|
+
id: node.deployment.element.id,
|
|
170
|
+
kind: node.deployment.element.kind,
|
|
171
|
+
title: node.deployment.element.title
|
|
172
|
+
}
|
|
119
173
|
};
|
|
120
174
|
}
|
|
121
175
|
if (node.hasDeployment()) {
|
|
122
176
|
return {
|
|
177
|
+
...base,
|
|
123
178
|
type: "deployment-node",
|
|
124
|
-
id: node.deployment.id,
|
|
125
|
-
title: node.title,
|
|
126
179
|
kind: node.deployment.kind,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
shape: node.shape,
|
|
130
|
-
tags: [...node.tags],
|
|
131
|
-
children: [...node.children()].flatMap((c) => modelRef(c) ?? [])
|
|
180
|
+
deploymentId: node.deployment.id,
|
|
181
|
+
children: [...node.children()].map((c) => c.id)
|
|
132
182
|
};
|
|
133
183
|
}
|
|
134
184
|
if (node.hasElement()) {
|
|
135
185
|
return {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
186
|
+
...base,
|
|
187
|
+
type: "element",
|
|
188
|
+
elementId: node.element.id,
|
|
139
189
|
kind: node.element.kind,
|
|
140
|
-
description: node.description.text,
|
|
141
|
-
technology: node.technology,
|
|
142
|
-
shape: node.shape,
|
|
143
|
-
tags: [...node.tags],
|
|
144
190
|
children: [...node.children()].flatMap((c) => modelRef(c) ?? [])
|
|
145
191
|
};
|
|
146
192
|
}
|
|
147
193
|
return [];
|
|
148
194
|
}),
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
technology: r.technology,
|
|
159
|
-
tags: [...r.tags]
|
|
160
|
-
}] : [];
|
|
161
|
-
}),
|
|
162
|
-
sourceLocation: safeCall(() => languageServices.locate({ view: view.id, projectId }))
|
|
195
|
+
edges: [...view.edges()].map((r) => ({
|
|
196
|
+
source: r.source.id,
|
|
197
|
+
target: r.target.id,
|
|
198
|
+
label: r.label,
|
|
199
|
+
description: r.description.text,
|
|
200
|
+
technology: r.technology,
|
|
201
|
+
tags: [...r.tags]
|
|
202
|
+
})),
|
|
203
|
+
sourceLocation: locate({ view: view.id })
|
|
163
204
|
};
|
|
164
205
|
});
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import { ifilter } from "@likec4/core/utils";
|
|
2
2
|
import z from "zod";
|
|
3
|
-
import { likec4Tool } from "../utils.js";
|
|
3
|
+
import { likec4Tool, logger } from "../utils.js";
|
|
4
|
+
import { includedInViews, includedInViewsSchema } from "./_common.js";
|
|
4
5
|
const searchResultSchema = z.array(
|
|
5
6
|
z.discriminatedUnion("type", [
|
|
6
7
|
z.object({
|
|
7
|
-
type: z.literal("
|
|
8
|
+
type: z.literal("element"),
|
|
9
|
+
project: z.string().describe("Project ID"),
|
|
8
10
|
id: z.string().describe("Element ID (FQN)"),
|
|
11
|
+
name: z.string().describe("Element name"),
|
|
9
12
|
kind: z.string(),
|
|
10
13
|
title: z.string(),
|
|
14
|
+
technology: z.string().nullable(),
|
|
11
15
|
shape: z.string(),
|
|
12
|
-
|
|
16
|
+
includedInViews: includedInViewsSchema,
|
|
13
17
|
tags: z.array(z.string())
|
|
14
18
|
}),
|
|
15
19
|
z.object({
|
|
16
20
|
type: z.literal("deployment-node"),
|
|
21
|
+
project: z.string().describe("Project ID"),
|
|
17
22
|
id: z.string().describe("Deployment ID (FQN)"),
|
|
23
|
+
name: z.string().describe("Deployment name"),
|
|
18
24
|
kind: z.string(),
|
|
19
25
|
title: z.string(),
|
|
26
|
+
technology: z.string().nullable(),
|
|
20
27
|
shape: z.string(),
|
|
21
|
-
|
|
28
|
+
includedInViews: includedInViewsSchema,
|
|
22
29
|
tags: z.array(z.string())
|
|
23
30
|
})
|
|
24
31
|
])
|
|
@@ -26,32 +33,69 @@ const searchResultSchema = z.array(
|
|
|
26
33
|
export const searchElement = likec4Tool({
|
|
27
34
|
name: "search-element",
|
|
28
35
|
annotations: {
|
|
29
|
-
readOnlyHint: true
|
|
36
|
+
readOnlyHint: true,
|
|
37
|
+
idempotentHint: true,
|
|
38
|
+
title: "Search elements"
|
|
30
39
|
},
|
|
31
40
|
description: `
|
|
32
|
-
Search
|
|
33
|
-
- id (FQN)
|
|
34
|
-
- title
|
|
35
|
-
- kind (if search string starts with "kind:")
|
|
36
|
-
- shape (if search string starts with "shape:")
|
|
37
|
-
- any assigned tags (if search string starts with "#")
|
|
41
|
+
Search LikeC4 elements and deployment nodes across all projects.
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
- shape
|
|
45
|
-
- project name this element belongs to
|
|
46
|
-
- assigned tags
|
|
43
|
+
Query syntax (case-insensitive):
|
|
44
|
+
- Free text: matches id (FQN) or title
|
|
45
|
+
- kind:<value>: filters by kind
|
|
46
|
+
- shape:<value>: filters by shape
|
|
47
|
+
- #<value>: matches assigned tags
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
Request:
|
|
50
|
+
- search: string \u2014 at least 2 characters
|
|
51
|
+
|
|
52
|
+
Response (JSON object):
|
|
53
|
+
- found: Result[] - returns top 20 results
|
|
54
|
+
- total: number - total number of results
|
|
55
|
+
|
|
56
|
+
Result (discriminated union by "type"):
|
|
57
|
+
- type = "element": { id: string, name: string, kind: string, title: string, technology: string|null, shape: string, project: string, includedInViews: View[], tags: string[] }
|
|
58
|
+
- type = "deployment-node": { id: string, name: string, kind: string, title: string, technology: string|null, shape: string, project: string, includedInViews: View[], tags: string[] }
|
|
59
|
+
|
|
60
|
+
View (object) fields:
|
|
61
|
+
- id: string \u2014 view identifier
|
|
62
|
+
- title: string \u2014 view title
|
|
63
|
+
- type: "element" | "deployment" | "dynamic"
|
|
64
|
+
|
|
65
|
+
Notes:
|
|
66
|
+
- Read-only, idempotent.
|
|
67
|
+
- Use results as input to other tools (e.g., read-element, read-view).
|
|
68
|
+
|
|
69
|
+
Example response:
|
|
70
|
+
{
|
|
71
|
+
"found": [
|
|
72
|
+
{
|
|
73
|
+
"type": "logical",
|
|
74
|
+
"project": "default",
|
|
75
|
+
"id": "shop.frontend",
|
|
76
|
+
"name": "frontend",
|
|
77
|
+
"kind": "container",
|
|
78
|
+
"title": "Frontend",
|
|
79
|
+
"technology": "React",
|
|
80
|
+
"shape": "rectangle",
|
|
81
|
+
"includedInViews": [
|
|
82
|
+
{
|
|
83
|
+
"id": "system-overview",
|
|
84
|
+
"title": "System Overview",
|
|
85
|
+
"type": "element"
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"tags": ["public"]
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
`,
|
|
50
93
|
inputSchema: {
|
|
51
94
|
search: z.string().min(2, "Search must be at least 2 characters long")
|
|
52
95
|
},
|
|
53
96
|
outputSchema: {
|
|
54
|
-
found: searchResultSchema
|
|
97
|
+
found: searchResultSchema,
|
|
98
|
+
total: z.number()
|
|
55
99
|
}
|
|
56
100
|
}, async (languageServices, args) => {
|
|
57
101
|
const projects = languageServices.projects();
|
|
@@ -73,33 +117,40 @@ Can be used for further requests (like read-element or read-project-summary)
|
|
|
73
117
|
for (const project of projects) {
|
|
74
118
|
try {
|
|
75
119
|
const model = await languageServices.computedModel(project.id);
|
|
76
|
-
for (const el of ifilter(model.elements(), predicate)) {
|
|
120
|
+
for (const el of ifilter(model.elements(), (e) => !e.imported && predicate(e))) {
|
|
77
121
|
found.push({
|
|
78
|
-
type: "
|
|
122
|
+
type: "element",
|
|
123
|
+
project: project.id,
|
|
79
124
|
id: el.id,
|
|
125
|
+
name: el.name,
|
|
80
126
|
kind: el.kind,
|
|
81
127
|
title: el.title,
|
|
128
|
+
technology: el.technology,
|
|
82
129
|
shape: el.shape,
|
|
83
|
-
|
|
84
|
-
|
|
130
|
+
tags: [...el.tags],
|
|
131
|
+
includedInViews: includedInViews(el.views())
|
|
85
132
|
});
|
|
86
133
|
}
|
|
87
134
|
for (const el of ifilter(model.deployment.nodes(), predicate)) {
|
|
88
135
|
found.push({
|
|
89
136
|
type: "deployment-node",
|
|
137
|
+
project: project.id,
|
|
90
138
|
id: el.id,
|
|
139
|
+
name: el.name,
|
|
91
140
|
kind: el.kind,
|
|
92
141
|
title: el.title,
|
|
142
|
+
technology: el.technology,
|
|
93
143
|
shape: el.shape,
|
|
94
|
-
|
|
95
|
-
|
|
144
|
+
tags: [...el.tags],
|
|
145
|
+
includedInViews: includedInViews(el.views())
|
|
96
146
|
});
|
|
97
147
|
}
|
|
98
148
|
} catch (error) {
|
|
99
|
-
|
|
149
|
+
logger.error(`Error searching in project ${project.id}:`, { error });
|
|
100
150
|
}
|
|
101
151
|
}
|
|
102
152
|
return {
|
|
103
|
-
found
|
|
153
|
+
found: found.slice(0, 20),
|
|
154
|
+
total: found.length
|
|
104
155
|
};
|
|
105
156
|
});
|
package/dist/mcp/utils.js
CHANGED
|
@@ -2,17 +2,20 @@ import { loggable } from "@likec4/log";
|
|
|
2
2
|
import { logger as mainLogger } from "../logger.js";
|
|
3
3
|
export const logger = mainLogger.getChild("mcp");
|
|
4
4
|
export function likec4Tool(config, cb) {
|
|
5
|
-
const { name, ...rest } = config;
|
|
5
|
+
const { name, description, ...rest } = config;
|
|
6
6
|
return (languageServices) => [
|
|
7
7
|
name,
|
|
8
|
-
|
|
8
|
+
{
|
|
9
|
+
description: description?.trim() ?? "",
|
|
10
|
+
...rest
|
|
11
|
+
},
|
|
9
12
|
mkcallTool(name, languageServices, cb)
|
|
10
13
|
];
|
|
11
14
|
}
|
|
12
15
|
function mkcallTool(name, languageServices, cb) {
|
|
13
16
|
const tool = cb.bind(null, languageServices);
|
|
14
17
|
return async function callTool(args, extra) {
|
|
15
|
-
logger.debug("Calling tool {name}", { name, args });
|
|
18
|
+
logger.debug("Calling tool {name}, args: {args}", { name, args });
|
|
16
19
|
try {
|
|
17
20
|
const result = await tool.call(null, args, extra);
|
|
18
21
|
if (typeof result === "string") {
|
|
@@ -35,7 +38,7 @@ function mkcallTool(name, languageServices, cb) {
|
|
|
35
38
|
return {
|
|
36
39
|
content: [{
|
|
37
40
|
type: "text",
|
|
38
|
-
text: loggable(err)
|
|
41
|
+
text: err instanceof Error ? err.message : loggable(err)
|
|
39
42
|
}],
|
|
40
43
|
isError: true
|
|
41
44
|
};
|
|
@@ -12,7 +12,7 @@ export declare class MergedSpecification {
|
|
|
12
12
|
readonly tags: Readonly<Record<c4.Tag, c4.TagSpecification>>;
|
|
13
13
|
readonly globals: c4.ModelGlobals;
|
|
14
14
|
readonly imports: MultiMap<c4.ProjectId, c4.Fqn, Set<c4.Fqn>>;
|
|
15
|
-
constructor(docs: ParsedLikeC4LangiumDocument
|
|
15
|
+
constructor(docs: ReadonlyArray<ParsedLikeC4LangiumDocument>);
|
|
16
16
|
/**
|
|
17
17
|
* Converts a parsed model into a C4 model element.
|
|
18
18
|
*/
|
package/dist/module.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { QueueGraphvizLayoter } from '@likec4/layouts';
|
|
|
2
2
|
import { type Module, WorkspaceCache } from 'langium';
|
|
3
3
|
import { type DefaultSharedModuleContext, type LangiumServices, type LangiumSharedServices, type PartialLangiumServices } from 'langium/lsp';
|
|
4
4
|
import { LikeC4DocumentationProvider } from './documentation';
|
|
5
|
+
import { type FileSystemModuleContext, type FileSystemProvider, type FileSystemWatcher } from './filesystem';
|
|
5
6
|
import { type LikeC4LanguageServices } from './LikeC4LanguageServices';
|
|
6
7
|
import { LikeC4CodeLensProvider, LikeC4CompletionProvider, LikeC4DocumentHighlightProvider, LikeC4DocumentLinkProvider, LikeC4DocumentSymbolProvider, LikeC4HoverProvider, LikeC4SemanticTokenProvider } from './lsp';
|
|
7
|
-
import { type LikeC4MCPServer, type
|
|
8
|
+
import { type LikeC4MCPServer, type LikeC4MCPServerModuleContext } from './mcp/interfaces';
|
|
9
|
+
import { LikeC4MCPServerFactory } from './mcp/MCPServerFactory';
|
|
8
10
|
import { type LikeC4ModelBuilder, DeploymentsIndex, FqnIndex, LikeC4ModelLocator, LikeC4ModelParser, LikeC4ValueConverter } from './model';
|
|
9
11
|
import { LikeC4ModelChanges } from './model-change/ModelChanges';
|
|
10
12
|
import { LikeC4NameProvider, LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
|
|
@@ -13,6 +15,7 @@ import { NodeKindProvider, WorkspaceSymbolProvider } from './shared';
|
|
|
13
15
|
import { LikeC4DocumentValidator } from './validation';
|
|
14
16
|
import { type LikeC4Views } from './views';
|
|
15
17
|
import { IndexManager, LangiumDocuments, LikeC4WorkspaceManager, ProjectsManager } from './workspace';
|
|
18
|
+
export type LanguageServicesContext = Omit<DefaultSharedModuleContext, 'fileSystemProvider'> & FileSystemModuleContext & LikeC4MCPServerModuleContext;
|
|
16
19
|
interface LikeC4AddedSharedServices {
|
|
17
20
|
lsp: {
|
|
18
21
|
NodeKindProvider: NodeKindProvider;
|
|
@@ -23,6 +26,8 @@ interface LikeC4AddedSharedServices {
|
|
|
23
26
|
IndexManager: IndexManager;
|
|
24
27
|
LangiumDocuments: LangiumDocuments;
|
|
25
28
|
WorkspaceManager: LikeC4WorkspaceManager;
|
|
29
|
+
FileSystemProvider: FileSystemProvider;
|
|
30
|
+
FileSystemWatcher: FileSystemWatcher;
|
|
26
31
|
};
|
|
27
32
|
}
|
|
28
33
|
export type LikeC4SharedServices = LangiumSharedServices & LikeC4AddedSharedServices;
|
|
@@ -73,15 +78,10 @@ export interface LikeC4AddedServices {
|
|
|
73
78
|
};
|
|
74
79
|
}
|
|
75
80
|
export type LikeC4Services = LangiumServices & LikeC4AddedServices;
|
|
76
|
-
export declare const
|
|
77
|
-
export
|
|
78
|
-
export declare function createCustomLanguageServices<I1, I2, I3, I extends I1 & I2 & I3 & LikeC4Services>(context: LanguageServicesContext, module?: Module<I, I1>, module2?: Module<I, I2>, module3?: Module<I, I3>): {
|
|
81
|
+
export declare const createLikeC4Module: (context: LikeC4MCPServerModuleContext) => Module<LikeC4Services, PartialLangiumServices & LikeC4AddedServices>;
|
|
82
|
+
export declare function createLanguageServices<I1, I2, I3, I extends I1 & I2 & I3 & LikeC4Services>(context: Partial<LanguageServicesContext>, module?: Module<I, I1>, module2?: Module<I, I2>, module3?: Module<I, I3>): {
|
|
79
83
|
shared: LikeC4SharedServices;
|
|
80
84
|
likec4: I;
|
|
81
85
|
};
|
|
82
|
-
export declare function createSharedServices(context?: LanguageServicesContext): LikeC4SharedServices;
|
|
83
|
-
export declare function createLanguageServices(context?: LanguageServicesContext): {
|
|
84
|
-
shared: LikeC4SharedServices;
|
|
85
|
-
likec4: LikeC4Services;
|
|
86
|
-
};
|
|
86
|
+
export declare function createSharedServices(context?: Partial<LanguageServicesContext>): LikeC4SharedServices;
|
|
87
87
|
export {};
|