@likec4/language-server 1.48.0 → 1.49.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.
- package/browser/package.json +2 -2
- package/browser-worker/package.json +2 -2
- package/dist/THIRD-PARTY-LICENSES.md +178 -0
- package/dist/_chunks/ConfigurableLayouter.mjs +1 -1956
- package/dist/_chunks/LikeC4FileSystem.mjs +3 -0
- package/dist/_chunks/LikeC4Views.mjs +34 -0
- package/dist/_chunks/ProjectsManager.mjs +1 -0
- package/dist/_chunks/WithMCPServer.mjs +481 -0
- package/dist/_chunks/icons.mjs +2 -5211
- package/dist/_chunks/{LikeC4LanguageServices.d.mts → index.d.mts} +1836 -707
- package/dist/_chunks/libs/@msgpack/msgpack.mjs +1 -805
- package/dist/_chunks/libs/eventemitter3.mjs +1 -243
- package/dist/_chunks/libs/fast-equals.mjs +1 -446
- package/dist/_chunks/libs/p-queue.mjs +1 -449
- package/dist/_chunks/libs/parse-ms.mjs +1 -36
- package/dist/_chunks/libs/picomatch.mjs +1 -1673
- package/dist/_chunks/libs/pretty-ms.mjs +1 -80
- package/dist/_chunks/libs/remeda.mjs +1 -482
- package/dist/_chunks/libs/strip-indent.mjs +1 -15
- package/dist/_chunks/libs/ufo.mjs +1 -166
- package/dist/_chunks/logger.mjs +1 -0
- package/dist/_chunks/rolldown-runtime.mjs +1 -42
- package/dist/_chunks/utils.mjs +1 -0
- package/dist/browser/index.d.mts +10 -0
- package/dist/browser/index.mjs +1 -0
- package/dist/browser/worker.mjs +1 -0
- package/dist/bundled.d.mts +2 -3
- package/dist/bundled.mjs +1 -51
- package/dist/filesystem/index.d.mts +2 -4
- package/dist/filesystem/index.mjs +1 -3
- package/dist/index.d.mts +38 -3
- package/dist/index.mjs +1 -48
- package/dist/likec4lib.d.mts +10 -3
- package/dist/likec4lib.mjs +1 -4
- package/dist/mcp/index.d.mts +2 -4
- package/dist/mcp/index.mjs +1 -3
- package/dist/module.d.mts +126 -4
- package/dist/module.mjs +1 -3
- package/dist/protocol.d.mts +314 -1
- package/dist/protocol.mjs +1 -3
- package/filesystem/package.json +4 -0
- package/mcp/package.json +4 -0
- package/module/package.json +4 -0
- package/package.json +79 -56
- package/LICENSE +0 -21
- package/dist/LikeC4LanguageServices.d.mts +0 -4
- package/dist/LikeC4LanguageServices.mjs +0 -3
- package/dist/_chunks/LikeC4LanguageServices.mjs +0 -725
- package/dist/_chunks/ast.d.mts +0 -1444
- package/dist/_chunks/ast.mjs +0 -2375
- package/dist/_chunks/ast2.mjs +0 -176
- package/dist/_chunks/common-exports.mjs +0 -0
- package/dist/_chunks/filesystem.mjs +0 -58
- package/dist/_chunks/grammar.mjs +0 -8
- package/dist/_chunks/libs/@hono/node-server.mjs +0 -436
- package/dist/_chunks/libs/hono.mjs +0 -1829
- package/dist/_chunks/likec4lib.mjs +0 -9
- package/dist/_chunks/mcp.mjs +0 -33
- package/dist/_chunks/module.mjs +0 -28
- package/dist/_chunks/module2.mjs +0 -6576
- package/dist/_chunks/protocol.d.mts +0 -311
- package/dist/_chunks/protocol.mjs +0 -78
- package/dist/ast.d.mts +0 -4
- package/dist/ast.mjs +0 -4
- package/dist/browser-worker.mjs +0 -6
- package/dist/browser.d.mts +0 -11
- package/dist/browser.mjs +0 -27
- package/dist/common-exports.d.mts +0 -4
- package/dist/common-exports.mjs +0 -5
- package/dist/generated/ast.d.mts +0 -2
- package/dist/generated/ast.mjs +0 -3
- package/dist/generated/grammar.d.mts +0 -6
- package/dist/generated/grammar.mjs +0 -3
- package/dist/generated/module.d.mts +0 -14
- package/dist/generated/module.mjs +0 -3
- package/dist/generated-lib/icons.d.mts +0 -4
- package/dist/generated-lib/icons.mjs +0 -3
- /package/dist/{browser-worker.d.mts → browser/worker.d.mts} +0 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
import{i as logger$2}from"./logger.mjs";import{h as t}from"./libs/remeda.mjs";import{t as ProjectsManager}from"./ProjectsManager.mjs";import{ifilter,invariant,isSameHierarchy}from"@likec4/core/utils";import{loggable}from"@likec4/log";import{invariant as invariant$1}from"@likec4/core";import{modelConnection}from"@likec4/core/model";import{URI}from"vscode-uri";import{McpServer}from"@modelcontextprotocol/sdk/server/mcp.js";import*as z from"zod/v3";import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio.js";import{MemoryEventStore,StreamableHTTPTransport}from"@hono/mcp";import{serve}from"@hono/node-server";import{Hono}from"hono";import{cors}from"hono/cors";const logger$1=logger$2.getChild(`mcp`);function likec4Tool(e,n){let{name:r,description:i,...a}=e;return e=>[r,{description:i?.trim()??``,...a},mkcallTool(r,e,n)]}function mkcallTool(e,n,r){let i=r.bind(null,n);return(async function(n,r){logger$1.debug(`Calling tool {name}, args: {args}`,{name:e,args:n});try{let e=await i.call(null,n,r);return typeof e==`string`?{content:[{type:`text`,text:e}]}:{content:[{type:`text`,text:JSON.stringify(e)}],structuredContent:e}}catch(n){return logger$1.error(`Tool ${e} failed`,{err:n}),{content:[{type:`text`,text:loggable(n)}],isError:!0}}})}var version=`1.49.0`;const locationSchema=z.object({path:z.string().describe(`Path to the file`),range:z.object({start:z.object({line:z.number(),character:z.number()}),end:z.object({line:z.number(),character:z.number()})}).describe(`Range in the file`)}).nullable(),projectIdSchema=z.string().refine(e=>!0).optional().default(ProjectsManager.DefaultProjectId).describe(`Project id (optional, will use "default" if not specified)`),includedInViewsSchema=z.array(z.object({id:z.string().describe(`View id`),title:z.string().describe(`View title`),type:z.enum([`element`,`deployment`,`dynamic`]).describe(`View type`)})),includedInViews=e=>[...e].map(e=>({id:e.id,title:e.titleOrId,type:e.$view._type})),mkLocate=(e,n)=>r=>{try{let i=e.locate({projectId:n,...r});return i?{path:URI.parse(i.uri).fsPath,range:i.range}:null}catch(e){return logger$1.debug(`Failed to locate {params}`,{error:e,params:r}),null}},endpointSchema=z.object({id:z.string(),title:z.string(),kind:z.string()}),searchResultSchema$1=z.object({type:z.enum([`direct`,`indirect`]).describe(`Type of relationship, "direct" for direct relationships, "indirect" for relationships through nested elements`),source:endpointSchema,target:endpointSchema,kind:z.string().nullable().describe(`Relationship kind`),title:z.string().nullable().describe(`Relationship title`),description:z.string().nullable().describe(`Relationship description`),technology:z.string().nullable().describe(`Relationship technology`),tags:z.array(z.string()).describe(`Relationship tags`),includedInViews:includedInViewsSchema.describe(`Views that include this relationship`),sourceLocation:locationSchema}),findRelationships=likec4Tool({name:`find-relationships`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Find relationships between two elements`},description:`
|
|
2
|
+
Find relationships between two LikeC4 elements within a project.
|
|
3
|
+
|
|
4
|
+
What it does:
|
|
5
|
+
- Finds both direct relationships (element1 ↔ element2) and indirect ones that arise via containment (e.g. via nested elements).
|
|
6
|
+
- Returns rich metadata for each relationship and where it appears in views.
|
|
7
|
+
|
|
8
|
+
Inputs:
|
|
9
|
+
- element1: string — Element ID (FQN)
|
|
10
|
+
- element2: string — Element ID (FQN)
|
|
11
|
+
- project: string (optional, defaults to "default") — Project id
|
|
12
|
+
|
|
13
|
+
Output:
|
|
14
|
+
- found: Relationship[]
|
|
15
|
+
|
|
16
|
+
Relationship (object) fields:
|
|
17
|
+
- type: "direct" | "indirect" — direct is between the specified endpoints; indirect is via nested elements
|
|
18
|
+
- source: Endpoint
|
|
19
|
+
- target: Endpoint
|
|
20
|
+
- kind: string|null — relationship kind from the model
|
|
21
|
+
- title: string|null — relationship title if provided
|
|
22
|
+
- description: string|null — relationship description text
|
|
23
|
+
- technology: string|null — relationship technology
|
|
24
|
+
- tags: string[] — relationship tags
|
|
25
|
+
- includedInViews: View[] — views where this relationship appears
|
|
26
|
+
- sourceLocation: { path: string, range: { start: { line: number, character: number }, end: { line: number, character: number } } } | null
|
|
27
|
+
|
|
28
|
+
Endpoint (object) fields:
|
|
29
|
+
- id: string — Element ID (FQN)
|
|
30
|
+
- title: string — element title
|
|
31
|
+
- kind: string — element kind
|
|
32
|
+
|
|
33
|
+
View (object) fields:
|
|
34
|
+
- id: string — view identifier
|
|
35
|
+
- title: string — view title
|
|
36
|
+
- type: "element" | "deployment" | "dynamic"
|
|
37
|
+
|
|
38
|
+
Notes:
|
|
39
|
+
- Read-only, idempotent; does not mutate the model. May trigger UI navigation in supporting clients.
|
|
40
|
+
- The order of results is not guaranteed.
|
|
41
|
+
|
|
42
|
+
Example:
|
|
43
|
+
Request:
|
|
44
|
+
{
|
|
45
|
+
"element1": "shop.frontend",
|
|
46
|
+
"element2": "shop.backend",
|
|
47
|
+
"project": "default"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
Response:
|
|
51
|
+
{
|
|
52
|
+
"found": [
|
|
53
|
+
{
|
|
54
|
+
"type": "direct",
|
|
55
|
+
"source": { "id": "shop.frontend", "title": "Frontend", "kind": "component" },
|
|
56
|
+
"target": { "id": "shop.backend", "title": "Backend", "kind": "component" },
|
|
57
|
+
"kind": "sync",
|
|
58
|
+
"title": "Calls",
|
|
59
|
+
"description": "Frontend calls Backend",
|
|
60
|
+
"technology": "HTTP",
|
|
61
|
+
"tags": ["public"],
|
|
62
|
+
"includedInViews": [
|
|
63
|
+
{ "id": "system-overview", "title": "System Overview", "type": "element" }
|
|
64
|
+
],
|
|
65
|
+
"sourceLocation": {
|
|
66
|
+
"path": "/abs/path/project/model.c4",
|
|
67
|
+
"range": { "start": { "line": 12, "character": 0 }, "end": { "line": 14, "character": 0 } }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
`,inputSchema:{element1:z.string().describe(`Element ID (FQN)`),element2:z.string().describe(`Element ID (FQN)`),project:projectIdSchema},outputSchema:{found:z.array(searchResultSchema$1)}},async(e,n)=>{let r=e.projectsManager.ensureProjectId(n.project);if(isSameHierarchy(n.element1,n.element2))throw Error(`No relationships possible between parent-child`);let i=[],s=await e.computedModel(r),c=s.findElement(n.element1);invariant(c,`Element "${n.element1}" not found in project "${r}"`);let l=s.findElement(n.element2);invariant(l,`Element "${n.element2}" not found in project "${r}"`);let u=mkLocate(e,r),d=modelConnection.findConnection(c,l,`both`).flatMap(e=>[...e.relations]);for(let e of d){let n=e.source===c&&e.target===l||e.source===l&&e.target===c;i.push({type:n?`direct`:`indirect`,source:{id:e.source.id,title:e.source.title,kind:e.source.kind},target:{id:e.target.id,title:e.target.title,kind:e.target.kind},kind:e.kind,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags],includedInViews:includedInViews(e.views()),sourceLocation:u({relation:e.id})})}return{found:i}}),listProjects=likec4Tool({name:`list-projects`,description:`
|
|
73
|
+
List LikeC4 projects discoverable in the current workspace.
|
|
74
|
+
|
|
75
|
+
Request:
|
|
76
|
+
- No input parameters.
|
|
77
|
+
|
|
78
|
+
Response (JSON object):
|
|
79
|
+
- projects: Project[]
|
|
80
|
+
|
|
81
|
+
Project (object) fields:
|
|
82
|
+
- id: string — stable project identifier
|
|
83
|
+
- title: string — human-readable project title
|
|
84
|
+
- folder: string — absolute path to the project root
|
|
85
|
+
- sources: string[] — absolute file paths of related documents
|
|
86
|
+
|
|
87
|
+
Notes:
|
|
88
|
+
- Read-only, idempotent, no side effects.
|
|
89
|
+
- Safe to call repeatedly.
|
|
90
|
+
|
|
91
|
+
Example response:
|
|
92
|
+
{
|
|
93
|
+
"projects": [
|
|
94
|
+
{
|
|
95
|
+
"id": "docs",
|
|
96
|
+
"title": "Documentation",
|
|
97
|
+
"folder": "/abs/path/to/workspace/docs",
|
|
98
|
+
"sources": [
|
|
99
|
+
"/abs/path/to/workspace/docs/model/contexts.likec4",
|
|
100
|
+
"/abs/path/to/workspace/docs/model/relations.likec4"
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`List projects`},outputSchema:{projects:z.array(z.object({id:z.string(),title:z.string(),folder:z.string(),sources:z.array(z.string())}))}},async e=>({projects:e.projects().map(e=>({id:e.id,title:e.title,folder:e.folder.fsPath,sources:e.documents.map(e=>e.fsPath)}))})),openView=likec4Tool({name:`open-view`,description:`
|
|
106
|
+
Open a LikeC4 view in the editor's preview panel.
|
|
107
|
+
|
|
108
|
+
Request:
|
|
109
|
+
- viewId: string — view id (name)
|
|
110
|
+
- project: string (optional) — project id. Defaults to "default" if omitted.
|
|
111
|
+
|
|
112
|
+
Response (JSON object):
|
|
113
|
+
- location: { path: string, range: { start: { line: number, character: number }, end: { line: number, character: number } } } | null — source location of the view if available
|
|
114
|
+
|
|
115
|
+
Notes:
|
|
116
|
+
- Read-only and idempotent with respect to the project model. Triggers a UI action in the editor.
|
|
117
|
+
- Only one preview panel can be open at a time.
|
|
118
|
+
|
|
119
|
+
Example response:
|
|
120
|
+
{
|
|
121
|
+
"location": {
|
|
122
|
+
"path": "/abs/path/project/model.c4",
|
|
123
|
+
"range": { "start": { "line": 10, "character": 0 }, "end": { "line": 30, "character": 0 } }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Open view in preview panel`},inputSchema:{viewId:z.string().describe(`View id (name)`),project:projectIdSchema},outputSchema:{location:locationSchema}},async(e,n)=>{let r=e.projectsManager.ensureProjectId(n.project),i=(await e.computedModel(r)).findView(n.viewId);if(!i)throw Error(`View with ID '${n.viewId}' not found in project ${r}`);return await e.views.openView(i.id,r),{location:mkLocate(e,r)({view:i.id})}}),readDeployment=likec4Tool({name:`read-deployment`,description:`
|
|
127
|
+
Read details about a deployment node or a deployed instance in a LikeC4 project.
|
|
128
|
+
|
|
129
|
+
What it does:
|
|
130
|
+
- Returns metadata about a deployment entity (node or instance), including kind, tags, color/shape, children, which views include it, and its source location.
|
|
131
|
+
|
|
132
|
+
Inputs:
|
|
133
|
+
- id: string — Deployment id (FQN)
|
|
134
|
+
- project: string (optional, defaults to "default") — Project id
|
|
135
|
+
|
|
136
|
+
Output fields:
|
|
137
|
+
- type: "deployment-node" | "deployed-instance"
|
|
138
|
+
- id: string — Deployment id (FQN)
|
|
139
|
+
- kind: string — Deployment node kind, or element kind for deployed instances
|
|
140
|
+
- name: string — Name of the deployment entity
|
|
141
|
+
- title: string — Title of the deployment entity
|
|
142
|
+
- description: string|null — Description text
|
|
143
|
+
- technology: string|null — Technology info, if any
|
|
144
|
+
- tags: string[] — Tags assigned to this entity
|
|
145
|
+
- project: string — Project id
|
|
146
|
+
- metadata: Record<string, string>
|
|
147
|
+
- links: Array<{ title: string|null, url: string, relative: string|null }> — external links associated with this deployment entity
|
|
148
|
+
- shape: string — Rendered shape
|
|
149
|
+
- color: string — Rendered color
|
|
150
|
+
- children: string[] — Child deployment ids (empty for instances)
|
|
151
|
+
- includedInViews: View[] — Views that include this entity
|
|
152
|
+
- instanceof: { id: string, title: string, kind: string } | null — If type is "deployed-instance", the referenced element
|
|
153
|
+
- sourceLocation: { path: string, range: { start: { line: number, character: number }, end: { line: number, character: number } } } | null
|
|
154
|
+
|
|
155
|
+
View (object) fields:
|
|
156
|
+
- id: string — view identifier
|
|
157
|
+
- title: string — view title
|
|
158
|
+
- type: "element" | "deployment" | "dynamic"
|
|
159
|
+
|
|
160
|
+
Notes:
|
|
161
|
+
- Read-only, idempotent; does not mutate the model.
|
|
162
|
+
|
|
163
|
+
Example request:
|
|
164
|
+
{ "id": "k8s.cluster.frontend", "project": "default" }
|
|
165
|
+
|
|
166
|
+
Example response (deployed instance):
|
|
167
|
+
{
|
|
168
|
+
"type": "deployed-instance",
|
|
169
|
+
"id": "k8s.cluster.frontend",
|
|
170
|
+
"kind": "k8s.pod",
|
|
171
|
+
"name": "frontend",
|
|
172
|
+
"title": "Frontend Pod",
|
|
173
|
+
"description": null,
|
|
174
|
+
"technology": "Kubernetes",
|
|
175
|
+
"tags": ["prod"],
|
|
176
|
+
"project": "default",
|
|
177
|
+
"metadata": {},
|
|
178
|
+
"links": [],
|
|
179
|
+
"shape": "rectangle",
|
|
180
|
+
"color": "#2F80ED",
|
|
181
|
+
"children": [],
|
|
182
|
+
"includedInViews": [
|
|
183
|
+
{ "id": "runtime-overview", "title": "Runtime Overview", "type": "deployment" }
|
|
184
|
+
],
|
|
185
|
+
"instanceof": { "id": "shop.frontend", "title": "Frontend", "kind": "component" },
|
|
186
|
+
"sourceLocation": {
|
|
187
|
+
"path": "/abs/path/project/model.c4",
|
|
188
|
+
"range": { "start": { "line": 10, "character": 0 }, "end": { "line": 25, "character": 0 } }
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read deployment entity`},inputSchema:{id:z.string().describe(`Deployment id (FQN)`),project:projectIdSchema},outputSchema:{type:z.enum([`deployment-node`,`deployed-instance`]),id:z.string().describe(`Deployment id (FQN)`),kind:z.string().describe(`Deployment node kind, or element kind for deployed instances`),name:z.string(),title:z.string(),description:z.string().nullable(),technology:z.string().nullable(),tags:z.array(z.string()),project:z.string(),metadata:z.record(z.union([z.string(),z.array(z.string())])),links:z.array(z.object({title:z.string().nullable().describe(`Optional link title`),url:z.string().describe(`Link URL`),relative:z.string().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this deployment entity`),shape:z.string(),color:z.string(),children:z.array(z.string()).describe(`Children of this deployment node (Array of Deployment ids)`),includedInViews:includedInViewsSchema.describe(`Views that include this deployment node`),instanceof:z.object({id:z.string().describe(`Element ID (FQN)`),title:z.string(),kind:z.string()}).nullable().describe(`If type is "deployed-instance", the referenced element`),sourceLocation:locationSchema}},async(e,n)=>{let r=e.projectsManager.ensureProjectId(n.project),i=(await e.computedModel(r)).deployment.findElement(n.id);invariant$1(i,`Deployment entity "${n.id}" not found in project "${r}"`);let a=mkLocate(e,r);return{type:i.isInstance()?`deployed-instance`:`deployment-node`,id:i.id,name:i.name,kind:i.kind,title:i.title,description:i.description.text,technology:i.technology,tags:[...i.tags],project:r,metadata:i.getMetadata(),links:(i.links??[]).map(e=>({title:e.title??null,url:e.url,relative:e.relative??null})),shape:i.shape,color:i.color,children:i.isInstance()?[]:[...i.children()].map(e=>e.id),includedInViews:includedInViews(i.views()),instanceof:i.isInstance()?{id:i.element.id,title:i.element.title,kind:i.element.kind}:null,sourceLocation:a({deployment:i.id})}}),readElement=likec4Tool({name:`read-element`,description:`
|
|
192
|
+
Read detailed information about a LikeC4 element.
|
|
193
|
+
|
|
194
|
+
Request:
|
|
195
|
+
- id: string — element id (FQN)
|
|
196
|
+
- project: string (optional) — project id. Defaults to "default" if omitted.
|
|
197
|
+
|
|
198
|
+
Response (JSON object):
|
|
199
|
+
- id: string — element id (FQN)
|
|
200
|
+
- name: string — element name
|
|
201
|
+
- kind: string — element kind
|
|
202
|
+
- title: string — human-readable title
|
|
203
|
+
- description: string|null — optional description
|
|
204
|
+
- technology: string|null — optional technology
|
|
205
|
+
- tags: string[] — assigned tags
|
|
206
|
+
- project: string — project id this element belongs to
|
|
207
|
+
- metadata: Record<string, string> — element metadata
|
|
208
|
+
- links: Array<{ title: string|null, url: string, relative: string|null }> — external links associated with this element
|
|
209
|
+
- shape: string — rendered shape
|
|
210
|
+
- color: string — rendered color
|
|
211
|
+
- children: string[] — ids (FQNs) of direct child elements
|
|
212
|
+
- defaultView: string|null — default view name if set
|
|
213
|
+
- includedInViews: View[] — views that include this element
|
|
214
|
+
- relationships: object — relationships of this element (direct and indirect)
|
|
215
|
+
- incoming: Array<{ source: { id: string, title: string, kind: string }, kind: string|null, target: string, title: string|null, description: string|null, technology: string|null, tags: string[] }>
|
|
216
|
+
- outgoing: Array<{ source: string, target: { id: string, title: string, kind: string }, kind: string|null, title: string|null, description: string|null, technology: string|null, tags: string[] }>
|
|
217
|
+
- deployedInstances: string[] — deployed instance ids (Deployment FQNs)
|
|
218
|
+
- sourceLocation: { path: string, range: { start: { line: number, character: number }, end: { line: number, character: number } } } | null — source location if available
|
|
219
|
+
|
|
220
|
+
View (object) fields:
|
|
221
|
+
- id: string — view identifier
|
|
222
|
+
- title: string — view title
|
|
223
|
+
- type: "element" | "deployment" | "dynamic"
|
|
224
|
+
|
|
225
|
+
Notes:
|
|
226
|
+
- Read-only, idempotent, no side effects.
|
|
227
|
+
- Safe to call repeatedly.
|
|
228
|
+
|
|
229
|
+
Example response:
|
|
230
|
+
{
|
|
231
|
+
"id": "shop.frontend",
|
|
232
|
+
"name": "frontend",
|
|
233
|
+
"kind": "container",
|
|
234
|
+
"title": "Frontend",
|
|
235
|
+
"description": "User-facing web app",
|
|
236
|
+
"technology": "React",
|
|
237
|
+
"tags": ["public"],
|
|
238
|
+
"project": "default",
|
|
239
|
+
"metadata": { "owner": "web" },
|
|
240
|
+
"links": [
|
|
241
|
+
{
|
|
242
|
+
"title": "Documentation",
|
|
243
|
+
"url": "https://docs.example.com/frontend",
|
|
244
|
+
"relative": null
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
"shape": "rounded-rectangle",
|
|
248
|
+
"color": "#2F80ED",
|
|
249
|
+
"children": ["shop.frontend.auth"],
|
|
250
|
+
"defaultView": "frontend-overview",
|
|
251
|
+
"includedInViews": [
|
|
252
|
+
{
|
|
253
|
+
"id": "frontend-overview",
|
|
254
|
+
"title": "Frontend Overview",
|
|
255
|
+
"type": "element"
|
|
256
|
+
}
|
|
257
|
+
],
|
|
258
|
+
"relationships": {
|
|
259
|
+
"incoming": [
|
|
260
|
+
{
|
|
261
|
+
"source": { "id": "shop.api", "title": "API", "kind": "container" },
|
|
262
|
+
"kind": "uses",
|
|
263
|
+
"target": "shop.frontend",
|
|
264
|
+
"title": "Calls",
|
|
265
|
+
"description": null,
|
|
266
|
+
"technology": "HTTPS",
|
|
267
|
+
"tags": []
|
|
268
|
+
}
|
|
269
|
+
],
|
|
270
|
+
"outgoing": []
|
|
271
|
+
},
|
|
272
|
+
"deployedInstances": ["k8s.cluster.frontend"],
|
|
273
|
+
"sourceLocation": {
|
|
274
|
+
"path": "/abs/path/project/model.c4",
|
|
275
|
+
"range": { "start": { "line": 10, "character": 0 }, "end": { "line": 25, "character": 0 } }
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read element`},inputSchema:{id:z.string().describe(`Element id (FQN)`),project:projectIdSchema},outputSchema:{id:z.string().describe(`Element id (FQN)`),kind:z.string().describe(`Element kind`),name:z.string().describe(`Element name`),title:z.string(),description:z.string().nullable(),technology:z.string().nullable(),tags:z.array(z.string()),project:z.string(),metadata:z.record(z.union([z.string(),z.array(z.string())])),links:z.array(z.object({title:z.string().nullable().describe(`Optional link title`),url:z.string().describe(`Link URL`),relative:z.string().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this element`),shape:z.string(),color:z.string(),children:z.array(z.string()).describe(`Children of this element (Array of FQNs)`),defaultView:z.string().nullable().describe(`Name of the default view of this element`),includedInViews:includedInViewsSchema.describe(`Views that include this element`),relationships:z.object({incoming:z.array(z.object({source:z.object({id:z.string(),title:z.string(),kind:z.string()}).describe(`Source element of this relationship`),kind:z.string().nullable().describe(`Relationship kind`),target:z.string().describe(`Target element id (FQN), either this element or nested element, if relationship is indirect`),title:z.string().nullable().describe(`Relationship title`),description:z.string().nullable().describe(`Relationship description`),technology:z.string().nullable().describe(`Relationship technology`),tags:z.array(z.string()).describe(`Relationship tags`)})).describe(`Incoming relationships of this element (direct and indirect, incoming to nested elements)`),outgoing:z.array(z.object({source:z.string().describe(`Source element id (FQN), either this element or nested element, if relationship is indirect`),target:z.object({id:z.string(),title:z.string(),kind:z.string()}).describe(`Target element of this relationship`),kind:z.string().nullable().describe(`Relationship kind`),title:z.string().nullable().describe(`Relationship title`),description:z.string().nullable().describe(`Relationship description`),technology:z.string().nullable().describe(`Relationship technology`),tags:z.array(z.string()).describe(`Relationship tags`)})).describe(`Outgoing relationships of this element (direct and indirect, outgoing from nested elements)`)}).describe(`Relationships of this element`),deployedInstances:z.array(z.string()).describe(`Deployed instances of this element (Array of Deployment FQNs)`),sourceLocation:locationSchema}},async(e,n)=>{let r=e.projectsManager.ensureProjectId(n.project),i=(await e.computedModel(r)).findElement(n.id);invariant$1(i,`Element "${n.id}" not found in project "${r}"`);let a=mkLocate(e,r);return{id:i.id,name:i.name,kind:i.kind,title:i.title,description:i.description.text,technology:i.technology,tags:[...i.tags],project:r,metadata:i.getMetadata(),links:(i.links??[]).map(e=>({title:e.title??null,url:e.url,relative:e.relative??null})),shape:i.shape,color:i.color,children:[...i.children()].map(e=>e.id),defaultView:i.defaultView?.id||null,includedInViews:includedInViews(i.views()),relationships:{incoming:[...i.incoming()].map(e=>({source:{id:e.source.id,title:e.source.title,kind:e.source.kind},kind:e.kind,target:e.target.id,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags]})),outgoing:[...i.outgoing()].map(e=>({source:e.source.id,target:{id:e.target.id,title:e.target.title,kind:e.target.kind},kind:e.kind,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags]}))},deployedInstances:[...i.deployments()].map(e=>e.id),sourceLocation:a({element:i.id})}}),readProjectSummary=likec4Tool({name:`read-project-summary`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read project summary`},description:`
|
|
279
|
+
Request:
|
|
280
|
+
- project: string (optional) — project id. Defaults to "default" if omitted.
|
|
281
|
+
|
|
282
|
+
Response (JSON object):
|
|
283
|
+
- title: string — human-readable project title
|
|
284
|
+
- folder: string — absolute path to the project root
|
|
285
|
+
- sources: string[] — absolute file paths of model documents
|
|
286
|
+
- specification: object
|
|
287
|
+
- elementKinds: string[] — all element kinds
|
|
288
|
+
- relationshipKinds: string[] — all relationship kinds
|
|
289
|
+
- deploymentKinds: string[] — all deployment kinds
|
|
290
|
+
- tags: string[] — all tags
|
|
291
|
+
- metadataKeys: string[] — used metadata keys
|
|
292
|
+
- elements: Element[] — list of elements
|
|
293
|
+
- deployments: Deployment[] — list of deployment entities
|
|
294
|
+
- views: View[] — list of views defined in the model
|
|
295
|
+
|
|
296
|
+
Element (object) fields:
|
|
297
|
+
- id: string — element id (FQN)
|
|
298
|
+
- kind: string — element kind
|
|
299
|
+
- title: string — element title
|
|
300
|
+
- tags: string[] — element tags
|
|
301
|
+
|
|
302
|
+
Deployment (object) fields:
|
|
303
|
+
- type = "deployment-node": { id: string, kind: string, title: string, tags: string[] }
|
|
304
|
+
- type = "deployed-instance": { id: string, title: string, tags: string[], referencedElementId: string }
|
|
305
|
+
|
|
306
|
+
View (object) fields:
|
|
307
|
+
- id: string — view identifier
|
|
308
|
+
- title: string — view title
|
|
309
|
+
- type: "element" | "deployment" | "dynamic"
|
|
310
|
+
|
|
311
|
+
Notes:
|
|
312
|
+
- Read-only, idempotent, no side effects.
|
|
313
|
+
- Safe to call repeatedly.
|
|
314
|
+
|
|
315
|
+
Example response:
|
|
316
|
+
{
|
|
317
|
+
"title": "Cloud Boutique",
|
|
318
|
+
"folder": "/abs/path/to/workspace/examples/cloud-system",
|
|
319
|
+
"sources": [
|
|
320
|
+
"/abs/path/to/workspace/examples/cloud-system/model.c4"
|
|
321
|
+
],
|
|
322
|
+
"specification": {
|
|
323
|
+
"elementKinds": ["system", "container", "component"],
|
|
324
|
+
"relationshipKinds": ["uses", "depends-on"],
|
|
325
|
+
"deploymentKinds": ["node", "cluster"],
|
|
326
|
+
"tags": ["public", "internal"],
|
|
327
|
+
"metadataKeys": ["owner", "tier"]
|
|
328
|
+
},
|
|
329
|
+
"elements": [
|
|
330
|
+
{
|
|
331
|
+
"id": "shop.frontend",
|
|
332
|
+
"kind": "component",
|
|
333
|
+
"title": "Frontend",
|
|
334
|
+
"tags": ["public"]
|
|
335
|
+
}
|
|
336
|
+
],
|
|
337
|
+
"deployments": [
|
|
338
|
+
{
|
|
339
|
+
"type": "deployment-node",
|
|
340
|
+
"id": "k8s.shop.frontend",
|
|
341
|
+
"kind": "cluster",
|
|
342
|
+
"title": "Frontend",
|
|
343
|
+
"tags": []
|
|
344
|
+
}
|
|
345
|
+
],
|
|
346
|
+
"views": [
|
|
347
|
+
{
|
|
348
|
+
"name": "system-overview",
|
|
349
|
+
"title": "System Overview",
|
|
350
|
+
"type": "element"
|
|
351
|
+
}
|
|
352
|
+
]
|
|
353
|
+
}
|
|
354
|
+
`,inputSchema:{project:projectIdSchema},outputSchema:{title:z.string(),folder:z.string(),sources:z.array(z.string()),specification:z.object({elementKinds:z.array(z.string()),relationshipKinds:z.array(z.string()),deploymentKinds:z.array(z.string()),tags:z.array(z.string()),metadataKeys:z.array(z.string())}),elements:z.array(z.object({id:z.string(),kind:z.string(),title:z.string(),tags:z.array(z.string())})).describe(`List of elements in the project`),deployments:z.array(z.discriminatedUnion(`type`,[z.object({type:z.literal(`deployment-node`),id:z.string().describe(`Node ID`),kind:z.string().describe(`Deployment node kind`),title:z.string().describe(`Node title`),tags:z.array(z.string())}),z.object({type:z.literal(`deployed-instance`),id:z.string().describe(`Node ID`),title:z.string().describe(`Node title`),tags:z.array(z.string()),referencedElementId:z.string().describe(`Element ID (FQN)`)})])).describe(`List of deployment nodes and deployed instances in the project`),views:z.array(z.object({id:z.string(),title:z.string(),type:z.enum([`element`,`deployment`,`dynamic`])}))}},async(e,r)=>{let i=e.projectsManager.ensureProjectId(r.project),a=e.project(i),o=await e.computedModel(i);return{title:a.title,folder:a.folder.fsPath,specification:{elementKinds:t(o.specification.elements),relationshipKinds:t(o.specification.relationships),deploymentKinds:t(o.specification.deployments),tags:[...o.tags],metadataKeys:o.specification.metadataKeys??[]},elements:[...o.elements()].filter(e=>!e.imported).map(e=>({id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]})),deployments:[...o.deployment.elements()].map(e=>e.isInstance()?{type:`deployed-instance`,id:e.id,title:e.title,tags:[...e.tags],referencedElementId:e.element.id}:{type:`deployment-node`,id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]}),views:[...o.views()].map(e=>({id:e.id,title:e.titleOrId,type:e.$view._type})),sources:a.documents?.map(e=>e.fsPath)??[]}}),modelRef=e=>e.hasElement()?e.element.id:e.hasDeployment()?e.deployment.id:null,nodeSchema=z.discriminatedUnion(`type`,[z.object({type:z.literal(`element`),id:z.string().describe(`Node ID`),elementId:z.string().describe(`Element ID (FQN)`),kind:z.string().describe(`Element kind`),title:z.string().describe(`Node title`),description:z.string().nullable(),technology:z.string().nullable(),children:z.array(z.string()).describe(`Children nodes, array of node IDs`),shape:z.string().describe(`Rendered shape`),color:z.string().describe(`Rendered color`),tags:z.array(z.string())}),z.object({type:z.literal(`deployment-node`),id:z.string().describe(`Node ID`),deploymentId:z.string().describe(`Deployment entity ID (FQN)`),kind:z.string().describe(`Deployment kind`),title:z.string().describe(`Node title`),description:z.string().nullable(),technology:z.string().nullable(),children:z.array(z.string()).describe(`Children nodes, array of node IDs`),shape:z.string().describe(`Rendered shape`),color:z.string().describe(`Rendered color`),tags:z.array(z.string())}),z.object({type:z.literal(`deployed-instance`),id:z.string().describe(`Node ID`),deploymentId:z.string().describe(`Deployment entity ID (FQN)`),title:z.string().describe(`Node title`),description:z.string().nullable(),technology:z.string().nullable(),referencedElement:z.object({id:z.string().describe(`Element ID (FQN)`),kind:z.string().describe(`Element kind`),title:z.string().describe(`Element title`)}),shape:z.string().describe(`Rendered shape`),color:z.string().describe(`Rendered color`),tags:z.array(z.string())})]),readView=likec4Tool({name:`read-view`,description:`
|
|
355
|
+
Read detailed information about a LikeC4 view.
|
|
356
|
+
|
|
357
|
+
Request:
|
|
358
|
+
- viewId: string — view id (name)
|
|
359
|
+
- project: string (optional) — project id. Defaults to "default" if omitted.
|
|
360
|
+
|
|
361
|
+
Response (JSON object):
|
|
362
|
+
- id: string — view id
|
|
363
|
+
- type: "element" | "deployment" | "dynamic" — view type
|
|
364
|
+
- title: string — view title (falls back to id if not set)
|
|
365
|
+
- description: string|null — optional description
|
|
366
|
+
- tags: string[] — view tags
|
|
367
|
+
- project: string — project id this view belongs to
|
|
368
|
+
- nodes: Node[] — nodes included in the view
|
|
369
|
+
- edges: Edge[] — relationships between nodes
|
|
370
|
+
- sourceLocation: { path: string, range: { start: { line: number, character: number }, end: { line: number, character: number } } } | null — source location if available
|
|
371
|
+
|
|
372
|
+
Node (discriminated union by "type"):
|
|
373
|
+
- type = "element": { id: string, elementId: string, kind: string, title: string, description: string|null, technology: string|null, children: string[], shape: string, color: string, tags: string[] }
|
|
374
|
+
- 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[] }
|
|
375
|
+
- 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[] }
|
|
376
|
+
|
|
377
|
+
Edge object:
|
|
378
|
+
- { source: string, target: string, label: string|null, description: string|null, technology: string|null, tags: string[] }
|
|
379
|
+
|
|
380
|
+
Notes:
|
|
381
|
+
- Read-only, idempotent, no side effects.
|
|
382
|
+
|
|
383
|
+
Example response:
|
|
384
|
+
{
|
|
385
|
+
"id": "system-overview",
|
|
386
|
+
"type": "element",
|
|
387
|
+
"title": "System Overview",
|
|
388
|
+
"description": null,
|
|
389
|
+
"tags": [],
|
|
390
|
+
"project": "default",
|
|
391
|
+
"nodes": [
|
|
392
|
+
{ "type": "logical", "id": "n1", "elementId": "shop.frontend", "kind": "container", "title": "Frontend", "description": null, "technology": "React", "children": [], "shape": "rounded-rectangle", "color": "#2F80ED", "tags": [] }
|
|
393
|
+
],
|
|
394
|
+
"edges": [
|
|
395
|
+
{ "source": "n1", "target": "n2", "label": "calls", "description": null, "technology": "HTTPS", "tags": [] }
|
|
396
|
+
],
|
|
397
|
+
"sourceLocation": {
|
|
398
|
+
"path": "/abs/path/project/model.c4",
|
|
399
|
+
"range": { "start": { "line": 10, "character": 0 }, "end": { "line": 30, "character": 0 } }
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read view`},inputSchema:{viewId:z.string().describe(`View id (name)`),project:projectIdSchema},outputSchema:{id:z.string(),type:z.enum([`element`,`deployment`,`dynamic`]).describe(`View type`),title:z.string(),description:z.string().nullable(),tags:z.array(z.string()),project:z.string(),nodes:z.array(nodeSchema),edges:z.array(z.object({source:z.string().describe(`Source node`),target:z.string().describe(`Target node`),label:z.string().nullable(),description:z.string().nullable(),technology:z.string().nullable(),tags:z.array(z.string())})).describe(`Edge represents relationship between nodes`),sourceLocation:locationSchema}},async(e,n)=>{let r=e.projectsManager.ensureProjectId(n.project),i=e.project(r),a=(await e.computedModel(r)).findView(n.viewId);if(!a)throw Error(`View with ID '${n.viewId}' not found in project ${i.id}`);let o=mkLocate(e,i.id);return{id:a.id,type:a.$view._type,title:a.title??a.id,description:a.description.text,tags:[...a.tags],project:i.id,nodes:[...a.nodes()].flatMap(e=>{let n={id:e.id,title:e.title,description:e.description.text,technology:e.technology,shape:e.shape,color:e.color,tags:[...e.tags]};return e.hasDeployedInstance()?{...n,type:`deployed-instance`,deploymentId:e.deployment.id,referencedElement:{id:e.deployment.element.id,kind:e.deployment.element.kind,title:e.deployment.element.title}}:e.hasDeployment()?{...n,type:`deployment-node`,kind:e.deployment.kind,deploymentId:e.deployment.id,children:[...e.children()].map(e=>e.id)}:e.hasElement()?{...n,type:`element`,elementId:e.element.id,kind:e.element.kind,children:[...e.children()].flatMap(e=>modelRef(e)??[])}:[]}),edges:[...a.edges()].map(e=>({source:e.source.id,target:e.target.id,label:e.label,description:e.description.text,technology:e.technology,tags:[...e.tags]})),sourceLocation:o({view:a.id})}}),searchResultSchema=z.array(z.discriminatedUnion(`type`,[z.object({type:z.literal(`element`),project:z.string().describe(`Project ID`),id:z.string().describe(`Element ID (FQN)`),name:z.string().describe(`Element name`),kind:z.string(),title:z.string(),technology:z.string().nullable(),shape:z.string(),includedInViews:includedInViewsSchema,metadata:z.record(z.union([z.string(),z.array(z.string())])),tags:z.array(z.string())}),z.object({type:z.literal(`deployment-node`),project:z.string().describe(`Project ID`),id:z.string().describe(`Deployment ID (FQN)`),name:z.string().describe(`Deployment name`),kind:z.string(),title:z.string(),technology:z.string().nullable(),shape:z.string(),includedInViews:includedInViewsSchema,metadata:z.record(z.union([z.string(),z.array(z.string())])),tags:z.array(z.string())})])),searchElement=likec4Tool({name:`search-element`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Search elements`},description:`
|
|
403
|
+
Search LikeC4 elements and deployment nodes across all projects.
|
|
404
|
+
|
|
405
|
+
Query syntax (case-insensitive):
|
|
406
|
+
- kind:<value> filters by kind
|
|
407
|
+
- shape:<value> filters by shape
|
|
408
|
+
- meta:<key> filters by having metadata with the given key
|
|
409
|
+
- #<value> matches assigned tags
|
|
410
|
+
- <value> matches id (FQN) or title
|
|
411
|
+
|
|
412
|
+
Request:
|
|
413
|
+
- search: string — at least 2 characters
|
|
414
|
+
|
|
415
|
+
Response (JSON object):
|
|
416
|
+
- total: number - total number of results
|
|
417
|
+
- found: Result[] - returns top 20 results
|
|
418
|
+
|
|
419
|
+
Result (discriminated union by "type"):
|
|
420
|
+
- type = "element": { id: string, name: string, kind: string, title: string, technology: string|null, shape: string, project: string, includedInViews: View[], tags: string[], metadata: Record<string, string> }
|
|
421
|
+
- type = "deployment-node": { id: string, name: string, kind: string, title: string, technology: string|null, shape: string, project: string, includedInViews: View[], tags: string[], metadata: Record<string, string> }
|
|
422
|
+
|
|
423
|
+
View (object) fields:
|
|
424
|
+
- id: string — view identifier
|
|
425
|
+
- title: string — view title
|
|
426
|
+
- type: "element" | "deployment" | "dynamic"
|
|
427
|
+
|
|
428
|
+
Notes:
|
|
429
|
+
- Read-only, idempotent.
|
|
430
|
+
- Use results as input to other tools (e.g., read-element, read-view).
|
|
431
|
+
|
|
432
|
+
Example response:
|
|
433
|
+
{
|
|
434
|
+
"total": 1,
|
|
435
|
+
"found": [
|
|
436
|
+
{
|
|
437
|
+
"type": "logical",
|
|
438
|
+
"project": "default",
|
|
439
|
+
"id": "shop.frontend",
|
|
440
|
+
"name": "frontend",
|
|
441
|
+
"kind": "container",
|
|
442
|
+
"title": "Frontend",
|
|
443
|
+
"technology": "React",
|
|
444
|
+
"shape": "rectangle",
|
|
445
|
+
"includedInViews": [
|
|
446
|
+
{
|
|
447
|
+
"id": "system-overview",
|
|
448
|
+
"title": "System Overview",
|
|
449
|
+
"type": "element"
|
|
450
|
+
}
|
|
451
|
+
],
|
|
452
|
+
"tags": ["public"],
|
|
453
|
+
"metadata": {}
|
|
454
|
+
}
|
|
455
|
+
]
|
|
456
|
+
}
|
|
457
|
+
`,inputSchema:{search:z.string().min(2,`Search must be at least 2 characters long`)},outputSchema:{total:z.number(),found:searchResultSchema}},async(e,n)=>{let r=e.projects(),a=[],o=n.search.toLowerCase(),predicate;o.startsWith(`kind:`)?(o=o.slice(5),logger$1.debug(`search by kind: {search}`,{search:o}),predicate=e=>e.kind.toLowerCase()===o):o.startsWith(`shape:`)?(o=o.slice(6),logger$1.debug(`search by shape: {search}`,{search:o}),predicate=e=>e.shape.toLowerCase()===o):o.startsWith(`meta:`)?(o=o.slice(5),logger$1.debug(`search by metadata: {search}`,{search:o}),predicate=e=>!!e.getMetadata(o)):o.startsWith(`#`)?(o=o.slice(1),logger$1.debug(`search by tag: {search}`,{search:o}),predicate=e=>e.tags.some(e=>e.toLowerCase().includes(o))):(logger$1.debug(`search by id/title: {search}`,{search:o}),predicate=e=>e.id.toLowerCase().includes(o)||e.title.toLowerCase().includes(o));for(let n of r)try{let r=await e.computedModel(n.id);for(let e of ifilter(r.elements(),e=>!e.imported&&predicate(e)))a.push({type:`element`,project:n.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:includedInViews(e.views())});for(let e of ifilter(r.deployment.nodes(),predicate))a.push({type:`deployment-node`,project:n.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:includedInViews(e.views())})}catch(e){logger$1.error(`Error searching in project ${n.id}:`,{error:e})}return{total:a.length,found:a.slice(0,20)}});var MCPServerFactory=class{constructor(e){this.services=e}create(n){let r=this.services.shared.lsp.Connection!==void 0,i=new McpServer({name:`LikeC4`,version},{instructions:`LikeC4 MCP – query and navigate LikeC4 models.
|
|
458
|
+
|
|
459
|
+
Conventions:
|
|
460
|
+
- All tools are read-only and idempotent.
|
|
461
|
+
- "project" is optional and defaults to "default".
|
|
462
|
+
|
|
463
|
+
Available tools:
|
|
464
|
+
- list-projects — List all LikeC4 projects in the workspace.
|
|
465
|
+
- read-project-summary — Project specification (element kinds, deployment node kinds, tags, metadata keys), all elements, deployment nodes and views. Input: { project? }.
|
|
466
|
+
- search-element — Search elements and deployment nodes across all projects by id/title/kind/shape/tags/metadata. Input: { search }.
|
|
467
|
+
- read-element — Full element details including relationships, includedInViews, deployedInstances, metadata and sourceLocation. Input: { id, project? }.
|
|
468
|
+
- read-deployment — Details of a deployment node or deployed instance. Input: { id, project? }.
|
|
469
|
+
- read-view — Full view details (nodes/edges) and sourceLocation. Input: { viewId, project? }.
|
|
470
|
+
- find-relationships — Direct and indirect relationships between two elements in a project. Input: { element1, element2, project? }.
|
|
471
|
+
${r?`- open-view — Opens the LikeC4 view panel in the editor. Triggers UI; at most one preview panel at a time. Input: { viewId, project? }.`:``}
|
|
472
|
+
|
|
473
|
+
Instructions:
|
|
474
|
+
- Identify the project first
|
|
475
|
+
- Use "search-element" to find elements by id/title/kind/shape/tags/metadata and select the project
|
|
476
|
+
- Use "read-project-summary" to find all elements and deployment nodes inside the project, what kinds, tags, metadata keys are available
|
|
477
|
+
- Use "list-projects" to list all available projects
|
|
478
|
+
- If response returns "sourceLocation", provide link to this location in the editor
|
|
479
|
+
|
|
480
|
+
Full documentation: https://likec4.dev/llms-full.txt
|
|
481
|
+
`,enforceStrictCapabilities:!0,...n,capabilities:{tools:{},logging:{},...n?.capabilities}});return i.registerTool(...listProjects(this.services.likec4.LanguageServices)),i.registerTool(...readProjectSummary(this.services.likec4.LanguageServices)),i.registerTool(...readElement(this.services.likec4.LanguageServices)),i.registerTool(...readDeployment(this.services.likec4.LanguageServices)),i.registerTool(...readView(this.services.likec4.LanguageServices)),i.registerTool(...searchElement(this.services.likec4.LanguageServices)),i.registerTool(...findRelationships(this.services.likec4.LanguageServices)),r&&i.registerTool(...openView(this.services.likec4.LanguageServices)),i.server.onerror=n=>{logger$2.error(loggable(n))},i}},StdioLikeC4MCPServer=class{transport=void 0;_mcp=void 0;constructor(e){this.services=e}get mcp(){if(!this._mcp)throw Error(`MCP server is not started`);return this._mcp}get isStarted(){return this.transport!==void 0}get port(){return NaN}async dispose(){await this.stop()}async start(){this.transport||(logger$1.info(`Starting MCP stdio server`),this._mcp=this.services.mcp.ServerFactory.create(),this.transport=new StdioServerTransport,await this._mcp.connect(this.transport),logger$1.info(`LikeC4 MCP Server running on stdio`))}async stop(){if(this.transport)try{logger$1.info(`Stopping MCP stdio server`),await this.transport.close(),this._mcp&&await this._mcp.close()}finally{this._mcp=void 0,this.transport=void 0}}};async function createHonoApp(e){let n=new Hono;n.use(`*`,cors({origin:`*`,allowHeaders:[`Content-Type`,`mcp-session-id`,`Last-Event-ID`,`mcp-protocol-version`],exposeHeaders:[`mcp-session-id`,`mcp-protocol-version`]})),n.get(`/health`,e=>e.json({status:`ok`}));let r=e.create(),i=new StreamableHTTPTransport({eventStore:new MemoryEventStore({})});return n.all(`/mcp`,async e=>(r.isConnected()||await r.connect(i),await i.handleRequest(e))),n.notFound(e=>(logger$1.debug(`${e.req.method} ${e.req.url} not found`),e.json({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not found.`},id:null},{status:404}))),n.onError((e,n)=>(logger$1.error(loggable(e)),n.json({jsonrpc:`2.0`,error:{code:-32603,message:`Internal server error`},id:null},{status:500}))),n}async function startServer(e){let{factory:n,port:r}=e,i=await createHonoApp(n);return new Promise((e,n)=>{let a=serve({fetch:i.fetch,hostname:`0.0.0.0`,port:r}).prependOnceListener(`error`,n).prependOnceListener(`listening`,()=>{a.removeListener(`error`,n),e(a.unref())})})}var StreamableLikeC4MCPServer=class{server=void 0;constructor(e,n=33335){this.services=e,this._port=n}get mcp(){throw Error(`StreamableLikeC4MCPServer has access to McpServer only during the request`)}get isStarted(){return this.server?.listening===!0}get port(){return this._port}async dispose(){await this.stop()}async start(e=this._port){if(this.server){if(this.port===e)return;await this.stop()}logger$1.info(`Starting MCP server on port {port}`,{port:e}),this._port=e,this.server=await startServer({factory:this.services.mcp.ServerFactory,port:e}),logger$1.info(`MCP server ready at http://0.0.0.0:{port}/mcp`,{port:e})}stop(){let e=this.server;return e?(logger$1.info(`Stopping MCP server`),this.server=void 0,new Promise(n=>{e.close(e=>{e?logger$1.error(`Failed to stop MCP server`,{err:e}):logger$1.info(`MCP server stopped`),n()})})):(logger$1.info(`MCP server is not running, nothing to stop`),Promise.resolve())}};function streamableLikeC4MCPServer(e,n=33335){logger$1.debug(`Creating StreamableLikeC4MCPServer`);let r=new StreamableLikeC4MCPServer(e,n),i=e.LanguageMetaData.languageId,a=e.shared.lsp.Connection;return e.shared.workspace.ConfigurationProvider.onConfigurationSectionUpdate(e=>{if(e.section!==i){logger$1.warn(`Unexpected configuration update: {update}`,{update:e});return}let{enabled:o=!1,port:c=n}=e.configuration.mcp;if(!o){r.stop();return}Promise.resolve().then(()=>r.start(c)).then(()=>{a?.telemetry?.logEvent({eventName:`mcp-server-started`,mcpPort:c})}).catch(e=>{let n=loggable(e);a?.telemetry?.logEvent({eventName:`mcp-server-start-failed`,mcpPort:c,message:n}),logger$1.warn(`Failed to start LikeC4 MCP Server: \n${n}`),a&&a.window.showErrorMessage(`LikeC4: Failed to start MCP Server\n\n${n}`)})}),r}function stdioLikeC4MCPServer(e){return new StdioLikeC4MCPServer(e)}function WithMCPServer(e=`sse`){return{mcpServer:n=>e===`stdio`?stdioLikeC4MCPServer(n):streamableLikeC4MCPServer(n,typeof e==`object`?e.port:33335),mcpServerFactory:e=>new MCPServerFactory(e)}}export{WithMCPServer as t};
|