@lineadraw/mcp 0.5.0 → 0.7.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/README.md +12 -0
- package/dist/editor.html +262 -272
- package/dist/server.js +8 -8
- package/dist/server.js.map +1 -1
- package/package.json +19 -19
package/dist/server.js
CHANGED
|
@@ -30,7 +30,7 @@ var DocumentRegistry = class {
|
|
|
30
30
|
/** Resolve a document by id, or the active one when omitted. */
|
|
31
31
|
get(id) {
|
|
32
32
|
const key = id ?? this.activeId;
|
|
33
|
-
if (!key) throw new Error("No document
|
|
33
|
+
if (!key) throw new Error("No document. Call linea_new_document first");
|
|
34
34
|
const entry = this.docs.get(key);
|
|
35
35
|
if (!entry) throw new Error(`Unknown document "${key}"`);
|
|
36
36
|
return { id: key, doc: entry.doc };
|
|
@@ -259,7 +259,7 @@ var coreLineaTools = [
|
|
|
259
259
|
{
|
|
260
260
|
name: "linea_set_dim_style",
|
|
261
261
|
title: "Set dimension style",
|
|
262
|
-
description: "Patch a document dimension style (default: the first): textHeight, textOffset, arrowType (filled|open|tick|dot|none), arrowSize, extensionType (long|short), extensionOffset, extensionOvershoot, precision, font (arial|osifont|jetbrains-mono|source-serif), widthFactor. NOTE: annotation scale is NOT a style key
|
|
262
|
+
description: "Patch a document dimension style (default: the first): textHeight, textOffset, arrowType (filled|open|tick|dot|none), arrowSize, extensionType (long|short), extensionOffset, extensionOvershoot, precision, font (arial|osifont|jetbrains-mono|source-serif), widthFactor. NOTE: annotation scale is NOT a style key: set the top-level `scale` field on each dimension object.",
|
|
263
263
|
inputSchema: {
|
|
264
264
|
patch: z.record(z.string(), z.unknown()),
|
|
265
265
|
styleId: z.string().optional(),
|
|
@@ -291,7 +291,7 @@ var coreLineaTools = [
|
|
|
291
291
|
{
|
|
292
292
|
name: "linea_query",
|
|
293
293
|
title: "Query objects",
|
|
294
|
-
description: "Filtered read over model-space objects
|
|
294
|
+
description: "Filtered read over model-space objects, or one paper layout's sheet objects (viewports, annotations) via `layout`. All filters AND: type, layer (name), color, lineType, content (text substring), bbox (intersects), inside (contained), near ({point, tol}), ids. `measure: true` adds bbox/length/area per object. Prefer this over linea_get_document; it returns compact data.",
|
|
295
295
|
inputSchema: {
|
|
296
296
|
ids: z.array(z.string()).optional(),
|
|
297
297
|
type: z.string().optional(),
|
|
@@ -331,7 +331,7 @@ var coreLineaTools = [
|
|
|
331
331
|
{
|
|
332
332
|
name: "linea_layer",
|
|
333
333
|
title: "Manage layers",
|
|
334
|
-
description: "add (name, props?) | update (layer, props
|
|
334
|
+
description: "add (name, props?) | update (layer, props; rename via props.name) | remove (layer; must be empty and not current) | set-current (layer). `layer` targets by name or id. Returns the resulting layer list.",
|
|
335
335
|
inputSchema: {
|
|
336
336
|
kind: z.enum(["add", "update", "remove", "set-current"]),
|
|
337
337
|
name: z.string().optional().describe("New layer name (kind: add)"),
|
|
@@ -361,7 +361,7 @@ var coreLineaTools = [
|
|
|
361
361
|
{
|
|
362
362
|
name: "linea_render",
|
|
363
363
|
title: "Render snapshot",
|
|
364
|
-
description: "Render model space (or a paper layout via `layout`) for visual verification. svg returns SVG markup as text; png returns an image (Node MCP server only
|
|
364
|
+
description: "Render model space (or a paper layout via `layout`) for visual verification. svg returns SVG markup as text; png returns an image (Node MCP server only; the in-browser editor supports svg).",
|
|
365
365
|
inputSchema: {
|
|
366
366
|
format: z.enum(["svg", "png"]).optional().describe("Default svg"),
|
|
367
367
|
layout: z.string().optional().describe("Layout name/id"),
|
|
@@ -370,7 +370,7 @@ var coreLineaTools = [
|
|
|
370
370
|
width: z.number().int().positive().optional().describe("png only, px"),
|
|
371
371
|
background: z.string().optional().describe("png only, e.g. #ffffff"),
|
|
372
372
|
palette: z.enum(["color", "grayscale", "monochrome"]).optional().describe(
|
|
373
|
-
"Print-style color remap
|
|
373
|
+
"Print-style color remap: use monochrome with a white background (light layer colors are authored for the dark canvas)"
|
|
374
374
|
),
|
|
375
375
|
documentId
|
|
376
376
|
},
|
|
@@ -380,7 +380,7 @@ var coreLineaTools = [
|
|
|
380
380
|
if (format === "png") {
|
|
381
381
|
if (!s.renderPng)
|
|
382
382
|
throw new Error(
|
|
383
|
-
'png rendering is only available on the Node MCP server
|
|
383
|
+
'png rendering is only available on the Node MCP server; use format: "svg"'
|
|
384
384
|
);
|
|
385
385
|
const bytes = await s.renderPng(opts);
|
|
386
386
|
return {
|
|
@@ -422,7 +422,7 @@ var coreLineaTools = [
|
|
|
422
422
|
{
|
|
423
423
|
name: "linea_summary",
|
|
424
424
|
title: "Document summary",
|
|
425
|
-
description: "Counts by type/layer, bbox, layers, layouts
|
|
425
|
+
description: "Counts by type/layer, bbox, layers, layouts: the cheap 'what is in this document' observation.",
|
|
426
426
|
inputSchema: { documentId },
|
|
427
427
|
run(ctx, args) {
|
|
428
428
|
const s = ctx.get(args.documentId);
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/documents.ts","../src/tools.ts","../../mcp-tools/src/tools.ts"],"sourcesContent":["// @lineadraw/mcp — MCP server exposing Linea document tools + the in-chat viewer\n// (MCP Apps extension). Two transports:\n//\n// stdio — for hosts that spawn the server as a subprocess (Claude Desktop):\n//\n// { \"command\": \"node\", \"args\": [\"<abs path>/dist/server.js\", \"--stdio\"] }\n//\n// Streamable HTTP (default) — Claude's web connectors require an https URL;\n// either tunnel plain HTTP (`npx cloudflared tunnel --url http://localhost:3001`)\n// or serve TLS locally with a mkcert certificate:\n//\n// mkcert -install && mkcert localhost\n// TLS_CERT=./localhost.pem TLS_KEY=./localhost-key.pem npm run serve\n//\n// and add https://localhost:3001/mcp as the custom connector.\n\nimport { readFileSync } from \"node:fs\";\nimport http, { type IncomingMessage, type ServerResponse } from \"node:http\";\nimport https from \"node:https\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { DocumentRegistry } from \"./documents.js\";\nimport { registerLineaTools } from \"./tools.js\";\n\nconst PORT = Number(process.env.PORT ?? 3001);\n\n// ONE registry for the process: every MCP session shares the open documents,\n// so a reconnecting client keeps its work.\nconst registry = new DocumentRegistry();\n\nconst buildServer = (): McpServer => {\n const server = new McpServer({ name: \"Lineadraw CAD\", version: \"0.1.0\" });\n registerLineaTools(server, registry);\n return server;\n};\n\nfunction startHttpServer() {\n const handle = async (req: IncomingMessage, res: ServerResponse) => {\n const path = (req.url ?? \"/\").split(\"?\")[0];\n // Log every request — when a connector fails to attach, an EMPTY log tells\n // you the client never reached this server at all (e.g. the check runs from\n // Anthropic infrastructure, which cannot see localhost — use a tunnel).\n console.log(`${new Date().toISOString()} ${req.method} ${path}`);\n\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET,POST,DELETE,OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n if (req.method === \"OPTIONS\") {\n res.writeHead(204).end();\n return;\n }\n\n // Route ALL methods through the transport: clients probe with GET (SSE\n // stream) and DELETE (session teardown) too, and the transport answers\n // those correctly for a stateless server — a bare 404 would read as\n // \"not an MCP server\". Served at \"/\" as well as \"/mcp\": Claude probes the\n // URL exactly as entered, and a bare origin should still work.\n if (path !== \"/\" && path !== \"/mcp\") {\n res.writeHead(404).end();\n return;\n }\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n });\n res.on(\"close\", () => transport.close());\n await buildServer().connect(transport);\n await transport.handleRequest(req, res);\n };\n\n const listener = (req: IncomingMessage, res: ServerResponse) => {\n void handle(req, res).catch((e) => {\n console.error(e);\n if (!res.headersSent) res.writeHead(500);\n res.end();\n });\n };\n\n const { TLS_CERT, TLS_KEY } = process.env;\n const tls = Boolean(TLS_CERT && TLS_KEY);\n const server = tls\n ? https.createServer(\n { cert: readFileSync(TLS_CERT!), key: readFileSync(TLS_KEY!) },\n listener,\n )\n : http.createServer(listener);\n server.listen(PORT, () => {\n console.log(\n tls\n ? `Linea MCP server on https://localhost:${PORT}/mcp`\n : `Linea MCP server on http://localhost:${PORT}/mcp (set TLS_CERT/TLS_KEY for https)`,\n );\n });\n}\n\n// stdio mode: stdout carries the JSON-RPC stream, so nothing else may be\n// written to it — log to stderr only.\nif (process.argv.includes(\"--stdio\")) {\n await buildServer().connect(new StdioServerTransport());\n console.error(\"Linea MCP server on stdio\");\n} else {\n startHttpServer();\n}\n","// In-process document registry: one MCP server session holds live Drawing\n// instances keyed by the document's own id (uuid stored IN the file, so\n// re-opening the same file targets the same entry). Most tools default to\n// the ACTIVE document — the last one created/opened — so single-document\n// conversations never pass ids around.\n\nimport { Drawing, newDrawing, openDrawing, drawingFromJson } from \"@lineadraw/sdk\";\n\nexport class DocumentRegistry {\n private docs = new Map<string, { doc: Drawing; revision: number }>();\n private activeId: string | null = null;\n\n create(name?: string): { id: string; doc: Drawing } {\n // Name must go through newDrawing: `doc.document` is a detached-clone\n // getter, so assigning `.name` on it mutates a throwaway copy.\n const doc = newDrawing(name);\n const id = doc.document.id;\n this.docs.set(id, { doc, revision: 0 });\n this.activeId = id;\n return { id, doc };\n }\n\n async open(path: string): Promise<{ id: string; doc: Drawing }> {\n const doc = await openDrawing(path);\n const id = doc.document.id;\n this.docs.set(id, { doc, revision: 0 });\n this.activeId = id;\n return { id, doc };\n }\n\n /** Resolve a document by id, or the active one when omitted. */\n get(id?: string): { id: string; doc: Drawing } {\n const key = id ?? this.activeId;\n if (!key) throw new Error(\"No document — call linea_new_document first\");\n const entry = this.docs.get(key);\n if (!entry) throw new Error(`Unknown document \"${key}\"`);\n return { id: key, doc: entry.doc };\n }\n\n /**\n * Replace a document's full state (validated + migrated) — how in-chat\n * editor edits land. The id must match; conversation undo history resets.\n */\n replace(id: string, raw: unknown): { doc: Drawing; revision: number } {\n const entry = this.docs.get(id);\n if (!entry) throw new Error(`Unknown document \"${id}\"`);\n const doc = drawingFromJson(JSON.stringify(raw));\n if (doc.document.id !== id)\n throw new Error(\n `Document id mismatch: payload has \"${doc.document.id}\", expected \"${id}\"`,\n );\n entry.doc = doc;\n return { doc, revision: this.bump(id) };\n }\n\n /** Mark a document changed; the viewer compares revisions to refresh. */\n bump(id: string): number {\n const entry = this.docs.get(id);\n if (!entry) return 0;\n return ++entry.revision;\n }\n\n revision(id: string): number {\n return this.docs.get(id)?.revision ?? 0;\n }\n}\n","// Tool layer: the shared linea_* catalog (@lineadraw/mcp-tools) adapted onto\n// @lineadraw/sdk's Drawing, plus the Node-only tools (disk I/O, the MCP App).\n// Angles cross the tool boundary in DEGREES (handled by the shared handlers);\n// object payloads are validated by the SDK's zod schemas.\n\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n registerAppTool,\n registerAppResource,\n RESOURCE_MIME_TYPE,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport type { Drawing } from \"@lineadraw/sdk\";\nimport {\n coreLineaTools,\n documentId,\n runTool,\n toolError,\n toolResult,\n type DocumentSession,\n type ToolContext,\n} from \"@lineadraw/mcp-tools\";\nimport type { DocumentRegistry } from \"./documents.js\";\n\nexport const EDITOR_RESOURCE_URI = \"ui://linea/editor.html\";\n\n/** The shared catalog's session, backed by an SDK Drawing in the registry.\n * Most members are the Drawing method bound 1:1; only the ones that adapt\n * semantics (revision bookkeeping, remove count, ids filter, …) add a body. */\nconst drawingSession = (\n registry: DocumentRegistry,\n id: string,\n doc: Drawing,\n): DocumentSession => ({\n id,\n revision: () => registry.revision(id),\n bump: () => registry.bump(id),\n add: (objects, opts) =>\n doc.add(objects as Parameters<Drawing[\"add\"]>[0], { layout: opts?.layout }),\n update: (entries) => doc.update(entries),\n remove: (ids) => {\n const removed = ids.filter((oid) => doc.getObject(oid) !== undefined);\n doc.remove(ids);\n return removed.length;\n },\n query: (filter) => {\n const { ids, ...rest } = filter;\n let objects = doc.query(rest as Parameters<Drawing[\"query\"]>[0]);\n if (ids) {\n const wanted = new Set(ids);\n objects = objects.filter((o) => wanted.has(o.id));\n }\n return objects as unknown as Record<string, unknown>[];\n },\n measure: (oid) => ({\n bbox: doc.bboxOf([oid]),\n length: doc.length(oid),\n area: doc.area(oid),\n }),\n listLayers: () => {\n const current = doc.document.currentLayerId;\n return doc.layers.map((l) => ({ ...l, current: l.id === current }));\n },\n addLayer: (props) => doc.addLayer(props as Parameters<Drawing[\"addLayer\"]>[0]),\n updateLayer: doc.updateLayer.bind(doc),\n removeLayer: doc.removeLayer.bind(doc),\n setCurrentLayer: doc.setCurrentLayer.bind(doc),\n renderSvg: doc.toSvg.bind(doc),\n renderPng: doc.toPng.bind(doc),\n undo: doc.undo.bind(doc),\n redo: doc.redo.bind(doc),\n move: doc.move.bind(doc),\n rotate: doc.rotate.bind(doc),\n scale: doc.scale.bind(doc),\n mirror: doc.mirror.bind(doc),\n copy: doc.copy.bind(doc),\n array: doc.array.bind(doc),\n createLayout: (name, opts) =>\n doc.createLayout(name, {\n sheet: opts.sheet,\n orientation: opts.orientation,\n viewport: opts.scale !== undefined ? { scale: opts.scale } : undefined,\n }),\n updateLayout: doc.updateLayoutMeta.bind(doc),\n removeLayout: doc.removeLayout.bind(doc),\n setDimStyle: (patch, styleId) =>\n doc.setDimStyle(patch as Parameters<Drawing[\"setDimStyle\"]>[0], styleId),\n setTextStyle: (patch, styleId) =>\n doc.setTextStyle(patch as Parameters<Drawing[\"setTextStyle\"]>[0], styleId),\n summary: () => doc.summary() as unknown as Record<string, unknown>,\n getDocument: () => doc.document,\n replace: (raw) => registry.replace(id, raw).revision,\n});\n\nexport function registerLineaTools(\n server: McpServer,\n registry: DocumentRegistry,\n opts: { editorHtml?: () => Promise<string> } = {},\n): void {\n const ctx: ToolContext = {\n get(idArg?: string) {\n const { id, doc } = registry.get(idArg);\n return drawingSession(registry, id, doc);\n },\n };\n\n // The shared catalog (add/update/remove/transform/query/layers/render/\n // undo/summary/get/replace). runTool's results are valid CallToolResults\n // at runtime; the cast bridges its looser RawToolResult content typing\n // (needed for image content) to the SDK's exact union.\n for (const def of coreLineaTools) {\n server.registerTool(\n def.name,\n {\n title: def.title,\n description: def.description,\n inputSchema: def.inputSchema,\n },\n async (args: unknown) =>\n (await runTool(def, ctx, args)) as CallToolResult,\n );\n }\n\n // --- Node-only tools: registry lifecycle + disk I/O -----------------------\n\n const run = <A>(fn: (args: A) => unknown) => {\n return async (args: A) => {\n try {\n return toolResult(await fn(args));\n } catch (e) {\n return toolError(e);\n }\n };\n };\n\n server.registerTool(\n \"linea_new_document\",\n {\n title: \"New Linea document\",\n description:\n \"Create a fresh CAD document (mm, Y-up) and make it active. \" +\n \"Call linea_show_document afterwards to display it in chat.\",\n inputSchema: { name: z.string().optional() },\n },\n run(({ name }: { name?: string }) => {\n const { id, doc } = registry.create(name);\n return { documentId: id, summary: doc.summary() };\n }),\n );\n\n server.registerTool(\n \"linea_open_document\",\n {\n title: \"Open .linea file\",\n description:\n \"Open a .linea file (or legacy .lineadraw) from disk and make it active.\",\n inputSchema: { path: z.string() },\n },\n run(async ({ path: p }: { path: string }) => {\n const { id, doc } = await registry.open(p);\n return { documentId: id, migration: doc.migration, summary: doc.summary() };\n }),\n );\n\n server.registerTool(\n \"linea_save_document\",\n {\n title: \"Save .linea file\",\n description: \"Save the document to disk as .linea JSON.\",\n inputSchema: { path: z.string(), documentId },\n },\n run(async ({ path: p, documentId: idArg }: { path: string; documentId?: string }) => {\n const { doc } = registry.get(idArg);\n await doc.save(p);\n return { saved: p };\n }),\n );\n\n server.registerTool(\n \"linea_export\",\n {\n title: \"Export document\",\n description: \"Write the document to disk as svg | png | pdf | dxf | dwg.\",\n inputSchema: {\n format: z.enum([\"svg\", \"png\", \"pdf\", \"dxf\", \"dwg\"]),\n path: z.string(),\n layout: z.string().optional().describe(\"Render a layout instead of model space (svg/png)\"),\n documentId,\n },\n },\n run(async ({ format, path: p, layout, documentId: idArg }: {\n format: \"svg\" | \"png\" | \"pdf\" | \"dxf\" | \"dwg\";\n path: string;\n layout?: string;\n documentId?: string;\n }) => {\n const { doc } = registry.get(idArg);\n if (format === \"svg\") await doc.exportSvg(p, { layout });\n else if (format === \"png\") await doc.exportPng(p, { layout });\n else if (format === \"pdf\") await doc.exportPdf(p);\n else if (format === \"dwg\") await doc.exportDwg(p);\n else await doc.exportDxf(p);\n return { exported: p };\n }),\n );\n\n // --- the MCP App: the full editor, in chat ---------------------------------\n\n registerAppTool(\n server,\n \"linea_show_document\",\n {\n title: \"Show Linea document\",\n description:\n \"Open the document in the FULL interactive Linea editor INSIDE the \" +\n \"chat: the user can view, pan/zoom, draw, snap, dimension, and edit; \" +\n \"their changes flow back into the document. Call this after creating \" +\n \"or meaningfully changing a document, or whenever the user wants to \" +\n \"see or edit it.\",\n inputSchema: { documentId },\n _meta: { ui: { resourceUri: EDITOR_RESOURCE_URI } },\n },\n (async ({ documentId: idArg }: { documentId?: string }) => {\n try {\n const { id, doc } = registry.get(idArg);\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Showing \"${doc.document.name}\" in the in-chat editor (${doc.objects.length} model objects)`,\n },\n ],\n structuredContent: {\n documentId: id,\n revision: registry.revision(id),\n document: doc.document,\n } as unknown as Record<string, unknown>,\n };\n } catch (e) {\n return toolError(e);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n }) as any,\n );\n\n registerAppResource(\n server,\n \"Linea editor\",\n EDITOR_RESOURCE_URI,\n { mimeType: RESOURCE_MIME_TYPE },\n async () => ({\n contents: [\n {\n uri: EDITOR_RESOURCE_URI,\n mimeType: RESOURCE_MIME_TYPE,\n text: await (opts.editorHtml ??\n (async () => {\n const here = path.dirname(fileURLToPath(import.meta.url));\n // Bundled server: editor.html sits next to dist/server.js.\n // Dev (tsx src/server.ts): it lives in the sibling dist/.\n return readFile(path.join(here, \"editor.html\"), \"utf-8\").catch(\n () =>\n readFile(path.join(here, \"..\", \"dist\", \"editor.html\"), \"utf-8\"),\n );\n }))(),\n },\n ],\n }),\n );\n}\n","// The shared linea_* tool catalog: one definition per tool — name, schema,\n// and a handler written against DocumentSession — consumed verbatim by the\n// Node MCP server (@lineadraw/mcp, zod shapes) and the in-browser WebMCP layer\n// (@lineadraw/editor, JSON Schema via toolJsonSchema). Angles cross this\n// boundary in DEGREES (agent ergonomics); tool-arg points are [x, y] tuples\n// (see `point` below); points INSIDE object bodies also accept {x, y}.\n\nimport { z } from \"zod\";\nimport type {\n PointInput,\n QueryFilter,\n RenderPngOptions,\n ToolContext,\n} from \"./session\";\n\nconst DEG2RAD = Math.PI / 180;\n\nconst box = z\n .object({\n minX: z.number(),\n minY: z.number(),\n maxX: z.number(),\n maxY: z.number(),\n })\n .describe(\"An axis-aligned box in world mm\");\n\n// Deliberately tuple-only, NOT union([tuple, {x,y}]): a bare-anyOf property\n// has no top-level `type`, and schema-rebuilding bridges (the WebMCP local\n// relay among them) degrade such properties to untyped {} — hosts then\n// string-encode the value and every call fails validation. A tuple keeps\n// `type: \"array\"` at the top level everywhere. ({x, y} still parses fine in\n// OBJECT bodies — model schemas accept both; this is only the tool-arg form.)\nconst point = z\n .tuple([z.number(), z.number()])\n .describe(\"A world point in mm: [x, y]\");\n\nconst looseObject = z\n .record(z.string(), z.unknown())\n .describe(\n 'A Linea model object, e.g. {\"type\":\"line\",\"a\":[0,0],\"b\":[100,0]}. ' +\n \"Types: line, point (p; paints as a dot sized by lineWidth), \" +\n \"polyline (points with bulge, closed), circle, arc, \" +\n \"ellipse, hatch, text, dimension, block. Optional layer (name), \" +\n \"color (#rrggbb), lineType.\",\n );\n\nexport const documentId = z\n .string()\n .optional()\n .describe(\"Document id; omit for the active document\");\n\nexport interface LineaToolDef {\n name: string;\n title: string;\n description: string;\n /** Zod raw shape — the MCP SDK consumes it verbatim; browser adapters\n * convert via toolJsonSchema and validate via toolArgs. */\n inputSchema: z.ZodRawShape;\n run(\n ctx: ToolContext,\n args: Record<string, unknown>,\n ): unknown | Promise<unknown>;\n}\n\n/** Success payload in MCP content shape (text + structuredContent). */\nexport const toolResult = (data: unknown) => ({\n content: [{ type: \"text\" as const, text: JSON.stringify(data) }],\n structuredContent: data as Record<string, unknown>,\n});\n\n/** A handler result that already IS a CallToolResult (e.g. image content) —\n * runTool passes it through instead of JSON-wrapping it. */\nexport type RawToolResult = {\n content: ({ type: string } & Record<string, unknown>)[];\n isError?: boolean;\n structuredContent?: Record<string, unknown>;\n};\n\nconst isRawToolResult = (v: unknown): v is RawToolResult =>\n typeof v === \"object\" &&\n v !== null &&\n Array.isArray((v as { content?: unknown }).content);\n\n/** Error payload in MCP content shape. */\nexport const toolError = (e: unknown) => ({\n content: [\n { type: \"text\" as const, text: String(e instanceof Error ? e.message : e) },\n ],\n isError: true as const,\n});\n\n/** Parse args against the tool's schema, run it, wrap result/error. */\nexport const runTool = async (\n def: LineaToolDef,\n ctx: ToolContext,\n args: unknown,\n): Promise<\n ReturnType<typeof toolResult> | ReturnType<typeof toolError> | RawToolResult\n> => {\n try {\n const parsed = z.object(def.inputSchema).parse(args ?? {});\n const out = await def.run(ctx, parsed);\n return isRawToolResult(out) ? out : toolResult(out);\n } catch (e) {\n return toolError(e);\n }\n};\n\n/** The tool's input schema as plain JSON Schema (WebMCP registration). */\nexport const toolJsonSchema = (def: LineaToolDef): Record<string, unknown> =>\n z.toJSONSchema(z.object(def.inputSchema), { io: \"input\" }) as Record<\n string,\n unknown\n >;\n\ntype TransformArgs = {\n kind: \"move\" | \"rotate\" | \"scale\" | \"mirror\" | \"copy\" | \"array\";\n ids: string[];\n delta?: PointInput;\n angleDeg?: number;\n factor?: number;\n center?: PointInput;\n axisA?: PointInput;\n axisB?: PointInput;\n count?: number;\n documentId?: string;\n};\n\n/**\n * The environment-neutral tools — everything that only needs a document\n * session. Node-only tools (new/open/save/export, the MCP App) live in\n * @lineadraw/mcp; browser-only tools (selection, view, spaces) in @lineadraw/editor.\n */\nexport const coreLineaTools: LineaToolDef[] = [\n {\n name: \"linea_add_objects\",\n title: \"Add objects\",\n description:\n \"Add objects to model space (or a paper layout via `layout`). \" +\n \"Returns the created ids.\",\n inputSchema: {\n objects: z.array(looseObject).min(1),\n layout: z\n .string()\n .optional()\n .describe(\"Layout name/id for sheet annotations\"),\n documentId,\n },\n run(ctx, args) {\n const { objects, layout, documentId: idArg } = args as {\n objects: Record<string, unknown>[];\n layout?: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n const ids = s.add(objects, { layout });\n return { ids, revision: s.bump() };\n },\n },\n {\n name: \"linea_update_objects\",\n title: \"Update objects\",\n description:\n \"Patch objects by id: entries are {id, ...fieldsToChange}. One undo step.\",\n inputSchema: {\n entries: z.array(z.record(z.string(), z.unknown())).min(1),\n documentId,\n },\n run(ctx, args) {\n const { entries, documentId: idArg } = args as {\n entries: Record<string, unknown>[];\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.update(entries as ({ id: string } & Record<string, unknown>)[]);\n return { updated: entries.length, revision: s.bump() };\n },\n },\n {\n name: \"linea_remove_objects\",\n title: \"Remove objects\",\n description:\n \"Delete objects by id. Unknown ids are skipped; `removed` reports how \" +\n \"many objects were actually deleted.\",\n inputSchema: { ids: z.array(z.string()).min(1), documentId },\n run(ctx, args) {\n const { ids, documentId: idArg } = args as {\n ids: string[];\n documentId?: string;\n };\n const s = ctx.get(idArg);\n const removed = s.remove(ids);\n return { removed, revision: s.bump() };\n },\n },\n {\n name: \"linea_transform\",\n title: \"Transform objects\",\n description:\n \"move (delta) | rotate (angleDeg, center?) | scale (factor, center?) | \" +\n \"mirror (axisA, axisB) | copy (delta → new ids) | array (count TOTAL, delta → new ids). \" +\n \"rotate/scale default their center to the selection bbox center.\",\n inputSchema: {\n kind: z.enum([\"move\", \"rotate\", \"scale\", \"mirror\", \"copy\", \"array\"]),\n ids: z.array(z.string()).min(1),\n delta: point.optional(),\n angleDeg: z.number().optional(),\n factor: z.number().optional(),\n center: point.optional(),\n axisA: point.optional(),\n axisB: point.optional(),\n count: z.number().int().optional(),\n documentId,\n },\n run(ctx, args) {\n const a = args as TransformArgs;\n const s = ctx.get(a.documentId);\n const need = <T>(v: T | undefined, name: string): T => {\n if (v === undefined) throw new Error(`${a.kind} requires \"${name}\"`);\n return v;\n };\n let created: string[] | undefined;\n switch (a.kind) {\n case \"move\":\n s.move(a.ids, need(a.delta, \"delta\"));\n break;\n case \"rotate\":\n s.rotate(a.ids, need(a.angleDeg, \"angleDeg\") * DEG2RAD, a.center);\n break;\n case \"scale\":\n s.scale(a.ids, need(a.factor, \"factor\"), a.center);\n break;\n case \"mirror\":\n s.mirror(a.ids, need(a.axisA, \"axisA\"), need(a.axisB, \"axisB\"));\n break;\n case \"copy\":\n created = s.copy(a.ids, need(a.delta, \"delta\"));\n break;\n case \"array\":\n created = s.array(a.ids, need(a.count, \"count\"), need(a.delta, \"delta\"));\n break;\n }\n return { ...(created ? { ids: created } : {}), revision: s.bump() };\n },\n },\n {\n name: \"linea_create_layout\",\n title: \"Create paper layout\",\n description:\n \"Add a paper layout (default: A3 landscape, one viewport fitted to \" +\n 'the model extents). scale accepts \"1:50\" strings.',\n inputSchema: {\n name: z.string(),\n // Named size + optional custom mm — two typed params instead of a\n // union so every property keeps a top-level JSON-schema `type`\n // (see `point` for why bare anyOf properties are relay-hostile).\n sheet: z.enum([\"A4\", \"A3\", \"A2\", \"A1\", \"A0\"]).optional(),\n sheetSize: z\n .object({ width: z.number(), height: z.number() })\n .optional()\n .describe(\"Custom sheet size in mm (overrides `sheet`)\"),\n orientation: z.enum([\"portrait\", \"landscape\"]).optional(),\n scale: z.string().optional().describe('Viewport scale, e.g. \"1:50\"'),\n documentId,\n },\n run(ctx, args) {\n const { name, sheet, sheetSize, orientation, scale, documentId: idArg } =\n args as {\n name: string;\n sheet?: \"A4\" | \"A3\" | \"A2\" | \"A1\" | \"A0\";\n sheetSize?: { width: number; height: number };\n orientation?: \"portrait\" | \"landscape\";\n scale?: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n const layoutId = s.createLayout(name, {\n sheet: sheetSize ?? sheet,\n orientation,\n scale,\n });\n return { layoutId, revision: s.bump() };\n },\n },\n {\n name: \"linea_update_layout\",\n title: \"Update layout\",\n description:\n \"Patch a paper layout's name, sheet size (mm), or print palette \" +\n '(printPalette \"monochrome\" prints/renders everything black).',\n inputSchema: {\n layout: z.string().describe(\"Layout name/id\"),\n name: z.string().optional().describe(\"New layout name\"),\n sheetSize: z\n .object({ width: z.number(), height: z.number() })\n .optional()\n .describe(\"New sheet size in mm\"),\n printPalette: z.enum([\"color\", \"grayscale\", \"monochrome\"]).optional(),\n documentId,\n },\n run(ctx, args) {\n const { layout, name, sheetSize, printPalette, documentId: idArg } =\n args as {\n layout: string;\n name?: string;\n sheetSize?: { width: number; height: number };\n printPalette?: \"color\" | \"grayscale\" | \"monochrome\";\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.updateLayout(layout, { name, sheet: sheetSize, printPalette });\n return { revision: s.bump() };\n },\n },\n {\n name: \"linea_remove_layout\",\n title: \"Remove layout\",\n description: \"Delete a paper layout (and its sheet objects) by name or id.\",\n inputSchema: {\n layout: z.string().describe(\"Layout name/id\"),\n documentId,\n },\n run(ctx, args) {\n const { layout, documentId: idArg } = args as {\n layout: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.removeLayout(layout);\n return { revision: s.bump() };\n },\n },\n {\n name: \"linea_set_dim_style\",\n title: \"Set dimension style\",\n description:\n \"Patch a document dimension style (default: the first): textHeight, \" +\n \"textOffset, arrowType (filled|open|tick|dot|none), arrowSize, \" +\n \"extensionType (long|short), extensionOffset, extensionOvershoot, \" +\n \"precision, font (arial|osifont|jetbrains-mono|source-serif), \" +\n \"widthFactor. NOTE: annotation scale is NOT a style \" +\n \"key — set the top-level `scale` field on each dimension object.\",\n inputSchema: {\n patch: z.record(z.string(), z.unknown()),\n styleId: z.string().optional(),\n documentId,\n },\n run(ctx, args) {\n const { patch, styleId, documentId: idArg } = args as {\n patch: Record<string, unknown>;\n styleId?: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.setDimStyle(patch, styleId);\n return { revision: s.bump() };\n },\n },\n {\n name: \"linea_set_text_style\",\n title: \"Set text style\",\n description:\n \"Patch a document text style (default: the first): font \" +\n \"(arial|osifont|jetbrains-mono|source-serif), widthFactor, \" +\n \"textHeight (default height for new text), arrowType, arrowSize \" +\n \"(leader arrows). Per-object styleOverride still wins over the style.\",\n inputSchema: {\n patch: z.record(z.string(), z.unknown()),\n styleId: z.string().optional(),\n documentId,\n },\n run(ctx, args) {\n const { patch, styleId, documentId: idArg } = args as {\n patch: Record<string, unknown>;\n styleId?: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.setTextStyle(patch, styleId);\n return { revision: s.bump() };\n },\n },\n {\n name: \"linea_query\",\n title: \"Query objects\",\n description:\n \"Filtered read over model-space objects — or one paper layout's sheet \" +\n \"objects (viewports, annotations) via `layout` — all filters AND: \" +\n \"type, layer (name), color, lineType, content (text substring), bbox \" +\n \"(intersects), inside (contained), near ({point, tol}), ids. \" +\n \"`measure: true` adds bbox/length/area per object. Prefer this over \" +\n \"linea_get_document — it returns compact data.\",\n inputSchema: {\n ids: z.array(z.string()).optional(),\n type: z.string().optional(),\n layer: z.string().optional(),\n color: z.string().optional(),\n lineType: z.string().optional(),\n content: z.string().optional(),\n bbox: box.optional(),\n inside: box.optional(),\n near: z.object({ point, tol: z.number().positive() }).optional(),\n layout: z\n .string()\n .optional()\n .describe(\"Search this layout's sheet objects (name/id) instead of model space\"),\n measure: z.boolean().optional(),\n limit: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Max objects returned (default 100)\"),\n documentId,\n },\n run(ctx, args) {\n const { measure, limit, documentId: idArg, ...filter } = args as {\n measure?: boolean;\n limit?: number;\n documentId?: string;\n } & QueryFilter;\n const s = ctx.get(idArg);\n const all = s.query(filter);\n const cap = limit ?? 100;\n const objects = all.slice(0, cap).map((o) =>\n measure ? { ...o, measure: s.measure(String(o.id)) } : o,\n );\n return { total: all.length, returned: objects.length, objects };\n },\n },\n {\n name: \"linea_list_layers\",\n title: \"List layers\",\n description:\n \"All layers with full metadata (color, hidden, locked, …) and which \" +\n \"one is current (the default for new objects).\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n return { layers: s.listLayers() };\n },\n },\n {\n name: \"linea_layer\",\n title: \"Manage layers\",\n description:\n \"add (name, props?) | update (layer, props — rename via props.name) | \" +\n \"remove (layer; must be empty and not current) | set-current (layer). \" +\n \"`layer` targets by name or id. Returns the resulting layer list.\",\n inputSchema: {\n kind: z.enum([\"add\", \"update\", \"remove\", \"set-current\"]),\n name: z.string().optional().describe(\"New layer name (kind: add)\"),\n layer: z.string().optional().describe(\"Target layer name/id\"),\n props: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\"Layer fields, e.g. {color, hidden, locked, name}\"),\n documentId,\n },\n run(ctx, args) {\n const { kind, name, layer, props, documentId: idArg } = args as {\n kind: \"add\" | \"update\" | \"remove\" | \"set-current\";\n name?: string;\n layer?: string;\n props?: Record<string, unknown>;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n const need = <T>(v: T | undefined, what: string): T => {\n if (v === undefined) throw new Error(`${kind} requires \"${what}\"`);\n return v;\n };\n let layerId: string | undefined;\n if (kind === \"add\") layerId = s.addLayer({ ...props, name: need(name, \"name\") });\n else if (kind === \"update\") s.updateLayer(need(layer, \"layer\"), props ?? {});\n else if (kind === \"remove\") s.removeLayer(need(layer, \"layer\"));\n else s.setCurrentLayer(need(layer, \"layer\"));\n return {\n ...(layerId ? { layerId } : {}),\n layers: s.listLayers(),\n revision: s.bump(),\n };\n },\n },\n {\n name: \"linea_render\",\n title: \"Render snapshot\",\n description:\n \"Render model space (or a paper layout via `layout`) for visual \" +\n \"verification. svg returns SVG markup as text; png returns an image \" +\n \"(Node MCP server only — the in-browser editor supports svg).\",\n inputSchema: {\n format: z.enum([\"svg\", \"png\"]).optional().describe(\"Default svg\"),\n layout: z.string().optional().describe(\"Layout name/id\"),\n bbox: box.optional(),\n padding: z.number().optional().describe(\"Around the content bbox, mm\"),\n width: z.number().int().positive().optional().describe(\"png only, px\"),\n background: z.string().optional().describe(\"png only, e.g. #ffffff\"),\n palette: z\n .enum([\"color\", \"grayscale\", \"monochrome\"])\n .optional()\n .describe(\n \"Print-style color remap — use monochrome with a white background \" +\n \"(light layer colors are authored for the dark canvas)\",\n ),\n documentId,\n },\n async run(ctx, args) {\n const { format, documentId: idArg, ...opts } = args as {\n format?: \"svg\" | \"png\";\n documentId?: string;\n } & RenderPngOptions;\n const s = ctx.get(idArg);\n if (format === \"png\") {\n if (!s.renderPng)\n throw new Error(\n \"png rendering is only available on the Node MCP server — use format: \\\"svg\\\"\",\n );\n const bytes = await s.renderPng(opts);\n return {\n content: [\n {\n type: \"image\" as const,\n // renderPng exists on the Node adapter only, so Buffer is here.\n data: Buffer.from(bytes).toString(\"base64\"),\n mimeType: \"image/png\",\n },\n ],\n };\n }\n return { content: [{ type: \"text\" as const, text: s.renderSvg(opts) }] };\n },\n },\n {\n name: \"linea_undo\",\n title: \"Undo\",\n description: \"Revert the last change (agent or user edit alike).\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n const undone = s.undo();\n return { undone, revision: undone ? s.bump() : s.revision() };\n },\n },\n {\n name: \"linea_redo\",\n title: \"Redo\",\n description: \"Re-apply the last undone change.\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n const redone = s.redo();\n return { redone, revision: redone ? s.bump() : s.revision() };\n },\n },\n {\n name: \"linea_summary\",\n title: \"Document summary\",\n description:\n \"Counts by type/layer, bbox, layers, layouts — the cheap 'what is in \" +\n \"this document' observation.\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n return { documentId: s.id, revision: s.revision(), ...s.summary() };\n },\n },\n {\n name: \"linea_get_document\",\n title: \"Get document JSON\",\n description:\n \"The full document (validated .linea JSON) + revision. The in-chat \" +\n \"viewer calls this to refresh; agents usually want linea_summary instead.\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n return { documentId: s.id, revision: s.revision(), document: s.getDocument() };\n },\n },\n {\n name: \"linea_replace_document\",\n title: \"Replace document state\",\n description:\n \"Replace the FULL document with the given .linea JSON (validated + \" +\n \"migrated). Used by the in-chat editor to persist interactive edits; \" +\n \"agents should prefer the granular add/update/transform tools.\",\n inputSchema: {\n document: z.record(z.string(), z.unknown()),\n documentId,\n },\n run(ctx, args) {\n const { document, documentId: idArg } = args as {\n document: Record<string, unknown>;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n return { documentId: s.id, revision: s.replace(document) };\n },\n },\n];\n"],"mappings":"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","names":["path","z","registry","z","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/documents.ts","../src/tools.ts","../../mcp-tools/src/tools.ts"],"sourcesContent":["// @lineadraw/mcp — MCP server exposing Linea document tools + the in-chat viewer\n// (MCP Apps extension). Two transports:\n//\n// stdio — for hosts that spawn the server as a subprocess (Claude Desktop):\n//\n// { \"command\": \"node\", \"args\": [\"<abs path>/dist/server.js\", \"--stdio\"] }\n//\n// Streamable HTTP (default) — Claude's web connectors require an https URL;\n// either tunnel plain HTTP (`npx cloudflared tunnel --url http://localhost:3001`)\n// or serve TLS locally with a mkcert certificate:\n//\n// mkcert -install && mkcert localhost\n// TLS_CERT=./localhost.pem TLS_KEY=./localhost-key.pem npm run serve\n//\n// and add https://localhost:3001/mcp as the custom connector.\n\nimport { readFileSync } from \"node:fs\";\nimport http, { type IncomingMessage, type ServerResponse } from \"node:http\";\nimport https from \"node:https\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { DocumentRegistry } from \"./documents.js\";\nimport { registerLineaTools } from \"./tools.js\";\n\nconst PORT = Number(process.env.PORT ?? 3001);\n\n// ONE registry for the process: every MCP session shares the open documents,\n// so a reconnecting client keeps its work.\nconst registry = new DocumentRegistry();\n\nconst buildServer = (): McpServer => {\n const server = new McpServer({ name: \"Lineadraw CAD\", version: \"0.1.0\" });\n registerLineaTools(server, registry);\n return server;\n};\n\nfunction startHttpServer() {\n const handle = async (req: IncomingMessage, res: ServerResponse) => {\n const path = (req.url ?? \"/\").split(\"?\")[0];\n // Log every request — when a connector fails to attach, an EMPTY log tells\n // you the client never reached this server at all (e.g. the check runs from\n // Anthropic infrastructure, which cannot see localhost — use a tunnel).\n console.log(`${new Date().toISOString()} ${req.method} ${path}`);\n\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET,POST,DELETE,OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n if (req.method === \"OPTIONS\") {\n res.writeHead(204).end();\n return;\n }\n\n // Route ALL methods through the transport: clients probe with GET (SSE\n // stream) and DELETE (session teardown) too, and the transport answers\n // those correctly for a stateless server — a bare 404 would read as\n // \"not an MCP server\". Served at \"/\" as well as \"/mcp\": Claude probes the\n // URL exactly as entered, and a bare origin should still work.\n if (path !== \"/\" && path !== \"/mcp\") {\n res.writeHead(404).end();\n return;\n }\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n });\n res.on(\"close\", () => transport.close());\n await buildServer().connect(transport);\n await transport.handleRequest(req, res);\n };\n\n const listener = (req: IncomingMessage, res: ServerResponse) => {\n void handle(req, res).catch((e) => {\n console.error(e);\n if (!res.headersSent) res.writeHead(500);\n res.end();\n });\n };\n\n const { TLS_CERT, TLS_KEY } = process.env;\n const tls = Boolean(TLS_CERT && TLS_KEY);\n const server = tls\n ? https.createServer(\n { cert: readFileSync(TLS_CERT!), key: readFileSync(TLS_KEY!) },\n listener,\n )\n : http.createServer(listener);\n server.listen(PORT, () => {\n console.log(\n tls\n ? `Linea MCP server on https://localhost:${PORT}/mcp`\n : `Linea MCP server on http://localhost:${PORT}/mcp (set TLS_CERT/TLS_KEY for https)`,\n );\n });\n}\n\n// stdio mode: stdout carries the JSON-RPC stream, so nothing else may be\n// written to it — log to stderr only.\nif (process.argv.includes(\"--stdio\")) {\n await buildServer().connect(new StdioServerTransport());\n console.error(\"Linea MCP server on stdio\");\n} else {\n startHttpServer();\n}\n","// In-process document registry: one MCP server session holds live Drawing\n// instances keyed by the document's own id (uuid stored IN the file, so\n// re-opening the same file targets the same entry). Most tools default to\n// the ACTIVE document — the last one created/opened — so single-document\n// conversations never pass ids around.\n\nimport { Drawing, newDrawing, openDrawing, drawingFromJson } from \"@lineadraw/sdk\";\n\nexport class DocumentRegistry {\n private docs = new Map<string, { doc: Drawing; revision: number }>();\n private activeId: string | null = null;\n\n create(name?: string): { id: string; doc: Drawing } {\n // Name must go through newDrawing: `doc.document` is a detached-clone\n // getter, so assigning `.name` on it mutates a throwaway copy.\n const doc = newDrawing(name);\n const id = doc.document.id;\n this.docs.set(id, { doc, revision: 0 });\n this.activeId = id;\n return { id, doc };\n }\n\n async open(path: string): Promise<{ id: string; doc: Drawing }> {\n const doc = await openDrawing(path);\n const id = doc.document.id;\n this.docs.set(id, { doc, revision: 0 });\n this.activeId = id;\n return { id, doc };\n }\n\n /** Resolve a document by id, or the active one when omitted. */\n get(id?: string): { id: string; doc: Drawing } {\n const key = id ?? this.activeId;\n if (!key) throw new Error(\"No document. Call linea_new_document first\");\n const entry = this.docs.get(key);\n if (!entry) throw new Error(`Unknown document \"${key}\"`);\n return { id: key, doc: entry.doc };\n }\n\n /**\n * Replace a document's full state (validated + migrated) — how in-chat\n * editor edits land. The id must match; conversation undo history resets.\n */\n replace(id: string, raw: unknown): { doc: Drawing; revision: number } {\n const entry = this.docs.get(id);\n if (!entry) throw new Error(`Unknown document \"${id}\"`);\n const doc = drawingFromJson(JSON.stringify(raw));\n if (doc.document.id !== id)\n throw new Error(\n `Document id mismatch: payload has \"${doc.document.id}\", expected \"${id}\"`,\n );\n entry.doc = doc;\n return { doc, revision: this.bump(id) };\n }\n\n /** Mark a document changed; the viewer compares revisions to refresh. */\n bump(id: string): number {\n const entry = this.docs.get(id);\n if (!entry) return 0;\n return ++entry.revision;\n }\n\n revision(id: string): number {\n return this.docs.get(id)?.revision ?? 0;\n }\n}\n","// Tool layer: the shared linea_* catalog (@lineadraw/mcp-tools) adapted onto\n// @lineadraw/sdk's Drawing, plus the Node-only tools (disk I/O, the MCP App).\n// Angles cross the tool boundary in DEGREES (handled by the shared handlers);\n// object payloads are validated by the SDK's zod schemas.\n\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n registerAppTool,\n registerAppResource,\n RESOURCE_MIME_TYPE,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport type { Drawing } from \"@lineadraw/sdk\";\nimport {\n coreLineaTools,\n documentId,\n runTool,\n toolError,\n toolResult,\n type DocumentSession,\n type ToolContext,\n} from \"@lineadraw/mcp-tools\";\nimport type { DocumentRegistry } from \"./documents.js\";\n\nexport const EDITOR_RESOURCE_URI = \"ui://linea/editor.html\";\n\n/** The shared catalog's session, backed by an SDK Drawing in the registry.\n * Most members are the Drawing method bound 1:1; only the ones that adapt\n * semantics (revision bookkeeping, remove count, ids filter, …) add a body. */\nconst drawingSession = (\n registry: DocumentRegistry,\n id: string,\n doc: Drawing,\n): DocumentSession => ({\n id,\n revision: () => registry.revision(id),\n bump: () => registry.bump(id),\n add: (objects, opts) =>\n doc.add(objects as Parameters<Drawing[\"add\"]>[0], { layout: opts?.layout }),\n update: (entries) => doc.update(entries),\n remove: (ids) => {\n const removed = ids.filter((oid) => doc.getObject(oid) !== undefined);\n doc.remove(ids);\n return removed.length;\n },\n query: (filter) => {\n const { ids, ...rest } = filter;\n let objects = doc.query(rest as Parameters<Drawing[\"query\"]>[0]);\n if (ids) {\n const wanted = new Set(ids);\n objects = objects.filter((o) => wanted.has(o.id));\n }\n return objects as unknown as Record<string, unknown>[];\n },\n measure: (oid) => ({\n bbox: doc.bboxOf([oid]),\n length: doc.length(oid),\n area: doc.area(oid),\n }),\n listLayers: () => {\n const current = doc.document.currentLayerId;\n return doc.layers.map((l) => ({ ...l, current: l.id === current }));\n },\n addLayer: (props) => doc.addLayer(props as Parameters<Drawing[\"addLayer\"]>[0]),\n updateLayer: doc.updateLayer.bind(doc),\n removeLayer: doc.removeLayer.bind(doc),\n setCurrentLayer: doc.setCurrentLayer.bind(doc),\n renderSvg: doc.toSvg.bind(doc),\n renderPng: doc.toPng.bind(doc),\n undo: doc.undo.bind(doc),\n redo: doc.redo.bind(doc),\n move: doc.move.bind(doc),\n rotate: doc.rotate.bind(doc),\n scale: doc.scale.bind(doc),\n mirror: doc.mirror.bind(doc),\n copy: doc.copy.bind(doc),\n array: doc.array.bind(doc),\n createLayout: (name, opts) =>\n doc.createLayout(name, {\n sheet: opts.sheet,\n orientation: opts.orientation,\n viewport: opts.scale !== undefined ? { scale: opts.scale } : undefined,\n }),\n updateLayout: doc.updateLayoutMeta.bind(doc),\n removeLayout: doc.removeLayout.bind(doc),\n setDimStyle: (patch, styleId) =>\n doc.setDimStyle(patch as Parameters<Drawing[\"setDimStyle\"]>[0], styleId),\n setTextStyle: (patch, styleId) =>\n doc.setTextStyle(patch as Parameters<Drawing[\"setTextStyle\"]>[0], styleId),\n summary: () => doc.summary() as unknown as Record<string, unknown>,\n getDocument: () => doc.document,\n replace: (raw) => registry.replace(id, raw).revision,\n});\n\nexport function registerLineaTools(\n server: McpServer,\n registry: DocumentRegistry,\n opts: { editorHtml?: () => Promise<string> } = {},\n): void {\n const ctx: ToolContext = {\n get(idArg?: string) {\n const { id, doc } = registry.get(idArg);\n return drawingSession(registry, id, doc);\n },\n };\n\n // The shared catalog (add/update/remove/transform/query/layers/render/\n // undo/summary/get/replace). runTool's results are valid CallToolResults\n // at runtime; the cast bridges its looser RawToolResult content typing\n // (needed for image content) to the SDK's exact union.\n for (const def of coreLineaTools) {\n server.registerTool(\n def.name,\n {\n title: def.title,\n description: def.description,\n inputSchema: def.inputSchema,\n },\n async (args: unknown) =>\n (await runTool(def, ctx, args)) as CallToolResult,\n );\n }\n\n // --- Node-only tools: registry lifecycle + disk I/O -----------------------\n\n const run = <A>(fn: (args: A) => unknown) => {\n return async (args: A) => {\n try {\n return toolResult(await fn(args));\n } catch (e) {\n return toolError(e);\n }\n };\n };\n\n server.registerTool(\n \"linea_new_document\",\n {\n title: \"New Linea document\",\n description:\n \"Create a fresh CAD document (mm, Y-up) and make it active. \" +\n \"Call linea_show_document afterwards to display it in chat.\",\n inputSchema: { name: z.string().optional() },\n },\n run(({ name }: { name?: string }) => {\n const { id, doc } = registry.create(name);\n return { documentId: id, summary: doc.summary() };\n }),\n );\n\n server.registerTool(\n \"linea_open_document\",\n {\n title: \"Open .linea file\",\n description:\n \"Open a .linea file (or legacy .lineadraw) from disk and make it active.\",\n inputSchema: { path: z.string() },\n },\n run(async ({ path: p }: { path: string }) => {\n const { id, doc } = await registry.open(p);\n return { documentId: id, migration: doc.migration, summary: doc.summary() };\n }),\n );\n\n server.registerTool(\n \"linea_save_document\",\n {\n title: \"Save .linea file\",\n description: \"Save the document to disk as .linea JSON.\",\n inputSchema: { path: z.string(), documentId },\n },\n run(async ({ path: p, documentId: idArg }: { path: string; documentId?: string }) => {\n const { doc } = registry.get(idArg);\n await doc.save(p);\n return { saved: p };\n }),\n );\n\n server.registerTool(\n \"linea_export\",\n {\n title: \"Export document\",\n description: \"Write the document to disk as svg | png | pdf | dxf | dwg.\",\n inputSchema: {\n format: z.enum([\"svg\", \"png\", \"pdf\", \"dxf\", \"dwg\"]),\n path: z.string(),\n layout: z.string().optional().describe(\"Render a layout instead of model space (svg/png)\"),\n documentId,\n },\n },\n run(async ({ format, path: p, layout, documentId: idArg }: {\n format: \"svg\" | \"png\" | \"pdf\" | \"dxf\" | \"dwg\";\n path: string;\n layout?: string;\n documentId?: string;\n }) => {\n const { doc } = registry.get(idArg);\n if (format === \"svg\") await doc.exportSvg(p, { layout });\n else if (format === \"png\") await doc.exportPng(p, { layout });\n else if (format === \"pdf\") await doc.exportPdf(p);\n else if (format === \"dwg\") await doc.exportDwg(p);\n else await doc.exportDxf(p);\n return { exported: p };\n }),\n );\n\n // --- the MCP App: the full editor, in chat ---------------------------------\n\n registerAppTool(\n server,\n \"linea_show_document\",\n {\n title: \"Show Linea document\",\n description:\n \"Open the document in the FULL interactive Linea editor INSIDE the \" +\n \"chat: the user can view, pan/zoom, draw, snap, dimension, and edit; \" +\n \"their changes flow back into the document. Call this after creating \" +\n \"or meaningfully changing a document, or whenever the user wants to \" +\n \"see or edit it.\",\n inputSchema: { documentId },\n _meta: { ui: { resourceUri: EDITOR_RESOURCE_URI } },\n },\n (async ({ documentId: idArg }: { documentId?: string }) => {\n try {\n const { id, doc } = registry.get(idArg);\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Showing \"${doc.document.name}\" in the in-chat editor (${doc.objects.length} model objects)`,\n },\n ],\n structuredContent: {\n documentId: id,\n revision: registry.revision(id),\n document: doc.document,\n } as unknown as Record<string, unknown>,\n };\n } catch (e) {\n return toolError(e);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n }) as any,\n );\n\n registerAppResource(\n server,\n \"Linea editor\",\n EDITOR_RESOURCE_URI,\n { mimeType: RESOURCE_MIME_TYPE },\n async () => ({\n contents: [\n {\n uri: EDITOR_RESOURCE_URI,\n mimeType: RESOURCE_MIME_TYPE,\n text: await (opts.editorHtml ??\n (async () => {\n const here = path.dirname(fileURLToPath(import.meta.url));\n // Bundled server: editor.html sits next to dist/server.js.\n // Dev (tsx src/server.ts): it lives in the sibling dist/.\n return readFile(path.join(here, \"editor.html\"), \"utf-8\").catch(\n () =>\n readFile(path.join(here, \"..\", \"dist\", \"editor.html\"), \"utf-8\"),\n );\n }))(),\n },\n ],\n }),\n );\n}\n","// The shared linea_* tool catalog: one definition per tool — name, schema,\n// and a handler written against DocumentSession — consumed verbatim by the\n// Node MCP server (@lineadraw/mcp, zod shapes) and the in-browser WebMCP layer\n// (@lineadraw/editor, JSON Schema via toolJsonSchema). Angles cross this\n// boundary in DEGREES (agent ergonomics); tool-arg points are [x, y] tuples\n// (see `point` below); points INSIDE object bodies also accept {x, y}.\n\nimport { z } from \"zod\";\nimport type {\n PointInput,\n QueryFilter,\n RenderPngOptions,\n ToolContext,\n} from \"./session\";\n\nconst DEG2RAD = Math.PI / 180;\n\nconst box = z\n .object({\n minX: z.number(),\n minY: z.number(),\n maxX: z.number(),\n maxY: z.number(),\n })\n .describe(\"An axis-aligned box in world mm\");\n\n// Deliberately tuple-only, NOT union([tuple, {x,y}]): a bare-anyOf property\n// has no top-level `type`, and schema-rebuilding bridges (the WebMCP local\n// relay among them) degrade such properties to untyped {} — hosts then\n// string-encode the value and every call fails validation. A tuple keeps\n// `type: \"array\"` at the top level everywhere. ({x, y} still parses fine in\n// OBJECT bodies — model schemas accept both; this is only the tool-arg form.)\nconst point = z\n .tuple([z.number(), z.number()])\n .describe(\"A world point in mm: [x, y]\");\n\nconst looseObject = z\n .record(z.string(), z.unknown())\n .describe(\n 'A Linea model object, e.g. {\"type\":\"line\",\"a\":[0,0],\"b\":[100,0]}. ' +\n \"Types: line, point (p; paints as a dot sized by lineWidth), \" +\n \"polyline (points with bulge, closed), circle, arc, \" +\n \"ellipse, hatch, text, dimension, block. Optional layer (name), \" +\n \"color (#rrggbb), lineType.\",\n );\n\nexport const documentId = z\n .string()\n .optional()\n .describe(\"Document id; omit for the active document\");\n\nexport interface LineaToolDef {\n name: string;\n title: string;\n description: string;\n /** Zod raw shape — the MCP SDK consumes it verbatim; browser adapters\n * convert via toolJsonSchema and validate via toolArgs. */\n inputSchema: z.ZodRawShape;\n run(\n ctx: ToolContext,\n args: Record<string, unknown>,\n ): unknown | Promise<unknown>;\n}\n\n/** Success payload in MCP content shape (text + structuredContent). */\nexport const toolResult = (data: unknown) => ({\n content: [{ type: \"text\" as const, text: JSON.stringify(data) }],\n structuredContent: data as Record<string, unknown>,\n});\n\n/** A handler result that already IS a CallToolResult (e.g. image content) —\n * runTool passes it through instead of JSON-wrapping it. */\nexport type RawToolResult = {\n content: ({ type: string } & Record<string, unknown>)[];\n isError?: boolean;\n structuredContent?: Record<string, unknown>;\n};\n\nconst isRawToolResult = (v: unknown): v is RawToolResult =>\n typeof v === \"object\" &&\n v !== null &&\n Array.isArray((v as { content?: unknown }).content);\n\n/** Error payload in MCP content shape. */\nexport const toolError = (e: unknown) => ({\n content: [\n { type: \"text\" as const, text: String(e instanceof Error ? e.message : e) },\n ],\n isError: true as const,\n});\n\n/** Parse args against the tool's schema, run it, wrap result/error. */\nexport const runTool = async (\n def: LineaToolDef,\n ctx: ToolContext,\n args: unknown,\n): Promise<\n ReturnType<typeof toolResult> | ReturnType<typeof toolError> | RawToolResult\n> => {\n try {\n const parsed = z.object(def.inputSchema).parse(args ?? {});\n const out = await def.run(ctx, parsed);\n return isRawToolResult(out) ? out : toolResult(out);\n } catch (e) {\n return toolError(e);\n }\n};\n\n/** The tool's input schema as plain JSON Schema (WebMCP registration). */\nexport const toolJsonSchema = (def: LineaToolDef): Record<string, unknown> =>\n z.toJSONSchema(z.object(def.inputSchema), { io: \"input\" }) as Record<\n string,\n unknown\n >;\n\ntype TransformArgs = {\n kind: \"move\" | \"rotate\" | \"scale\" | \"mirror\" | \"copy\" | \"array\";\n ids: string[];\n delta?: PointInput;\n angleDeg?: number;\n factor?: number;\n center?: PointInput;\n axisA?: PointInput;\n axisB?: PointInput;\n count?: number;\n documentId?: string;\n};\n\n/**\n * The environment-neutral tools — everything that only needs a document\n * session. Node-only tools (new/open/save/export, the MCP App) live in\n * @lineadraw/mcp; browser-only tools (selection, view, spaces) in @lineadraw/editor.\n */\nexport const coreLineaTools: LineaToolDef[] = [\n {\n name: \"linea_add_objects\",\n title: \"Add objects\",\n description:\n \"Add objects to model space (or a paper layout via `layout`). \" +\n \"Returns the created ids.\",\n inputSchema: {\n objects: z.array(looseObject).min(1),\n layout: z\n .string()\n .optional()\n .describe(\"Layout name/id for sheet annotations\"),\n documentId,\n },\n run(ctx, args) {\n const { objects, layout, documentId: idArg } = args as {\n objects: Record<string, unknown>[];\n layout?: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n const ids = s.add(objects, { layout });\n return { ids, revision: s.bump() };\n },\n },\n {\n name: \"linea_update_objects\",\n title: \"Update objects\",\n description:\n \"Patch objects by id: entries are {id, ...fieldsToChange}. One undo step.\",\n inputSchema: {\n entries: z.array(z.record(z.string(), z.unknown())).min(1),\n documentId,\n },\n run(ctx, args) {\n const { entries, documentId: idArg } = args as {\n entries: Record<string, unknown>[];\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.update(entries as ({ id: string } & Record<string, unknown>)[]);\n return { updated: entries.length, revision: s.bump() };\n },\n },\n {\n name: \"linea_remove_objects\",\n title: \"Remove objects\",\n description:\n \"Delete objects by id. Unknown ids are skipped; `removed` reports how \" +\n \"many objects were actually deleted.\",\n inputSchema: { ids: z.array(z.string()).min(1), documentId },\n run(ctx, args) {\n const { ids, documentId: idArg } = args as {\n ids: string[];\n documentId?: string;\n };\n const s = ctx.get(idArg);\n const removed = s.remove(ids);\n return { removed, revision: s.bump() };\n },\n },\n {\n name: \"linea_transform\",\n title: \"Transform objects\",\n description:\n \"move (delta) | rotate (angleDeg, center?) | scale (factor, center?) | \" +\n \"mirror (axisA, axisB) | copy (delta → new ids) | array (count TOTAL, delta → new ids). \" +\n \"rotate/scale default their center to the selection bbox center.\",\n inputSchema: {\n kind: z.enum([\"move\", \"rotate\", \"scale\", \"mirror\", \"copy\", \"array\"]),\n ids: z.array(z.string()).min(1),\n delta: point.optional(),\n angleDeg: z.number().optional(),\n factor: z.number().optional(),\n center: point.optional(),\n axisA: point.optional(),\n axisB: point.optional(),\n count: z.number().int().optional(),\n documentId,\n },\n run(ctx, args) {\n const a = args as TransformArgs;\n const s = ctx.get(a.documentId);\n const need = <T>(v: T | undefined, name: string): T => {\n if (v === undefined) throw new Error(`${a.kind} requires \"${name}\"`);\n return v;\n };\n let created: string[] | undefined;\n switch (a.kind) {\n case \"move\":\n s.move(a.ids, need(a.delta, \"delta\"));\n break;\n case \"rotate\":\n s.rotate(a.ids, need(a.angleDeg, \"angleDeg\") * DEG2RAD, a.center);\n break;\n case \"scale\":\n s.scale(a.ids, need(a.factor, \"factor\"), a.center);\n break;\n case \"mirror\":\n s.mirror(a.ids, need(a.axisA, \"axisA\"), need(a.axisB, \"axisB\"));\n break;\n case \"copy\":\n created = s.copy(a.ids, need(a.delta, \"delta\"));\n break;\n case \"array\":\n created = s.array(a.ids, need(a.count, \"count\"), need(a.delta, \"delta\"));\n break;\n }\n return { ...(created ? { ids: created } : {}), revision: s.bump() };\n },\n },\n {\n name: \"linea_create_layout\",\n title: \"Create paper layout\",\n description:\n \"Add a paper layout (default: A3 landscape, one viewport fitted to \" +\n 'the model extents). scale accepts \"1:50\" strings.',\n inputSchema: {\n name: z.string(),\n // Named size + optional custom mm — two typed params instead of a\n // union so every property keeps a top-level JSON-schema `type`\n // (see `point` for why bare anyOf properties are relay-hostile).\n sheet: z.enum([\"A4\", \"A3\", \"A2\", \"A1\", \"A0\"]).optional(),\n sheetSize: z\n .object({ width: z.number(), height: z.number() })\n .optional()\n .describe(\"Custom sheet size in mm (overrides `sheet`)\"),\n orientation: z.enum([\"portrait\", \"landscape\"]).optional(),\n scale: z.string().optional().describe('Viewport scale, e.g. \"1:50\"'),\n documentId,\n },\n run(ctx, args) {\n const { name, sheet, sheetSize, orientation, scale, documentId: idArg } =\n args as {\n name: string;\n sheet?: \"A4\" | \"A3\" | \"A2\" | \"A1\" | \"A0\";\n sheetSize?: { width: number; height: number };\n orientation?: \"portrait\" | \"landscape\";\n scale?: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n const layoutId = s.createLayout(name, {\n sheet: sheetSize ?? sheet,\n orientation,\n scale,\n });\n return { layoutId, revision: s.bump() };\n },\n },\n {\n name: \"linea_update_layout\",\n title: \"Update layout\",\n description:\n \"Patch a paper layout's name, sheet size (mm), or print palette \" +\n '(printPalette \"monochrome\" prints/renders everything black).',\n inputSchema: {\n layout: z.string().describe(\"Layout name/id\"),\n name: z.string().optional().describe(\"New layout name\"),\n sheetSize: z\n .object({ width: z.number(), height: z.number() })\n .optional()\n .describe(\"New sheet size in mm\"),\n printPalette: z.enum([\"color\", \"grayscale\", \"monochrome\"]).optional(),\n documentId,\n },\n run(ctx, args) {\n const { layout, name, sheetSize, printPalette, documentId: idArg } =\n args as {\n layout: string;\n name?: string;\n sheetSize?: { width: number; height: number };\n printPalette?: \"color\" | \"grayscale\" | \"monochrome\";\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.updateLayout(layout, { name, sheet: sheetSize, printPalette });\n return { revision: s.bump() };\n },\n },\n {\n name: \"linea_remove_layout\",\n title: \"Remove layout\",\n description: \"Delete a paper layout (and its sheet objects) by name or id.\",\n inputSchema: {\n layout: z.string().describe(\"Layout name/id\"),\n documentId,\n },\n run(ctx, args) {\n const { layout, documentId: idArg } = args as {\n layout: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.removeLayout(layout);\n return { revision: s.bump() };\n },\n },\n {\n name: \"linea_set_dim_style\",\n title: \"Set dimension style\",\n description:\n \"Patch a document dimension style (default: the first): textHeight, \" +\n \"textOffset, arrowType (filled|open|tick|dot|none), arrowSize, \" +\n \"extensionType (long|short), extensionOffset, extensionOvershoot, \" +\n \"precision, font (arial|osifont|jetbrains-mono|source-serif), \" +\n \"widthFactor. NOTE: annotation scale is NOT a style \" +\n \"key: set the top-level `scale` field on each dimension object.\",\n inputSchema: {\n patch: z.record(z.string(), z.unknown()),\n styleId: z.string().optional(),\n documentId,\n },\n run(ctx, args) {\n const { patch, styleId, documentId: idArg } = args as {\n patch: Record<string, unknown>;\n styleId?: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.setDimStyle(patch, styleId);\n return { revision: s.bump() };\n },\n },\n {\n name: \"linea_set_text_style\",\n title: \"Set text style\",\n description:\n \"Patch a document text style (default: the first): font \" +\n \"(arial|osifont|jetbrains-mono|source-serif), widthFactor, \" +\n \"textHeight (default height for new text), arrowType, arrowSize \" +\n \"(leader arrows). Per-object styleOverride still wins over the style.\",\n inputSchema: {\n patch: z.record(z.string(), z.unknown()),\n styleId: z.string().optional(),\n documentId,\n },\n run(ctx, args) {\n const { patch, styleId, documentId: idArg } = args as {\n patch: Record<string, unknown>;\n styleId?: string;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n s.setTextStyle(patch, styleId);\n return { revision: s.bump() };\n },\n },\n {\n name: \"linea_query\",\n title: \"Query objects\",\n description:\n \"Filtered read over model-space objects, or one paper layout's sheet \" +\n \"objects (viewports, annotations) via `layout`. All filters AND: \" +\n \"type, layer (name), color, lineType, content (text substring), bbox \" +\n \"(intersects), inside (contained), near ({point, tol}), ids. \" +\n \"`measure: true` adds bbox/length/area per object. Prefer this over \" +\n \"linea_get_document; it returns compact data.\",\n inputSchema: {\n ids: z.array(z.string()).optional(),\n type: z.string().optional(),\n layer: z.string().optional(),\n color: z.string().optional(),\n lineType: z.string().optional(),\n content: z.string().optional(),\n bbox: box.optional(),\n inside: box.optional(),\n near: z.object({ point, tol: z.number().positive() }).optional(),\n layout: z\n .string()\n .optional()\n .describe(\"Search this layout's sheet objects (name/id) instead of model space\"),\n measure: z.boolean().optional(),\n limit: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Max objects returned (default 100)\"),\n documentId,\n },\n run(ctx, args) {\n const { measure, limit, documentId: idArg, ...filter } = args as {\n measure?: boolean;\n limit?: number;\n documentId?: string;\n } & QueryFilter;\n const s = ctx.get(idArg);\n const all = s.query(filter);\n const cap = limit ?? 100;\n const objects = all.slice(0, cap).map((o) =>\n measure ? { ...o, measure: s.measure(String(o.id)) } : o,\n );\n return { total: all.length, returned: objects.length, objects };\n },\n },\n {\n name: \"linea_list_layers\",\n title: \"List layers\",\n description:\n \"All layers with full metadata (color, hidden, locked, …) and which \" +\n \"one is current (the default for new objects).\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n return { layers: s.listLayers() };\n },\n },\n {\n name: \"linea_layer\",\n title: \"Manage layers\",\n description:\n \"add (name, props?) | update (layer, props; rename via props.name) | \" +\n \"remove (layer; must be empty and not current) | set-current (layer). \" +\n \"`layer` targets by name or id. Returns the resulting layer list.\",\n inputSchema: {\n kind: z.enum([\"add\", \"update\", \"remove\", \"set-current\"]),\n name: z.string().optional().describe(\"New layer name (kind: add)\"),\n layer: z.string().optional().describe(\"Target layer name/id\"),\n props: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\"Layer fields, e.g. {color, hidden, locked, name}\"),\n documentId,\n },\n run(ctx, args) {\n const { kind, name, layer, props, documentId: idArg } = args as {\n kind: \"add\" | \"update\" | \"remove\" | \"set-current\";\n name?: string;\n layer?: string;\n props?: Record<string, unknown>;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n const need = <T>(v: T | undefined, what: string): T => {\n if (v === undefined) throw new Error(`${kind} requires \"${what}\"`);\n return v;\n };\n let layerId: string | undefined;\n if (kind === \"add\") layerId = s.addLayer({ ...props, name: need(name, \"name\") });\n else if (kind === \"update\") s.updateLayer(need(layer, \"layer\"), props ?? {});\n else if (kind === \"remove\") s.removeLayer(need(layer, \"layer\"));\n else s.setCurrentLayer(need(layer, \"layer\"));\n return {\n ...(layerId ? { layerId } : {}),\n layers: s.listLayers(),\n revision: s.bump(),\n };\n },\n },\n {\n name: \"linea_render\",\n title: \"Render snapshot\",\n description:\n \"Render model space (or a paper layout via `layout`) for visual \" +\n \"verification. svg returns SVG markup as text; png returns an image \" +\n \"(Node MCP server only; the in-browser editor supports svg).\",\n inputSchema: {\n format: z.enum([\"svg\", \"png\"]).optional().describe(\"Default svg\"),\n layout: z.string().optional().describe(\"Layout name/id\"),\n bbox: box.optional(),\n padding: z.number().optional().describe(\"Around the content bbox, mm\"),\n width: z.number().int().positive().optional().describe(\"png only, px\"),\n background: z.string().optional().describe(\"png only, e.g. #ffffff\"),\n palette: z\n .enum([\"color\", \"grayscale\", \"monochrome\"])\n .optional()\n .describe(\n \"Print-style color remap: use monochrome with a white background \" +\n \"(light layer colors are authored for the dark canvas)\",\n ),\n documentId,\n },\n async run(ctx, args) {\n const { format, documentId: idArg, ...opts } = args as {\n format?: \"svg\" | \"png\";\n documentId?: string;\n } & RenderPngOptions;\n const s = ctx.get(idArg);\n if (format === \"png\") {\n if (!s.renderPng)\n throw new Error(\n \"png rendering is only available on the Node MCP server; use format: \\\"svg\\\"\",\n );\n const bytes = await s.renderPng(opts);\n return {\n content: [\n {\n type: \"image\" as const,\n // renderPng exists on the Node adapter only, so Buffer is here.\n data: Buffer.from(bytes).toString(\"base64\"),\n mimeType: \"image/png\",\n },\n ],\n };\n }\n return { content: [{ type: \"text\" as const, text: s.renderSvg(opts) }] };\n },\n },\n {\n name: \"linea_undo\",\n title: \"Undo\",\n description: \"Revert the last change (agent or user edit alike).\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n const undone = s.undo();\n return { undone, revision: undone ? s.bump() : s.revision() };\n },\n },\n {\n name: \"linea_redo\",\n title: \"Redo\",\n description: \"Re-apply the last undone change.\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n const redone = s.redo();\n return { redone, revision: redone ? s.bump() : s.revision() };\n },\n },\n {\n name: \"linea_summary\",\n title: \"Document summary\",\n description:\n \"Counts by type/layer, bbox, layers, layouts: the cheap 'what is in \" +\n \"this document' observation.\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n return { documentId: s.id, revision: s.revision(), ...s.summary() };\n },\n },\n {\n name: \"linea_get_document\",\n title: \"Get document JSON\",\n description:\n \"The full document (validated .linea JSON) + revision. The in-chat \" +\n \"viewer calls this to refresh; agents usually want linea_summary instead.\",\n inputSchema: { documentId },\n run(ctx, args) {\n const s = ctx.get((args as { documentId?: string }).documentId);\n return { documentId: s.id, revision: s.revision(), document: s.getDocument() };\n },\n },\n {\n name: \"linea_replace_document\",\n title: \"Replace document state\",\n description:\n \"Replace the FULL document with the given .linea JSON (validated + \" +\n \"migrated). Used by the in-chat editor to persist interactive edits; \" +\n \"agents should prefer the granular add/update/transform tools.\",\n inputSchema: {\n document: z.record(z.string(), z.unknown()),\n documentId,\n },\n run(ctx, args) {\n const { document, documentId: idArg } = args as {\n document: Record<string, unknown>;\n documentId?: string;\n };\n const s = ctx.get(idArg);\n return { documentId: s.id, revision: s.replace(document) };\n },\n },\n];\n"],"mappings":"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","names":["path","z","registry","z","path"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lineadraw/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MCP server + in-chat viewer (MCP App) for Linea CAD documents.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
"prepack": "npm run build"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@lineadraw/sdk": "^0.
|
|
29
|
-
"@modelcontextprotocol/ext-apps": "^1.7.
|
|
30
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
31
|
-
"zod": "^4.4
|
|
28
|
+
"@lineadraw/sdk": "^0.13.0",
|
|
29
|
+
"@modelcontextprotocol/ext-apps": "^1.7.5",
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
31
|
+
"zod": "^4.5.4"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@eslint/js": "^10.0.1",
|
|
@@ -36,23 +36,23 @@
|
|
|
36
36
|
"@lineadraw/editor": "*",
|
|
37
37
|
"@lineadraw/mcp-tools": "*",
|
|
38
38
|
"@tailwindcss/vite": "^4.3.3",
|
|
39
|
-
"@types/node": "^26.
|
|
40
|
-
"@types/react": "^19.2.
|
|
41
|
-
"@types/react-dom": "^19.2.
|
|
42
|
-
"@vitejs/plugin-react": "^6.
|
|
43
|
-
"eslint": "^10.
|
|
39
|
+
"@types/node": "^26.4.0",
|
|
40
|
+
"@types/react": "^19.2.18",
|
|
41
|
+
"@types/react-dom": "^19.2.5",
|
|
42
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
43
|
+
"eslint": "^10.9.1",
|
|
44
44
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
45
|
-
"eslint-plugin-react-refresh": "^0.5.
|
|
46
|
-
"globals": "^17.
|
|
47
|
-
"react": "^19.2.
|
|
48
|
-
"react-dom": "^19.2.
|
|
45
|
+
"eslint-plugin-react-refresh": "^0.5.5",
|
|
46
|
+
"globals": "^17.11.0",
|
|
47
|
+
"react": "^19.2.8",
|
|
48
|
+
"react-dom": "^19.2.8",
|
|
49
49
|
"tailwindcss": "^4.3.3",
|
|
50
50
|
"tsup": "^8.5.1",
|
|
51
|
-
"tsx": "^4.23.
|
|
52
|
-
"typescript": "
|
|
53
|
-
"typescript-eslint": "^8.
|
|
54
|
-
"vite": "^8.
|
|
51
|
+
"tsx": "^4.23.13",
|
|
52
|
+
"typescript": "6.0.3",
|
|
53
|
+
"typescript-eslint": "^8.68.0",
|
|
54
|
+
"vite": "^8.2.2",
|
|
55
55
|
"vite-plugin-singlefile": "^2.3.3",
|
|
56
|
-
"vitest": "^4.1.
|
|
56
|
+
"vitest": "^4.1.11"
|
|
57
57
|
}
|
|
58
58
|
}
|