@mylasertools/kerfscript-mcp 0.0.0-stage → 0.1.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/LICENSE +661 -0
- package/OFL.txt +92 -0
- package/README.md +96 -2
- package/THIRD-PARTY-NOTICES.md +133 -0
- package/dist/budget.js +9 -0
- package/dist/chunk-43YRASDL.js +131 -0
- package/dist/chunk-6NSCAH6P.js +8884 -0
- package/dist/chunk-7I3ZJGJF.js +34 -0
- package/dist/chunk-IY7POWTF.js +19 -0
- package/dist/chunk-JUDNQ5QA.js +8220 -0
- package/dist/chunk-O5LBJLFO.js +23 -0
- package/dist/chunk-T5JFV7HE.js +154 -0
- package/dist/chunk-Z46EXYJU.js +32 -0
- package/dist/execute.js +8 -0
- package/dist/isolated.js +9 -0
- package/dist/replies.js +10 -0
- package/dist/runner.js +10 -0
- package/dist/service.js +39 -0
- package/dist/stdio.js +14 -0
- package/dist/tools.js +11 -0
- package/dist/types/src/budget.d.ts +14 -0
- package/dist/types/src/execute.d.ts +2 -0
- package/dist/types/src/isolated.d.ts +14 -0
- package/dist/types/src/replies.d.ts +13 -0
- package/dist/types/src/runner.d.ts +1 -0
- package/dist/types/src/schema.d.ts +33 -0
- package/dist/types/src/service.d.ts +9 -0
- package/dist/types/src/stdio.d.ts +1 -0
- package/dist/types/src/tools.d.ts +5 -0
- package/dist/types/src/worker.d.ts +11 -0
- package/dist/worker.js +16 -0
- package/package.json +75 -4
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/budget.ts
|
|
2
|
+
var DAY = 864e5;
|
|
3
|
+
var secondsToMidnight = (now = Date.now()) => Math.ceil((DAY - now % DAY) / 1e3);
|
|
4
|
+
async function spend(storage, client, clientLimit, totalLimit, now = Date.now()) {
|
|
5
|
+
const day = new Date(now).toISOString().slice(0, 10);
|
|
6
|
+
const key = `client:${client}`;
|
|
7
|
+
const stored = await storage.get(["day", "total", key]);
|
|
8
|
+
if (stored.get("day") !== day) {
|
|
9
|
+
await storage.deleteAll();
|
|
10
|
+
stored.clear();
|
|
11
|
+
}
|
|
12
|
+
const total = Number(stored.get("total") ?? 0);
|
|
13
|
+
const used = Number(stored.get(key) ?? 0);
|
|
14
|
+
if (!(total < totalLimit)) return "total";
|
|
15
|
+
if (!(used < clientLimit)) return "client";
|
|
16
|
+
await storage.put({ day, total: total + 1, [key]: used + 1 });
|
|
17
|
+
return "ok";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
secondsToMidnight,
|
|
22
|
+
spend
|
|
23
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// src/isolated.ts
|
|
2
|
+
import { Worker } from "node:worker_threads";
|
|
3
|
+
var failure = (message) => ({ ok: false, error: { message } });
|
|
4
|
+
function createExecutorPool({
|
|
5
|
+
size = 2,
|
|
6
|
+
maxQueue = 16,
|
|
7
|
+
timeoutMs = 5e3,
|
|
8
|
+
queueTimeoutMs = 5e3,
|
|
9
|
+
startupTimeoutMs = 5e3,
|
|
10
|
+
workerUrl = new URL("./runner.js", import.meta.url)
|
|
11
|
+
} = {}) {
|
|
12
|
+
for (const n of [size, maxQueue, timeoutMs, queueTimeoutMs, startupTimeoutMs])
|
|
13
|
+
if (!Number.isSafeInteger(n) || n < 1)
|
|
14
|
+
throw new Error("Pool limits must be positive integers.");
|
|
15
|
+
const slots = /* @__PURE__ */ new Set();
|
|
16
|
+
const queue = [];
|
|
17
|
+
const terminations = /* @__PURE__ */ new Set();
|
|
18
|
+
let closed = false;
|
|
19
|
+
function finish(item, result) {
|
|
20
|
+
clearTimeout(item.timer);
|
|
21
|
+
item.signal?.removeEventListener("abort", item.cancel);
|
|
22
|
+
item.resolve(result);
|
|
23
|
+
}
|
|
24
|
+
function retire(slot, message) {
|
|
25
|
+
if (slot.retiring) return;
|
|
26
|
+
slot.retiring = true;
|
|
27
|
+
clearTimeout(slot.startup);
|
|
28
|
+
if (slot.item) {
|
|
29
|
+
finish(slot.item, failure(message));
|
|
30
|
+
slot.item = void 0;
|
|
31
|
+
}
|
|
32
|
+
const done = () => {
|
|
33
|
+
slots.delete(slot);
|
|
34
|
+
terminations.delete(stopped);
|
|
35
|
+
pump();
|
|
36
|
+
};
|
|
37
|
+
const stopped = slot.worker.terminate().then(done, done);
|
|
38
|
+
terminations.add(stopped);
|
|
39
|
+
}
|
|
40
|
+
function start(slot) {
|
|
41
|
+
const item = slot.item;
|
|
42
|
+
if (!slot.ready || !item || slot.retiring) return;
|
|
43
|
+
clearTimeout(item.timer);
|
|
44
|
+
item.timer = setTimeout(
|
|
45
|
+
() => retire(
|
|
46
|
+
slot,
|
|
47
|
+
"Rendering exceeded its execution deadline. Reduce complexity or render locally."
|
|
48
|
+
),
|
|
49
|
+
timeoutMs
|
|
50
|
+
);
|
|
51
|
+
try {
|
|
52
|
+
slot.worker.postMessage(item.job);
|
|
53
|
+
} catch {
|
|
54
|
+
retire(slot, "Unable to send the job to the renderer.");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function spawn() {
|
|
58
|
+
const worker = new Worker(workerUrl, {
|
|
59
|
+
resourceLimits: { maxOldGenerationSizeMb: 96, stackSizeMb: 4 }
|
|
60
|
+
});
|
|
61
|
+
const slot = { worker, ready: false, retiring: false };
|
|
62
|
+
slots.add(slot);
|
|
63
|
+
slot.startup = setTimeout(() => retire(slot, "Renderer startup timed out."), startupTimeoutMs);
|
|
64
|
+
worker.on("message", (result) => {
|
|
65
|
+
if (slot.retiring) return;
|
|
66
|
+
if (!slot.ready) {
|
|
67
|
+
if (result.ready !== true) {
|
|
68
|
+
retire(slot, "Invalid renderer startup response.");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
slot.ready = true;
|
|
72
|
+
clearTimeout(slot.startup);
|
|
73
|
+
start(slot);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (!slot.item) {
|
|
77
|
+
retire(slot, "Unexpected renderer response.");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
finish(slot.item, result);
|
|
81
|
+
slot.item = void 0;
|
|
82
|
+
worker.unref();
|
|
83
|
+
pump();
|
|
84
|
+
});
|
|
85
|
+
worker.on("error", () => retire(slot, "Renderer exceeded its resources or failed."));
|
|
86
|
+
worker.on("exit", () => retire(slot, "Renderer stopped before returning a result."));
|
|
87
|
+
return slot;
|
|
88
|
+
}
|
|
89
|
+
function pump() {
|
|
90
|
+
while (!closed && queue.length) {
|
|
91
|
+
let slot = [...slots].find((s) => !s.retiring && !s.item);
|
|
92
|
+
if (!slot && slots.size >= size) return;
|
|
93
|
+
const item = queue.shift();
|
|
94
|
+
try {
|
|
95
|
+
slot ??= spawn();
|
|
96
|
+
} catch {
|
|
97
|
+
finish(item, failure("Unable to start renderer."));
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
clearTimeout(item.timer);
|
|
101
|
+
slot.item = item;
|
|
102
|
+
slot.worker.ref();
|
|
103
|
+
start(slot);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const execute = (job, signal) => {
|
|
107
|
+
if (closed) return Promise.resolve(failure("Renderer pool is closed."));
|
|
108
|
+
if (signal?.aborted) return Promise.resolve(failure("Cancelled."));
|
|
109
|
+
if (queue.length >= maxQueue)
|
|
110
|
+
return Promise.resolve(failure("Renderer queue is full. Retry later."));
|
|
111
|
+
return new Promise((resolve) => {
|
|
112
|
+
const item = {
|
|
113
|
+
job,
|
|
114
|
+
resolve,
|
|
115
|
+
signal,
|
|
116
|
+
cancel: () => {
|
|
117
|
+
const index = queue.indexOf(item);
|
|
118
|
+
if (index >= 0) {
|
|
119
|
+
queue.splice(index, 1);
|
|
120
|
+
finish(item, failure("Cancelled."));
|
|
121
|
+
} else {
|
|
122
|
+
const slot = [...slots].find((s) => s.item === item);
|
|
123
|
+
if (slot) retire(slot, "Cancelled.");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
item.timer = setTimeout(() => {
|
|
128
|
+
const index = queue.indexOf(item);
|
|
129
|
+
if (index >= 0) {
|
|
130
|
+
queue.splice(index, 1);
|
|
131
|
+
finish(item, failure("Renderer queue wait timed out. Retry later."));
|
|
132
|
+
}
|
|
133
|
+
}, queueTimeoutMs);
|
|
134
|
+
signal?.addEventListener("abort", item.cancel, { once: true });
|
|
135
|
+
queue.push(item);
|
|
136
|
+
pump();
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
return {
|
|
140
|
+
execute,
|
|
141
|
+
async close() {
|
|
142
|
+
closed = true;
|
|
143
|
+
for (const item of queue.splice(0)) finish(item, failure("Renderer pool is closed."));
|
|
144
|
+
for (const slot of slots) retire(slot, "Renderer pool is closed.");
|
|
145
|
+
await Promise.all(terminations);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
var isolatedExecute = createExecutorPool().execute;
|
|
150
|
+
|
|
151
|
+
export {
|
|
152
|
+
createExecutorPool,
|
|
153
|
+
isolatedExecute
|
|
154
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MAX_REPLY
|
|
3
|
+
} from "./chunk-7I3ZJGJF.js";
|
|
4
|
+
|
|
5
|
+
// src/replies.ts
|
|
6
|
+
var envelope = (result) => ({
|
|
7
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
8
|
+
structuredContent: result,
|
|
9
|
+
...result.ok === false ? { isError: true } : {}
|
|
10
|
+
});
|
|
11
|
+
function reply(result) {
|
|
12
|
+
const response = envelope(result);
|
|
13
|
+
if (new TextEncoder().encode(JSON.stringify(response)).length <= MAX_REPLY) return response;
|
|
14
|
+
return envelope({
|
|
15
|
+
ok: false,
|
|
16
|
+
error: {
|
|
17
|
+
message: "Reply exceeds the MCP output limit. Reduce the design or render locally with the KerfScript package."
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function page(text, offset, length = 12e3) {
|
|
22
|
+
const insidePair = (i) => i > 0 && /[\uD800-\uDBFF]/.test(text[i - 1] ?? "") && /[\uDC00-\uDFFF]/.test(text[i] ?? "");
|
|
23
|
+
const start = insidePair(offset) ? offset - 1 : offset;
|
|
24
|
+
let end = Math.min(start + length, text.length);
|
|
25
|
+
if (insidePair(end)) end--;
|
|
26
|
+
return { text: text.slice(start, end), nextOffset: end < text.length ? end : null };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
reply,
|
|
31
|
+
page
|
|
32
|
+
};
|
package/dist/execute.js
ADDED
package/dist/isolated.js
ADDED
package/dist/replies.js
ADDED
package/dist/runner.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
execute
|
|
3
|
+
} from "./chunk-6NSCAH6P.js";
|
|
4
|
+
import "./chunk-7I3ZJGJF.js";
|
|
5
|
+
import "./chunk-IY7POWTF.js";
|
|
6
|
+
|
|
7
|
+
// src/runner.ts
|
|
8
|
+
import { parentPort } from "node:worker_threads";
|
|
9
|
+
parentPort.on("message", (job) => parentPort.postMessage(execute(job)));
|
|
10
|
+
parentPort.postMessage({ ready: true });
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
handleRequest,
|
|
3
|
+
worker_default
|
|
4
|
+
} from "./chunk-43YRASDL.js";
|
|
5
|
+
import {
|
|
6
|
+
spend
|
|
7
|
+
} from "./chunk-O5LBJLFO.js";
|
|
8
|
+
import "./chunk-JUDNQ5QA.js";
|
|
9
|
+
import "./chunk-6NSCAH6P.js";
|
|
10
|
+
import "./chunk-Z46EXYJU.js";
|
|
11
|
+
import "./chunk-7I3ZJGJF.js";
|
|
12
|
+
import "./chunk-IY7POWTF.js";
|
|
13
|
+
|
|
14
|
+
// src/service.ts
|
|
15
|
+
import { DurableObject, WorkerEntrypoint } from "cloudflare:workers";
|
|
16
|
+
var KerfScriptService = class extends WorkerEntrypoint {
|
|
17
|
+
fetchForCaller(request, caller) {
|
|
18
|
+
if (typeof caller !== "string" || !caller.trim())
|
|
19
|
+
return new Response("A stable caller identity is required.", { status: 400 });
|
|
20
|
+
return handleRequest(request, this.env, caller);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var DailyBudget = class extends DurableObject {
|
|
24
|
+
spend(pool, client) {
|
|
25
|
+
return spend(
|
|
26
|
+
this.ctx.storage,
|
|
27
|
+
client,
|
|
28
|
+
Number(this.env.DAILY_CLIENT_LIMIT),
|
|
29
|
+
Number(
|
|
30
|
+
pool === "service" ? this.env.SERVICE_DAILY_REQUEST_LIMIT : this.env.DAILY_REQUEST_LIMIT
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
export {
|
|
36
|
+
DailyBudget,
|
|
37
|
+
KerfScriptService,
|
|
38
|
+
worker_default as default
|
|
39
|
+
};
|
package/dist/stdio.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createKerfScriptServer
|
|
4
|
+
} from "./chunk-JUDNQ5QA.js";
|
|
5
|
+
import {
|
|
6
|
+
isolatedExecute
|
|
7
|
+
} from "./chunk-T5JFV7HE.js";
|
|
8
|
+
import "./chunk-Z46EXYJU.js";
|
|
9
|
+
import "./chunk-7I3ZJGJF.js";
|
|
10
|
+
import "./chunk-IY7POWTF.js";
|
|
11
|
+
|
|
12
|
+
// src/stdio.ts
|
|
13
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
14
|
+
await createKerfScriptServer(isolatedExecute).connect(new StdioServerTransport());
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type Pool = 'public' | 'service';
|
|
2
|
+
export type Spend = 'ok' | 'client' | 'total';
|
|
3
|
+
export interface BudgetStorage {
|
|
4
|
+
get<T>(keys: string[]): Promise<Map<string, T>>;
|
|
5
|
+
put<T>(entries: Record<string, T>): Promise<void>;
|
|
6
|
+
deleteAll(): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare const secondsToMidnight: (now?: number) => number;
|
|
9
|
+
/**
|
|
10
|
+
* Counts one request against a client's and the service's allowance for the UTC
|
|
11
|
+
* day. A Durable Object runs this one request at a time. Limits that are not
|
|
12
|
+
* numbers refuse every request, so a configuration mistake cannot remove the cap.
|
|
13
|
+
*/
|
|
14
|
+
export declare function spend(storage: BudgetStorage, client: string, clientLimit: number, totalLimit: number, now?: number): Promise<Spend>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Executor } from './schema.js';
|
|
2
|
+
/** Create a pool per host or tenant. Idle workers do not keep Node running. */
|
|
3
|
+
export declare function createExecutorPool({ size, maxQueue, timeoutMs, queueTimeoutMs, startupTimeoutMs, workerUrl, }?: {
|
|
4
|
+
size?: number | undefined;
|
|
5
|
+
maxQueue?: number | undefined;
|
|
6
|
+
timeoutMs?: number | undefined;
|
|
7
|
+
queueTimeoutMs?: number | undefined;
|
|
8
|
+
startupTimeoutMs?: number | undefined;
|
|
9
|
+
workerUrl?: URL | undefined;
|
|
10
|
+
}): {
|
|
11
|
+
execute: Executor;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
export declare const isolatedExecute: Executor;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Result } from './schema.js';
|
|
2
|
+
export declare function reply(result: Result): {
|
|
3
|
+
isError?: boolean | undefined;
|
|
4
|
+
content: {
|
|
5
|
+
type: "text";
|
|
6
|
+
text: string;
|
|
7
|
+
}[];
|
|
8
|
+
structuredContent: Result;
|
|
9
|
+
};
|
|
10
|
+
export declare function page(text: string, offset: number, length?: number): {
|
|
11
|
+
text: string;
|
|
12
|
+
nextOffset: number | null;
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const MAX_SOURCE = 64000;
|
|
3
|
+
export declare const MAX_REPLY = 1000000;
|
|
4
|
+
export declare const sourceSchema: z.ZodString;
|
|
5
|
+
export declare const renderSchema: z.ZodObject<{
|
|
6
|
+
source: z.ZodString;
|
|
7
|
+
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean, z.ZodArray<z.ZodNumber>]>>>;
|
|
8
|
+
libraries: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
9
|
+
format: z.ZodDefault<z.ZodEnum<{
|
|
10
|
+
svg: "svg";
|
|
11
|
+
dxf: "dxf";
|
|
12
|
+
}>>;
|
|
13
|
+
sheet: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
14
|
+
kerf: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
gap: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
margin: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
layout: z.ZodDefault<z.ZodEnum<{
|
|
18
|
+
pack: "pack";
|
|
19
|
+
none: "none";
|
|
20
|
+
}>>;
|
|
21
|
+
}, z.core.$strict>;
|
|
22
|
+
export type RenderInput = z.infer<typeof renderSchema>;
|
|
23
|
+
export type Job = {
|
|
24
|
+
operation: 'render';
|
|
25
|
+
input: RenderInput;
|
|
26
|
+
} | {
|
|
27
|
+
operation: 'parameters';
|
|
28
|
+
source: string;
|
|
29
|
+
};
|
|
30
|
+
export type Result = {
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
};
|
|
33
|
+
export type Executor = (job: Job, signal?: AbortSignal) => Promise<Result>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
|
|
2
|
+
import { type Pool } from './budget.js';
|
|
3
|
+
export { default } from './worker.js';
|
|
4
|
+
export declare class KerfScriptService extends WorkerEntrypoint<Env> {
|
|
5
|
+
fetchForCaller(request: Request, caller: string): Response | Promise<Response>;
|
|
6
|
+
}
|
|
7
|
+
export declare class DailyBudget extends DurableObject<Env> {
|
|
8
|
+
spend(pool: Pool, client: string): Promise<import("./budget.js").Spend>;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { type Executor } from './schema.js';
|
|
3
|
+
/** Register on an existing MyLaserTools McpServer. The host supplies isolated execution. */
|
|
4
|
+
export declare function registerKerfScriptTools(server: McpServer, execute: Executor): void;
|
|
5
|
+
export declare function createKerfScriptServer(execute: Executor): McpServer;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The address a public client is limited by. One IPv6 subscriber usually holds a
|
|
3
|
+
* whole /64, so its addresses share one allowance. An IPv4 address written as
|
|
4
|
+
* IPv6 counts as that IPv4 address.
|
|
5
|
+
*/
|
|
6
|
+
export declare function clientAddress(ip: string): string;
|
|
7
|
+
export declare function handleRequest(request: Request, env: Env, caller?: string): Promise<Response>;
|
|
8
|
+
declare const _default: {
|
|
9
|
+
fetch: (request: Request<unknown, IncomingRequestCfProperties<unknown>>, env: Env) => Promise<Response>;
|
|
10
|
+
};
|
|
11
|
+
export default _default;
|
package/dist/worker.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clientAddress,
|
|
3
|
+
handleRequest,
|
|
4
|
+
worker_default
|
|
5
|
+
} from "./chunk-43YRASDL.js";
|
|
6
|
+
import "./chunk-O5LBJLFO.js";
|
|
7
|
+
import "./chunk-JUDNQ5QA.js";
|
|
8
|
+
import "./chunk-6NSCAH6P.js";
|
|
9
|
+
import "./chunk-Z46EXYJU.js";
|
|
10
|
+
import "./chunk-7I3ZJGJF.js";
|
|
11
|
+
import "./chunk-IY7POWTF.js";
|
|
12
|
+
export {
|
|
13
|
+
clientAddress,
|
|
14
|
+
worker_default as default,
|
|
15
|
+
handleRequest
|
|
16
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mylasertools/kerfscript-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "KerfScript tools for building parametric laser-cutting generators: documentation, examples, parameters and SVG/DXF rendering.",
|
|
5
|
+
"mcpName": "com.mylasertools/kerfscript",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "AGPL-3.0-only",
|
|
8
|
+
"author": "MyLaserTools",
|
|
9
|
+
"homepage": "https://kerfscript.mylasertools.com/docs/mcp/",
|
|
10
|
+
"bugs": "https://github.com/mylasertools/kerfscript/issues",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"mcp",
|
|
13
|
+
"mcp-server",
|
|
14
|
+
"model-context-protocol",
|
|
15
|
+
"kerfscript",
|
|
16
|
+
"laser-cutting",
|
|
17
|
+
"parametric",
|
|
18
|
+
"svg",
|
|
19
|
+
"dxf",
|
|
20
|
+
"generator"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/mylasertools/kerfscript.git",
|
|
25
|
+
"directory": "mcp"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public",
|
|
29
|
+
"registry": "https://registry.npmjs.org/"
|
|
30
|
+
},
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/types/src/tools.d.ts",
|
|
34
|
+
"default": "./dist/tools.js"
|
|
35
|
+
},
|
|
36
|
+
"./node": {
|
|
37
|
+
"types": "./dist/types/src/isolated.d.ts",
|
|
38
|
+
"default": "./dist/isolated.js"
|
|
39
|
+
},
|
|
40
|
+
"./execute": {
|
|
41
|
+
"types": "./dist/types/src/execute.d.ts",
|
|
42
|
+
"default": "./dist/execute.js"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"bin": {
|
|
46
|
+
"kerfscript-mcp": "dist/stdio.js"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist",
|
|
50
|
+
"README.md",
|
|
51
|
+
"LICENSE",
|
|
52
|
+
"THIRD-PARTY-NOTICES.md",
|
|
53
|
+
"OFL.txt"
|
|
54
|
+
],
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=20"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "node scripts/build.mjs",
|
|
60
|
+
"test": "node --test test/*.test.mjs",
|
|
61
|
+
"check": "npm run build && npm run types && tsc --declaration --emitDeclarationOnly --noEmit false --outDir dist/types && npm test",
|
|
62
|
+
"dev": "wrangler dev",
|
|
63
|
+
"types": "wrangler types",
|
|
64
|
+
"deploy:check": "wrangler deploy --dry-run",
|
|
65
|
+
"prepack": "npm run check"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"@modelcontextprotocol/sdk": "1.32.2",
|
|
69
|
+
"zod": "4.6.7"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@types/node": "20.19.43",
|
|
73
|
+
"esbuild": "0.25.12",
|
|
74
|
+
"typescript": "5.9.3",
|
|
75
|
+
"wrangler": "4.156.0"
|
|
76
|
+
}
|
|
77
|
+
}
|