@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
package/dist/empty.d.ts
ADDED
package/dist/empty.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LikeC4SharedServices } from '../module';
|
|
2
|
+
import type { FileSystemWatcher, FileSystemWatcherModuleContext } from './FileSystemWatcher';
|
|
3
|
+
export declare const chokidarFileSystemWatcher: FileSystemWatcherModuleContext;
|
|
4
|
+
/**
|
|
5
|
+
* A no-op file system watcher.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ChokidarFileSystemWatcher implements FileSystemWatcher {
|
|
8
|
+
protected services: LikeC4SharedServices;
|
|
9
|
+
private watcher?;
|
|
10
|
+
constructor(services: LikeC4SharedServices);
|
|
11
|
+
watch(folder: string): void;
|
|
12
|
+
dispose(): Promise<void>;
|
|
13
|
+
private createWatcher;
|
|
14
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { loggable } from "@likec4/log";
|
|
2
|
+
import chokidar from "chokidar";
|
|
3
|
+
import { URI } from "langium";
|
|
4
|
+
import { logger as mainLogger } from "../logger.js";
|
|
5
|
+
import { isAnyLikeC4File, isLikeC4ProjectFile } from "./LikeC4FileSystem.js";
|
|
6
|
+
const logger = mainLogger.getChild("chokidar");
|
|
7
|
+
export const chokidarFileSystemWatcher = {
|
|
8
|
+
fileSystemWatcher: (services) => new ChokidarFileSystemWatcher(services)
|
|
9
|
+
};
|
|
10
|
+
export class ChokidarFileSystemWatcher {
|
|
11
|
+
constructor(services) {
|
|
12
|
+
this.services = services;
|
|
13
|
+
}
|
|
14
|
+
watcher;
|
|
15
|
+
watch(folder) {
|
|
16
|
+
if (this.watcher) {
|
|
17
|
+
this.watcher.add(folder);
|
|
18
|
+
} else {
|
|
19
|
+
this.watcher = this.createWatcher(folder);
|
|
20
|
+
}
|
|
21
|
+
logger.debug(`watching folder: ${folder}`);
|
|
22
|
+
}
|
|
23
|
+
async dispose() {
|
|
24
|
+
if (this.watcher) {
|
|
25
|
+
await this.watcher.close();
|
|
26
|
+
this.watcher = void 0;
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
createWatcher(folder) {
|
|
31
|
+
let watcher = chokidar.watch(folder, {
|
|
32
|
+
ignored: (path, stats) => path.includes("node_modules") || !!stats && stats.isFile() && !isAnyLikeC4File(path),
|
|
33
|
+
ignoreInitial: true
|
|
34
|
+
});
|
|
35
|
+
const onAddOrChange = async (path) => {
|
|
36
|
+
try {
|
|
37
|
+
if (isLikeC4ProjectFile(path)) {
|
|
38
|
+
logger.debug(`project file changed: ${path}`);
|
|
39
|
+
await this.services.workspace.ProjectsManager.reloadProjects();
|
|
40
|
+
} else {
|
|
41
|
+
logger.debug(`file changed: ${path}`);
|
|
42
|
+
await this.services.workspace.DocumentBuilder.update([URI.file(path)], []);
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
logger.error(loggable(error));
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const onRemove = async (path) => {
|
|
49
|
+
try {
|
|
50
|
+
if (isLikeC4ProjectFile(path)) {
|
|
51
|
+
logger.debug(`project file removed: ${path}`);
|
|
52
|
+
await this.services.workspace.ProjectsManager.reloadProjects();
|
|
53
|
+
} else {
|
|
54
|
+
logger.debug(`file removed: ${path}`);
|
|
55
|
+
await this.services.workspace.DocumentBuilder.update([], [URI.file(path)]);
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
logger.error(loggable(error));
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
watcher.on("add", onAddOrChange).on("change", onAddOrChange).on("unlink", onRemove);
|
|
62
|
+
return watcher;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AsyncDisposable } from 'langium';
|
|
2
|
+
import { type LikeC4SharedServices } from '../module';
|
|
3
|
+
export interface FileSystemWatcherModuleContext {
|
|
4
|
+
fileSystemWatcher: (services: LikeC4SharedServices) => FileSystemWatcher;
|
|
5
|
+
}
|
|
6
|
+
export declare const noopFileSystemWatcher: FileSystemWatcherModuleContext;
|
|
7
|
+
export interface FileSystemWatcher extends AsyncDisposable {
|
|
8
|
+
/**
|
|
9
|
+
* Watches a folder for changes and triggers a reload of the documents and projects.
|
|
10
|
+
*/
|
|
11
|
+
watch(folder: string): void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A no-op file system watcher.
|
|
15
|
+
*/
|
|
16
|
+
export declare class NoopFileSystemWatcher implements FileSystemWatcher {
|
|
17
|
+
watch(): void;
|
|
18
|
+
dispose(): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FileSystemModuleContext } from './index';
|
|
2
|
+
export declare const LikeC4FileSystem: (ehableWatcher?: boolean) => FileSystemModuleContext;
|
|
3
|
+
export declare const isLikeC4ProjectFile: (path: string) => boolean;
|
|
4
|
+
export declare const isLikeC4File: (path: string) => any;
|
|
5
|
+
export declare const isAnyLikeC4File: (path: string) => any;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { fdir } from "fdir";
|
|
2
|
+
import { URI } from "langium";
|
|
3
|
+
import { NodeFileSystemProvider } from "langium/node";
|
|
4
|
+
import { LikeC4LanguageMetaData } from "../generated/module.js";
|
|
5
|
+
import { Content, isLikeC4Builtin } from "../likec4lib.js";
|
|
6
|
+
import { logError } from "../logger.js";
|
|
7
|
+
import { ProjectsManager } from "../workspace/ProjectsManager.js";
|
|
8
|
+
import { chokidarFileSystemWatcher } from "./ChokidarWatcher.js";
|
|
9
|
+
import { noopFileSystemWatcher } from "./FileSystemWatcher.js";
|
|
10
|
+
export const LikeC4FileSystem = (ehableWatcher = true) => ({
|
|
11
|
+
fileSystemProvider: () => new SymLinkTraversingFileSystemProvider(),
|
|
12
|
+
...ehableWatcher ? chokidarFileSystemWatcher : noopFileSystemWatcher
|
|
13
|
+
});
|
|
14
|
+
export const isLikeC4ProjectFile = (path) => ProjectsManager.ConfigFileNames.some((ext) => path.endsWith(ext));
|
|
15
|
+
export const isLikeC4File = (path) => LikeC4LanguageMetaData.fileExtensions.some((ext) => path.endsWith(ext));
|
|
16
|
+
export const isAnyLikeC4File = (path) => isLikeC4File(path) || isLikeC4ProjectFile(path);
|
|
17
|
+
class SymLinkTraversingFileSystemProvider extends NodeFileSystemProvider {
|
|
18
|
+
async readFile(uri) {
|
|
19
|
+
if (isLikeC4Builtin(uri)) {
|
|
20
|
+
return Promise.resolve(Content);
|
|
21
|
+
}
|
|
22
|
+
return await super.readFile(uri);
|
|
23
|
+
}
|
|
24
|
+
async readDirectory(folderPath) {
|
|
25
|
+
const entries = [];
|
|
26
|
+
try {
|
|
27
|
+
const crawled = await new fdir().withSymlinks({ resolvePaths: false }).withFullPaths().filter(isLikeC4File).crawl(folderPath.fsPath).withPromise();
|
|
28
|
+
for (const path of crawled) {
|
|
29
|
+
entries.push({
|
|
30
|
+
isFile: true,
|
|
31
|
+
isDirectory: false,
|
|
32
|
+
uri: URI.file(path)
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
} catch (error) {
|
|
36
|
+
logError(error);
|
|
37
|
+
}
|
|
38
|
+
return entries;
|
|
39
|
+
}
|
|
40
|
+
async scanProjectFiles(folderUri) {
|
|
41
|
+
const entries = [];
|
|
42
|
+
try {
|
|
43
|
+
const crawled = await new fdir().withSymlinks({ resolvePaths: false }).withFullPaths().filter(isLikeC4ProjectFile).crawl(folderUri.fsPath).withPromise();
|
|
44
|
+
for (const path of crawled) {
|
|
45
|
+
entries.push({
|
|
46
|
+
isFile: true,
|
|
47
|
+
isDirectory: false,
|
|
48
|
+
uri: URI.file(path)
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
logError(error);
|
|
53
|
+
}
|
|
54
|
+
return entries;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FileSystemNode, FileSystemProvider as LangiumFileSystemProvider, LangiumSharedCoreServices } from 'langium';
|
|
2
|
+
import { URI } from 'vscode-uri';
|
|
3
|
+
import { type FileSystemWatcherModuleContext } from './FileSystemWatcher';
|
|
4
|
+
export type { FileSystemWatcher } from './FileSystemWatcher';
|
|
5
|
+
export interface FileSystemProvider extends LangiumFileSystemProvider {
|
|
6
|
+
/**
|
|
7
|
+
* Scans the project files for the given URI.
|
|
8
|
+
* @returns The list of file system entries that are contained within the specified directory.
|
|
9
|
+
*/
|
|
10
|
+
scanProjectFiles(folderUri: URI): Promise<FileSystemNode[]>;
|
|
11
|
+
}
|
|
12
|
+
export interface FileSystemModuleContext extends FileSystemWatcherModuleContext {
|
|
13
|
+
fileSystemProvider: (services: LangiumSharedCoreServices) => FileSystemProvider;
|
|
14
|
+
}
|
|
15
|
+
export declare class NoopFileSystemProvider implements FileSystemProvider {
|
|
16
|
+
scanProjectFiles(): Promise<FileSystemNode[]>;
|
|
17
|
+
readFile(): Promise<string>;
|
|
18
|
+
readDirectory(): Promise<FileSystemNode[]>;
|
|
19
|
+
}
|
|
20
|
+
export declare const NoopFileSystem: FileSystemModuleContext;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { noopFileSystemWatcher } from "./FileSystemWatcher.js";
|
|
2
|
+
export class NoopFileSystemProvider {
|
|
3
|
+
scanProjectFiles() {
|
|
4
|
+
return Promise.resolve([]);
|
|
5
|
+
}
|
|
6
|
+
readFile() {
|
|
7
|
+
throw new Error("No file system is available.");
|
|
8
|
+
}
|
|
9
|
+
readDirectory() {
|
|
10
|
+
return Promise.resolve([]);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const NoopFileSystem = {
|
|
14
|
+
fileSystemProvider: () => new NoopFileSystemProvider(),
|
|
15
|
+
...noopFileSystemWatcher
|
|
16
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NoopFileSystem } from './filesystem';
|
|
2
|
+
import { LikeC4FileSystem } from './filesystem/LikeC4FileSystem';
|
|
3
|
+
import { WithMCPServer } from './mcp/server/WithMCPServer';
|
|
2
4
|
import { type LikeC4Services, type LikeC4SharedServices } from './module';
|
|
3
5
|
export { getLspConnectionSink, logger as lspLogger } from './logger';
|
|
4
6
|
export type { DocumentParser, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from './model';
|
|
5
7
|
export type { LikeC4LanguageServices } from './LikeC4LanguageServices';
|
|
6
8
|
export { isLikeC4Builtin } from './likec4lib';
|
|
7
|
-
export {
|
|
9
|
+
export { createLanguageServices } from './module';
|
|
8
10
|
export type { LikeC4Services, LikeC4SharedServices } from './module';
|
|
9
11
|
export type { LikeC4Views } from './views';
|
|
10
|
-
export { LikeC4FileSystem };
|
|
11
|
-
|
|
12
|
+
export { LikeC4FileSystem, NoopFileSystem, WithMCPServer };
|
|
13
|
+
type StartLanguageServerOptions = {
|
|
14
|
+
/**
|
|
15
|
+
* Whether to enable the file system watcher.
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
enableWatcher?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether to enable the MCP server.
|
|
21
|
+
* @default 'sse'
|
|
22
|
+
*/
|
|
23
|
+
enableMCP?: false | 'sse' | 'stdio';
|
|
24
|
+
};
|
|
25
|
+
export declare function startLanguageServer(options?: StartLanguageServerOptions): {
|
|
12
26
|
shared: LikeC4SharedServices;
|
|
13
27
|
likec4: LikeC4Services;
|
|
14
28
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { configureLogger, getConsoleSink, getTextFormatter } from "@likec4/log";
|
|
2
|
+
import { defu } from "defu";
|
|
2
3
|
import { startLanguageServer as startLanguim } from "langium/lsp";
|
|
3
4
|
import { createConnection, ProposedFeatures } from "vscode-languageserver/node";
|
|
4
|
-
import {
|
|
5
|
+
import { NoopFileSystem } from "./filesystem/index.js";
|
|
6
|
+
import { LikeC4FileSystem } from "./filesystem/LikeC4FileSystem.js";
|
|
5
7
|
import { getTelemetrySink, logger } from "./logger.js";
|
|
6
|
-
import { WithMCPServer } from "./mcp/
|
|
7
|
-
import {
|
|
8
|
+
import { WithMCPServer } from "./mcp/server/WithMCPServer.js";
|
|
9
|
+
import { createLanguageServices } from "./module.js";
|
|
8
10
|
import { ConfigurableLayouter } from "./views/configurable-layouter.js";
|
|
9
11
|
export { getLspConnectionSink, logger as lspLogger } from "./logger.js";
|
|
10
12
|
export { isLikeC4Builtin } from "./likec4lib.js";
|
|
11
|
-
export {
|
|
12
|
-
export { LikeC4FileSystem };
|
|
13
|
-
export function startLanguageServer() {
|
|
13
|
+
export { createLanguageServices } from "./module.js";
|
|
14
|
+
export { LikeC4FileSystem, NoopFileSystem, WithMCPServer };
|
|
15
|
+
export function startLanguageServer(options) {
|
|
16
|
+
const opts = defu(options, {
|
|
17
|
+
enableWatcher: true,
|
|
18
|
+
enableMCP: "sse"
|
|
19
|
+
});
|
|
14
20
|
const connection = createConnection(ProposedFeatures.all);
|
|
15
21
|
configureLogger({
|
|
16
22
|
sinks: {
|
|
@@ -27,10 +33,17 @@ export function startLanguageServer() {
|
|
|
27
33
|
]
|
|
28
34
|
});
|
|
29
35
|
logger.info("Starting LikeC4 language server");
|
|
30
|
-
const services =
|
|
31
|
-
{
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
const services = createLanguageServices(
|
|
37
|
+
{
|
|
38
|
+
connection,
|
|
39
|
+
...LikeC4FileSystem(opts.enableWatcher),
|
|
40
|
+
...opts.enableMCP && WithMCPServer(opts.enableMCP)
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
likec4: {
|
|
44
|
+
...ConfigurableLayouter.likec4
|
|
45
|
+
}
|
|
46
|
+
}
|
|
34
47
|
);
|
|
35
48
|
startLanguim(services.shared);
|
|
36
49
|
return services;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ServerOptions } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
import type { LikeC4Services } from '
|
|
3
|
+
import type { LikeC4Services } from '../module';
|
|
4
4
|
export declare class LikeC4MCPServerFactory {
|
|
5
5
|
private services;
|
|
6
6
|
constructor(services: LikeC4Services);
|
|
@@ -0,0 +1,69 @@
|
|
|
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.js";
|
|
5
|
+
import { findRelationships } from "./tools/find-relationships.js";
|
|
6
|
+
import { listProjects } from "./tools/list-projects.js";
|
|
7
|
+
import { openView } from "./tools/open-view.js";
|
|
8
|
+
import { readDeployment } from "./tools/read-deployment.js";
|
|
9
|
+
import { readElement } from "./tools/read-element.js";
|
|
10
|
+
import { readProjectSummary } from "./tools/read-project-summary.js";
|
|
11
|
+
import { readView } from "./tools/read-view.js";
|
|
12
|
+
import { searchElement } from "./tools/search-element.js";
|
|
13
|
+
export class LikeC4MCPServerFactory {
|
|
14
|
+
constructor(services) {
|
|
15
|
+
this.services = services;
|
|
16
|
+
}
|
|
17
|
+
create(options) {
|
|
18
|
+
const isInEditor = this.services.shared.lsp.Connection !== void 0;
|
|
19
|
+
const mcp = new McpServer({
|
|
20
|
+
name: "LikeC4",
|
|
21
|
+
version: packageJson.version
|
|
22
|
+
}, {
|
|
23
|
+
instructions: `LikeC4 MCP \u2013 query and navigate LikeC4 models.
|
|
24
|
+
|
|
25
|
+
Conventions:
|
|
26
|
+
- All tools are read-only and idempotent.
|
|
27
|
+
- "project" is optional and defaults to "default".
|
|
28
|
+
|
|
29
|
+
Available tools:
|
|
30
|
+
- list-projects \u2014 List all LikeC4 projects in the workspace.
|
|
31
|
+
- read-project-summary \u2014 Project specification (element kinds, deployment node kinds, tags, metadata keys), all elements, deployment nodes and views. Input: { project? }.
|
|
32
|
+
- search-element \u2014 Search elements and deployment nodes across all projects by id/title/kind/shape/tags. Input: { search }.
|
|
33
|
+
- read-element \u2014 Full element details including relationships, includedInViews, deployedInstances, and sourceLocation. Input: { id, project? }.
|
|
34
|
+
- read-deployment \u2014 Details of a deployment node or deployed instance. Input: { id, project? }.
|
|
35
|
+
- read-view \u2014 Full view details (nodes/edges) and sourceLocation. Input: { viewId, project? }.
|
|
36
|
+
- find-relationships \u2014 Direct and indirect relationships between two elements in a project. Input: { element1, element2, project? }.
|
|
37
|
+
${isInEditor ? "- open-view \u2014 Opens the LikeC4 view panel in the editor. Triggers UI; at most one preview panel at a time. Input: { viewId, project? }." : ""}
|
|
38
|
+
|
|
39
|
+
Instructions:
|
|
40
|
+
- Identify the project first
|
|
41
|
+
- Use "search-element" to find elements by id/title/kind/shape/tags and select the project
|
|
42
|
+
- Use "read-project-summary" to find all elements and deployment nodes inside the project, what kinds, tags, metadata keys are available
|
|
43
|
+
- Use "list-projects" to list all available projects
|
|
44
|
+
- If resource returns "sourceLocation", provide link to this location in the editor
|
|
45
|
+
|
|
46
|
+
Docs: https://likec4.dev/llms-full.txt
|
|
47
|
+
`,
|
|
48
|
+
...options,
|
|
49
|
+
capabilities: {
|
|
50
|
+
tools: {},
|
|
51
|
+
...options?.capabilities
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
mcp.registerTool(...listProjects(this.services.likec4.LanguageServices));
|
|
55
|
+
mcp.registerTool(...readProjectSummary(this.services.likec4.LanguageServices));
|
|
56
|
+
mcp.registerTool(...readElement(this.services.likec4.LanguageServices));
|
|
57
|
+
mcp.registerTool(...readDeployment(this.services.likec4.LanguageServices));
|
|
58
|
+
mcp.registerTool(...readView(this.services.likec4.LanguageServices));
|
|
59
|
+
mcp.registerTool(...searchElement(this.services.likec4.LanguageServices));
|
|
60
|
+
mcp.registerTool(...findRelationships(this.services.likec4.LanguageServices));
|
|
61
|
+
if (isInEditor) {
|
|
62
|
+
mcp.registerTool(...openView(this.services.likec4.LanguageServices));
|
|
63
|
+
}
|
|
64
|
+
mcp.server.onerror = (err) => {
|
|
65
|
+
logger.error(loggable(err));
|
|
66
|
+
};
|
|
67
|
+
return mcp;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import type { ServerOptions } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
import type {
|
|
4
|
-
import type { LikeC4MCPServer, LikeC4MCPServerFactory } from './interfaces';
|
|
2
|
+
import type { LikeC4MCPServer } from './interfaces';
|
|
5
3
|
export declare class NoopLikeC4MCPServer implements LikeC4MCPServer {
|
|
4
|
+
get mcp(): McpServer;
|
|
6
5
|
get isStarted(): boolean;
|
|
7
6
|
get port(): number;
|
|
8
|
-
start(port: number): Promise<
|
|
9
|
-
stop(): Promise<
|
|
10
|
-
}
|
|
11
|
-
export declare class NoopLikeC4MCPServerFactory implements LikeC4MCPServerFactory {
|
|
12
|
-
private services;
|
|
13
|
-
constructor(services: LikeC4Services);
|
|
14
|
-
create(options?: ServerOptions): McpServer;
|
|
7
|
+
start(port: number): Promise<void>;
|
|
8
|
+
stop(): Promise<void>;
|
|
15
9
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export class NoopLikeC4MCPServer {
|
|
2
|
+
get mcp() {
|
|
3
|
+
throw new Error("NoopLikeC4MCPServer does not have a McpServer");
|
|
4
|
+
}
|
|
2
5
|
get isStarted() {
|
|
3
6
|
return false;
|
|
4
7
|
}
|
|
@@ -6,17 +9,9 @@ export class NoopLikeC4MCPServer {
|
|
|
6
9
|
return NaN;
|
|
7
10
|
}
|
|
8
11
|
start(port) {
|
|
9
|
-
return Promise.
|
|
12
|
+
return Promise.resolve();
|
|
10
13
|
}
|
|
11
14
|
stop() {
|
|
12
|
-
return Promise.
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
export class NoopLikeC4MCPServerFactory {
|
|
16
|
-
constructor(services) {
|
|
17
|
-
this.services = services;
|
|
18
|
-
}
|
|
19
|
-
create(options) {
|
|
20
|
-
throw new Error("NoopLikeC4MCPServerFactory - switch to implementation");
|
|
15
|
+
return Promise.resolve();
|
|
21
16
|
}
|
|
22
17
|
}
|
package/dist/mcp/interfaces.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type {
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { LikeC4Services } from '../module';
|
|
3
3
|
export interface LikeC4MCPServer {
|
|
4
|
+
readonly mcp: McpServer;
|
|
4
5
|
readonly isStarted: boolean;
|
|
5
6
|
readonly port: number;
|
|
6
|
-
start(port
|
|
7
|
+
start(port?: number): Promise<void>;
|
|
7
8
|
stop(): Promise<void>;
|
|
8
9
|
}
|
|
9
|
-
export interface
|
|
10
|
-
|
|
10
|
+
export interface LikeC4MCPServerModuleContext {
|
|
11
|
+
mcpServer: (services: LikeC4Services) => LikeC4MCPServer;
|
|
11
12
|
}
|
|
13
|
+
export declare const NoMCPServer: LikeC4MCPServerModuleContext;
|
package/dist/mcp/interfaces.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { AsyncDisposable } from 'langium';
|
|
3
|
+
import type { LikeC4Services } from '../../module';
|
|
4
|
+
import type { LikeC4MCPServer } from '../interfaces';
|
|
5
|
+
export declare class StdioLikeC4MCPServer implements LikeC4MCPServer, AsyncDisposable {
|
|
6
|
+
private services;
|
|
7
|
+
private transport;
|
|
8
|
+
private _mcp;
|
|
9
|
+
constructor(services: LikeC4Services);
|
|
10
|
+
get mcp(): McpServer;
|
|
11
|
+
get isStarted(): boolean;
|
|
12
|
+
get port(): number;
|
|
13
|
+
dispose(): Promise<void>;
|
|
14
|
+
start(): Promise<void>;
|
|
15
|
+
stop(): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
+
import { logger } from "../utils.js";
|
|
3
|
+
export class StdioLikeC4MCPServer {
|
|
4
|
+
constructor(services) {
|
|
5
|
+
this.services = services;
|
|
6
|
+
}
|
|
7
|
+
transport = void 0;
|
|
8
|
+
_mcp = void 0;
|
|
9
|
+
get mcp() {
|
|
10
|
+
if (!this._mcp) {
|
|
11
|
+
throw new Error("MCP server is not started");
|
|
12
|
+
}
|
|
13
|
+
return this._mcp;
|
|
14
|
+
}
|
|
15
|
+
get isStarted() {
|
|
16
|
+
return this.transport !== void 0;
|
|
17
|
+
}
|
|
18
|
+
get port() {
|
|
19
|
+
return NaN;
|
|
20
|
+
}
|
|
21
|
+
async dispose() {
|
|
22
|
+
await this.stop();
|
|
23
|
+
}
|
|
24
|
+
async start() {
|
|
25
|
+
if (this.transport) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
logger.info("Starting MCP stdio server");
|
|
29
|
+
this._mcp = this.services.mcp.ServerFactory.create();
|
|
30
|
+
this.transport = new StdioServerTransport();
|
|
31
|
+
await this._mcp.connect(this.transport);
|
|
32
|
+
logger.info("LikeC4 MCP Server running on stdio");
|
|
33
|
+
}
|
|
34
|
+
async stop() {
|
|
35
|
+
if (!this.transport) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
logger.info("Stopping MCP stdio server");
|
|
39
|
+
await this.transport.close();
|
|
40
|
+
this._mcp?.close();
|
|
41
|
+
this.transport = void 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
1
2
|
import type { AsyncDisposable } from 'langium';
|
|
2
3
|
import type { LikeC4Services } from '../../module';
|
|
3
4
|
import type { LikeC4MCPServer } from '../interfaces';
|
|
4
|
-
export declare class
|
|
5
|
+
export declare class StreamableLikeC4MCPServer implements LikeC4MCPServer, AsyncDisposable {
|
|
5
6
|
private services;
|
|
6
|
-
private transports;
|
|
7
7
|
private server;
|
|
8
8
|
private _port;
|
|
9
9
|
constructor(services: LikeC4Services);
|
|
10
|
+
get mcp(): McpServer;
|
|
10
11
|
get isStarted(): boolean;
|
|
11
12
|
get port(): number;
|
|
12
13
|
dispose(): Promise<void>;
|