@mlightcad/cad-mcp-server 0.0.0-stage → 1.7.8-preview.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.
@@ -0,0 +1,213 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { createServer } from 'node:http';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { launchHeadlessChromium } from './headlessGpu.js';
7
+ function packageRoot() {
8
+ return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
9
+ }
10
+ function runnerDistDir() {
11
+ return path.join(packageRoot(), 'dist-runner');
12
+ }
13
+ function isHttpUrl(value) {
14
+ return /^https?:\/\//i.test(value.trim());
15
+ }
16
+ function drawingNameFromUrl(urlString) {
17
+ try {
18
+ const pathname = new URL(urlString).pathname;
19
+ const base = path.basename(pathname);
20
+ if (base && path.extname(base)) {
21
+ return base;
22
+ }
23
+ }
24
+ catch {
25
+ // fall through
26
+ }
27
+ return 'drawing.dwg';
28
+ }
29
+ function contentTypeFor(filePath) {
30
+ const ext = path.extname(filePath).toLowerCase();
31
+ const types = {
32
+ '.html': 'text/html; charset=utf-8',
33
+ '.js': 'text/javascript; charset=utf-8',
34
+ '.css': 'text/css; charset=utf-8',
35
+ '.json': 'application/json',
36
+ '.wasm': 'application/wasm',
37
+ '.dwg': 'application/octet-stream',
38
+ '.dxf': 'application/octet-stream'
39
+ };
40
+ return types[ext] ?? 'application/octet-stream';
41
+ }
42
+ function startStaticServer(root) {
43
+ return new Promise((resolve, reject) => {
44
+ const mountedInputs = new Map();
45
+ let mountSeq = 0;
46
+ const server = createServer((req, res) => {
47
+ void handleRequest(req, res);
48
+ });
49
+ async function handleRequest(req, res) {
50
+ try {
51
+ const urlPath = decodeURIComponent((req.url ?? '/').split('?')[0] ?? '/');
52
+ if (urlPath.startsWith('/__mcp_input__/')) {
53
+ const absolute = mountedInputs.get(urlPath);
54
+ if (!absolute || !existsSync(absolute)) {
55
+ res.writeHead(404);
56
+ res.end();
57
+ return;
58
+ }
59
+ const body = await readFile(absolute);
60
+ res.setHeader('Content-Type', contentTypeFor(absolute));
61
+ res.setHeader('Content-Length', String(body.byteLength));
62
+ res.writeHead(200);
63
+ res.end(body);
64
+ return;
65
+ }
66
+ const relative = urlPath === '/' ? 'index.html' : urlPath.replace(/^\//, '');
67
+ const filePath = path.join(root, relative);
68
+ if (!filePath.startsWith(root)) {
69
+ res.writeHead(403);
70
+ res.end();
71
+ return;
72
+ }
73
+ if (!existsSync(filePath)) {
74
+ res.writeHead(404);
75
+ res.end();
76
+ return;
77
+ }
78
+ res.setHeader('Content-Type', contentTypeFor(filePath));
79
+ const body = await readFile(filePath);
80
+ res.writeHead(200);
81
+ res.end(body);
82
+ }
83
+ catch (error) {
84
+ res.writeHead(500);
85
+ res.end(String(error));
86
+ }
87
+ }
88
+ server.listen(0, '127.0.0.1', () => {
89
+ const address = server.address();
90
+ if (!address || typeof address === 'string') {
91
+ reject(new Error('Failed to start static server for MCP runner.'));
92
+ return;
93
+ }
94
+ const baseUrl = `http://127.0.0.1:${address.port}`;
95
+ resolve({
96
+ url: baseUrl,
97
+ mountInput: (absolutePath, _fileName) => {
98
+ const token = String(++mountSeq);
99
+ const urlPath = `/__mcp_input__/${token}`;
100
+ mountedInputs.set(urlPath, absolutePath);
101
+ return `${baseUrl}${urlPath}`;
102
+ },
103
+ close: () => new Promise((closeResolve, closeReject) => {
104
+ server.close(err => (err ? closeReject(err) : closeResolve()));
105
+ })
106
+ });
107
+ });
108
+ });
109
+ }
110
+ /**
111
+ * Long-lived headless Chromium session hosting cad-simple-viewer + agent-core.
112
+ *
113
+ * Started lazily on the first tool call and kept for the process lifetime so
114
+ * drawing state persists across MCP tool invocations.
115
+ */
116
+ export class CadMcpSession {
117
+ browser;
118
+ page;
119
+ server;
120
+ constructor(browser, page, server) {
121
+ this.browser = browser;
122
+ this.page = page;
123
+ this.server = server;
124
+ }
125
+ static instance;
126
+ /**
127
+ * Returns the shared session, creating it on first call.
128
+ */
129
+ static shared(options = {}) {
130
+ if (!this.instance) {
131
+ this.instance = this.create(options).catch(error => {
132
+ this.instance = undefined;
133
+ throw error;
134
+ });
135
+ }
136
+ return this.instance;
137
+ }
138
+ static async create(options = {}) {
139
+ const runnerDir = runnerDistDir();
140
+ if (!existsSync(path.join(runnerDir, 'index.html'))) {
141
+ throw new Error('MCP runner is not built. Run "pnpm --filter @mlightcad/cad-mcp-server build".');
142
+ }
143
+ const server = await startStaticServer(runnerDir);
144
+ const channel = process.env.PLAYWRIGHT_BROWSER_CHANNEL;
145
+ const gpu = await launchHeadlessChromium({
146
+ channel,
147
+ useGpu: options.useGpu
148
+ });
149
+ const browser = gpu.browser;
150
+ console.error(`[cad-mcp-server] webgl: ${gpu.renderer} (${gpu.backend})`);
151
+ const context = await browser.newContext();
152
+ const page = await context.newPage();
153
+ page.on('console', msg => {
154
+ const text = msg.text();
155
+ if (text.includes('GL Driver Message')) {
156
+ return;
157
+ }
158
+ if (text.startsWith('[cad-mcp-server]') ||
159
+ msg.type() === 'error' ||
160
+ msg.type() === 'warning') {
161
+ console.error(text);
162
+ }
163
+ });
164
+ page.on('pageerror', error => {
165
+ console.error('[cad-mcp-server] page error:', error.message);
166
+ });
167
+ await page.goto(`${server.url}/index.html`, { waitUntil: 'networkidle' });
168
+ await page.waitForFunction(() => typeof window.__cadMcp !==
169
+ 'undefined');
170
+ console.error('[cad-mcp-server] browser ready');
171
+ return new CadMcpSession(browser, page, server);
172
+ }
173
+ async openDrawing(input) {
174
+ let fileName = null;
175
+ let drawingUrl = null;
176
+ const pathArg = input.path?.trim();
177
+ if (pathArg) {
178
+ if (isHttpUrl(pathArg)) {
179
+ drawingUrl = pathArg;
180
+ fileName = drawingNameFromUrl(pathArg);
181
+ }
182
+ else {
183
+ const absolute = path.resolve(pathArg);
184
+ if (!existsSync(absolute)) {
185
+ throw new Error(`Drawing not found: ${absolute}`);
186
+ }
187
+ fileName = path.basename(absolute);
188
+ drawingUrl = this.server.mountInput(absolute, fileName);
189
+ }
190
+ }
191
+ const mode = input.mode ?? (pathArg ? 'read' : 'write');
192
+ return this.page.evaluate(async ({ fileName: name, drawingUrl: url, mode: openMode }) => {
193
+ const api = window.__cadMcp;
194
+ return api.openDrawing({
195
+ fileName: name,
196
+ drawingUrl: url,
197
+ mode: openMode,
198
+ startBlank: !url
199
+ });
200
+ }, { fileName, drawingUrl, mode });
201
+ }
202
+ async executeCadScript(input) {
203
+ return this.page.evaluate(async (args) => {
204
+ const api = window.__cadMcp;
205
+ return api.executeCadScript(args);
206
+ }, input);
207
+ }
208
+ async close() {
209
+ await this.browser.close().catch(() => undefined);
210
+ await this.server.close().catch(() => undefined);
211
+ }
212
+ }
213
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { ToolResult } from '@mlightcad/cad-agent-core';
2
+ /**
3
+ * MCP tool-result content block (text or image).
4
+ */
5
+ export type McpContentBlock = {
6
+ type: 'text';
7
+ text: string;
8
+ } | {
9
+ type: 'image';
10
+ data: string;
11
+ mimeType: string;
12
+ };
13
+ /**
14
+ * Converts a cad-agent-core {@link ToolResult} into MCP content blocks.
15
+ *
16
+ * Screenshot data URLs from `cad.view.capturePreview` become image parts;
17
+ * the JSON summary omits bulky data URLs.
18
+ */
19
+ export declare function toolResultToMcpContent(result: ToolResult): {
20
+ content: McpContentBlock[];
21
+ isError?: boolean;
22
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Converts a cad-agent-core {@link ToolResult} into MCP content blocks.
3
+ *
4
+ * Screenshot data URLs from `cad.view.capturePreview` become image parts;
5
+ * the JSON summary omits bulky data URLs.
6
+ */
7
+ export function toolResultToMcpContent(result) {
8
+ const { images, ...summary } = result;
9
+ const content = [
10
+ {
11
+ type: 'text',
12
+ text: JSON.stringify({
13
+ ...summary,
14
+ ...(images?.length
15
+ ? {
16
+ imageCount: images.length,
17
+ note: 'Screenshot(s) attached as image parts for visual review.'
18
+ }
19
+ : {})
20
+ })
21
+ }
22
+ ];
23
+ if (images?.length) {
24
+ for (const image of images) {
25
+ const data = image.dataUrl.includes(',')
26
+ ? image.dataUrl.slice(image.dataUrl.indexOf(',') + 1)
27
+ : image.dataUrl;
28
+ content.push({
29
+ type: 'image',
30
+ data,
31
+ mimeType: image.mediaType || 'image/png'
32
+ });
33
+ }
34
+ }
35
+ return {
36
+ content,
37
+ ...(result.success ? {} : { isError: true })
38
+ };
39
+ }
40
+ //# sourceMappingURL=toolResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolResult.js","sourceRoot":"","sources":["../src/toolResult.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAkB;IAIvD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAA;IACrC,MAAM,OAAO,GAAsB;QACjC;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,GAAG,OAAO;gBACV,GAAG,CAAC,MAAM,EAAE,MAAM;oBAChB,CAAC,CAAC;wBACE,UAAU,EAAE,MAAM,CAAC,MAAM;wBACzB,IAAI,EAAE,0DAA0D;qBACjE;oBACH,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;SACH;KACF,CAAA;IAED,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;gBACtC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACrD,CAAC,CAAC,KAAK,CAAC,OAAO,CAAA;YACjB,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,OAAO;gBACb,IAAI;gBACJ,QAAQ,EAAE,KAAK,CAAC,SAAS,IAAI,WAAW;aACzC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;KAC7C,CAAA;AACH,CAAC"}