c64bridge 0.8.1 → 0.9.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/.github/prompts/steer.prompt.md +55 -0
- package/AGENTS.md +9 -7
- package/README.md +192 -154
- package/data/embeddings_asm.json +1 -1
- package/data/embeddings_basic.json +1 -1
- package/data/embeddings_hardware.json +1 -1
- package/data/embeddings_mixed.json +1 -1
- package/data/embeddings_other.json +1 -1
- package/data/graphics/petscii-style-guide.md +4 -4
- package/data/graphics/sprite-charset-best-practices.md +9 -9
- package/data/vice/vice-binary-monitor-spec.md +938 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/c64Client.js +76 -2
- package/dist/device.js +129 -13
- package/dist/mcp-server.js +1 -1
- package/dist/prompts/registry.js +27 -25
- package/dist/rag/indexer.js +18 -8
- package/dist/rag/knowledgeIndex.js +112 -79
- package/dist/rag/resourceUris.js +93 -0
- package/dist/sidwaveCompiler.js +1 -1
- package/dist/{assemblyConverter.js → tools/assember.js} +10 -1
- package/dist/tools/audio.js +11 -11
- package/dist/{basicConverter.js → tools/basicTokenizer.js} +1 -1
- package/dist/tools/debug.js +159 -6
- package/dist/tools/developer.js +13 -13
- package/dist/tools/disassembler.js +478 -0
- package/dist/tools/graphics.js +10 -10
- package/dist/tools/input.js +338 -0
- package/dist/tools/machineControl.js +5 -5
- package/dist/tools/memory.js +336 -12
- package/dist/tools/meta/index.js +1 -1
- package/dist/tools/printer.js +11 -12
- package/dist/tools/programRunners.js +61 -22
- package/dist/tools/rag.js +9 -9
- package/dist/tools/registry/batch.js +167 -0
- package/dist/tools/registry/config.js +1 -1
- package/dist/tools/registry/disk.js +1 -1
- package/dist/tools/registry/drive.js +1 -1
- package/dist/tools/registry/extract.js +1 -1
- package/dist/tools/registry/graphics.js +102 -2
- package/dist/tools/registry/index.js +4 -0
- package/dist/tools/registry/input.js +2 -0
- package/dist/tools/registry/memory.js +62 -2
- package/dist/tools/registry/platform.js +1 -1
- package/dist/tools/registry/printer.js +1 -1
- package/dist/tools/registry/program.js +1 -1
- package/dist/tools/registry/rag.js +1 -1
- package/dist/tools/registry/sound.js +1 -1
- package/dist/tools/registry/stream.js +1 -1
- package/dist/tools/registry/system.js +1 -1
- package/dist/tools/schema.js +4 -5
- package/dist/tools/storage.js +15 -15
- package/dist/tools/streaming.js +3 -3
- package/dist/tools/symbolRegistry.js +49 -0
- package/dist/tools/types.js +56 -4
- package/dist/tools/vice.js +2 -5
- package/dist/vice/process.js +120 -2
- package/dist/vice/readiness.js +35 -0
- package/dist/vice/smokeOptions.js +44 -0
- package/dist/vice/viceClient.js +5 -1
- package/dist/viceRunner.js +2 -0
- package/doc/plans/prompts/README.md +7 -7
- package/mcp/prompts.json +42 -59
- package/mcp/protocol-examples.json +2 -2
- package/mcp/resources.json +179 -166
- package/mcp/schemas/c64_batch.schema.json +53 -0
- package/mcp/schemas/c64_config.schema.json +525 -283
- package/mcp/schemas/c64_debug.schema.json +763 -304
- package/mcp/schemas/c64_disk.schema.json +499 -243
- package/mcp/schemas/c64_drive.schema.json +165 -90
- package/mcp/schemas/c64_extract.schema.json +533 -274
- package/mcp/schemas/c64_graphics.schema.json +607 -295
- package/mcp/schemas/c64_input.schema.json +136 -0
- package/mcp/schemas/c64_memory.schema.json +637 -128
- package/mcp/schemas/c64_printer.schema.json +393 -196
- package/mcp/schemas/c64_program.schema.json +699 -340
- package/mcp/schemas/c64_rag.schema.json +100 -54
- package/mcp/schemas/c64_select_backend.schema.json +49 -23
- package/mcp/schemas/c64_sound.schema.json +1092 -577
- package/mcp/schemas/c64_stream.schema.json +89 -47
- package/mcp/schemas/c64_system.schema.json +351 -185
- package/mcp/schemas/c64_vice.schema.json +85 -47
- package/mcp/server.json +1 -1
- package/mcp/tools.json +7299 -3346
- package/mcp.json +3 -3
- package/package.json +17 -14
- package/scripts/fetch-external-sources.mjs +1 -2
- package/scripts/run-coverage.mjs +33 -1
- package/scripts/run-tests.mjs +2 -2
- package/scripts/run-tests.ts +275 -52
- package/scripts/update-readme.ts +132 -3
- package/server.json +2 -2
package/dist/vice/process.js
CHANGED
|
@@ -3,10 +3,37 @@ import fs from "node:fs";
|
|
|
3
3
|
import net from "node:net";
|
|
4
4
|
import { createOutputTailCapture, getDiagnosticsSessionInfo, writeDiagnosticEvent } from "../diagnostics.js";
|
|
5
5
|
const DEFAULT_DISPLAY = ":99";
|
|
6
|
+
function hasDisplayArtifacts(display) {
|
|
7
|
+
const match = /^:([0-9]+)$/.exec(display.trim());
|
|
8
|
+
if (!match) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
const displayNumber = match[1];
|
|
12
|
+
return fs.existsSync(`/tmp/.X11-unix/X${displayNumber}`) || fs.existsSync(`/tmp/.X${displayNumber}-lock`);
|
|
13
|
+
}
|
|
14
|
+
export function resolveXvfbDisplayForLaunch(display) {
|
|
15
|
+
const explicitDisplay = process.env.VICE_XVFB_DISPLAY?.trim();
|
|
16
|
+
if (explicitDisplay) {
|
|
17
|
+
return explicitDisplay;
|
|
18
|
+
}
|
|
19
|
+
if (display !== DEFAULT_DISPLAY || !hasDisplayArtifacts(display)) {
|
|
20
|
+
return display;
|
|
21
|
+
}
|
|
22
|
+
const baseDisplay = Number.parseInt(display.slice(1), 10);
|
|
23
|
+
for (let candidate = baseDisplay + 1; candidate < baseDisplay + 100; candidate += 1) {
|
|
24
|
+
const candidateDisplay = `:${candidate}`;
|
|
25
|
+
if (!hasDisplayArtifacts(candidateDisplay)) {
|
|
26
|
+
return candidateDisplay;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return display;
|
|
30
|
+
}
|
|
6
31
|
export function delay(ms) {
|
|
7
32
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
8
33
|
}
|
|
9
34
|
function hasGraphicalSession() {
|
|
35
|
+
if (process.platform === "darwin" || process.platform === "win32")
|
|
36
|
+
return true;
|
|
10
37
|
return configuredDisplay() !== undefined || configuredWaylandDisplay() !== undefined;
|
|
11
38
|
}
|
|
12
39
|
function configuredDisplay() {
|
|
@@ -64,6 +91,53 @@ export async function waitForPort(host, port, timeoutMs = 4000) {
|
|
|
64
91
|
}
|
|
65
92
|
throw new Error(`Timeout waiting for VICE monitor at ${host}:${port}`);
|
|
66
93
|
}
|
|
94
|
+
async function sendResumeMonitorCommand(host, port, timeoutMs = 1500) {
|
|
95
|
+
const deadline = Date.now() + timeoutMs;
|
|
96
|
+
let lastError;
|
|
97
|
+
while (Date.now() < deadline) {
|
|
98
|
+
try {
|
|
99
|
+
await new Promise((resolve, reject) => {
|
|
100
|
+
const socket = net.connect({ host, port });
|
|
101
|
+
const cleanup = () => {
|
|
102
|
+
socket.removeAllListeners();
|
|
103
|
+
socket.destroy();
|
|
104
|
+
};
|
|
105
|
+
const packet = Buffer.alloc(11);
|
|
106
|
+
packet[0] = 0x02;
|
|
107
|
+
packet[1] = 0x02;
|
|
108
|
+
packet.writeUInt32LE(0, 2);
|
|
109
|
+
packet.writeUInt32LE(1, 6);
|
|
110
|
+
packet[10] = 0xaa;
|
|
111
|
+
socket.setTimeout(500, () => {
|
|
112
|
+
cleanup();
|
|
113
|
+
reject(new Error(`Timed out sending VICE monitor resume command to ${host}:${port}`));
|
|
114
|
+
});
|
|
115
|
+
socket.once("error", (error) => {
|
|
116
|
+
cleanup();
|
|
117
|
+
reject(error);
|
|
118
|
+
});
|
|
119
|
+
socket.once("connect", () => {
|
|
120
|
+
socket.write(packet, (error) => {
|
|
121
|
+
cleanup();
|
|
122
|
+
if (error) {
|
|
123
|
+
reject(error);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
resolve();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
lastError = error;
|
|
134
|
+
await delay(50);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
throw lastError instanceof Error
|
|
138
|
+
? lastError
|
|
139
|
+
: new Error(`Failed to resume VICE monitor at ${host}:${port}`);
|
|
140
|
+
}
|
|
67
141
|
async function waitForXvfb(display, timeoutMs = 5000) {
|
|
68
142
|
const match = /^:([0-9]+)/.exec(display.trim());
|
|
69
143
|
if (!match) {
|
|
@@ -113,7 +187,19 @@ export async function terminateProcess(child, signal = "SIGTERM", timeoutMs = 10
|
|
|
113
187
|
}
|
|
114
188
|
export async function startViceProcess(options) {
|
|
115
189
|
const debugEnabled = process.env.VICE_DEVICE_TEST_DEBUG === "1";
|
|
116
|
-
|
|
190
|
+
// When headless=true, skip Xvfb entirely and rely on VICE's own -headless flag (VICE 3.5+).
|
|
191
|
+
const useHeadless = options.headless === true || process.env.VICE_HEADLESS === "1";
|
|
192
|
+
let useXvfb;
|
|
193
|
+
let display;
|
|
194
|
+
if (useHeadless) {
|
|
195
|
+
useXvfb = false;
|
|
196
|
+
display = "";
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const probe = shouldUseXvfb(options.visible);
|
|
200
|
+
useXvfb = probe.useXvfb;
|
|
201
|
+
display = useXvfb ? resolveXvfbDisplayForLaunch(probe.display) : probe.display;
|
|
202
|
+
}
|
|
117
203
|
const viceEnv = { ...process.env };
|
|
118
204
|
let xvfb = null;
|
|
119
205
|
const xvfbOutput = createOutputTailCapture("xvfb");
|
|
@@ -123,6 +209,7 @@ export async function startViceProcess(options) {
|
|
|
123
209
|
directory: options.directory,
|
|
124
210
|
display,
|
|
125
211
|
extraArgs: options.extraArgs ?? [],
|
|
212
|
+
headless: useHeadless,
|
|
126
213
|
host: options.host,
|
|
127
214
|
port: options.port,
|
|
128
215
|
useXvfb,
|
|
@@ -157,12 +244,14 @@ export async function startViceProcess(options) {
|
|
|
157
244
|
});
|
|
158
245
|
viceEnv.DISPLAY = display;
|
|
159
246
|
await waitForXvfb(display);
|
|
247
|
+
await delay(300);
|
|
160
248
|
}
|
|
161
249
|
const args = [
|
|
162
250
|
"-binarymonitor",
|
|
163
251
|
"-binarymonitoraddress", `${options.host}:${options.port}`,
|
|
164
252
|
"-sounddev", "dummy",
|
|
165
253
|
"-config", "/dev/null",
|
|
254
|
+
...(useHeadless ? ["-headless"] : []),
|
|
166
255
|
...(options.directory ? ["-directory", options.directory] : []),
|
|
167
256
|
...(options.extraArgs ?? []),
|
|
168
257
|
];
|
|
@@ -216,7 +305,8 @@ export async function startViceProcess(options) {
|
|
|
216
305
|
child.once("exit", onExit);
|
|
217
306
|
child.once("error", onError);
|
|
218
307
|
waitForPort(options.host, options.port)
|
|
219
|
-
.then(() => {
|
|
308
|
+
.then(async () => {
|
|
309
|
+
await sendResumeMonitorCommand(options.host, options.port);
|
|
220
310
|
if (debugEnabled) {
|
|
221
311
|
console.error("[vice-process] monitor port is ready", { host: options.host, port: options.port });
|
|
222
312
|
}
|
|
@@ -293,15 +383,43 @@ export async function startViceProcess(options) {
|
|
|
293
383
|
});
|
|
294
384
|
return { host: options.host, port: options.port, process: child, stop };
|
|
295
385
|
}
|
|
386
|
+
function isIgnorableSocketDirError(error) {
|
|
387
|
+
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
const code = String(error.code ?? "");
|
|
391
|
+
return code === "EACCES" || code === "EPERM" || code === "EROFS" || code === "EEXIST";
|
|
392
|
+
}
|
|
296
393
|
export function ensureXvfbSocketDir(debugEnabled) {
|
|
297
394
|
const socketDir = "/tmp/.X11-unix";
|
|
298
395
|
try {
|
|
299
396
|
if (!fs.existsSync(socketDir)) {
|
|
300
397
|
fs.mkdirSync(socketDir, { mode: 0o1777 });
|
|
301
398
|
}
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
if (isIgnorableSocketDirError(error)) {
|
|
402
|
+
if (debugEnabled) {
|
|
403
|
+
console.error("[vice-process] unable to create Xvfb socket dir; continuing", error);
|
|
404
|
+
}
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
writeDiagnosticEvent("xvfb_socket_dir_failed", { socketDir, error });
|
|
408
|
+
if (debugEnabled) {
|
|
409
|
+
console.error("[vice-process] failed to prepare Xvfb socket dir", error);
|
|
410
|
+
}
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
302
414
|
fs.chmodSync(socketDir, 0o1777);
|
|
303
415
|
}
|
|
304
416
|
catch (error) {
|
|
417
|
+
if (isIgnorableSocketDirError(error)) {
|
|
418
|
+
if (debugEnabled) {
|
|
419
|
+
console.error("[vice-process] unable to chmod Xvfb socket dir; continuing", error);
|
|
420
|
+
}
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
305
423
|
writeDiagnosticEvent("xvfb_socket_dir_failed", { socketDir, error });
|
|
306
424
|
if (debugEnabled) {
|
|
307
425
|
console.error("[vice-process] failed to prepare Xvfb socket dir", error);
|
package/dist/vice/readiness.js
CHANGED
|
@@ -30,6 +30,41 @@ export async function waitForScreenPattern(bm, pattern, timeoutMs, tickMs = 50,
|
|
|
30
30
|
await exitMonitorIfNeeded(bm);
|
|
31
31
|
return idx;
|
|
32
32
|
}
|
|
33
|
+
export async function waitForStableScreenPattern(bm, pattern, timeoutMs, tickMs = 50, stableReads = 2, onRead, between) {
|
|
34
|
+
const requiredStableReads = Math.max(1, stableReads);
|
|
35
|
+
const start = nowNs();
|
|
36
|
+
let idx = -1;
|
|
37
|
+
let stableIdx = -1;
|
|
38
|
+
let consecutiveMatches = 0;
|
|
39
|
+
while (msSince(start) < timeoutMs) {
|
|
40
|
+
const t = nowNs();
|
|
41
|
+
const screen = await bm.memGet(0x0400, 0x0400 + 999);
|
|
42
|
+
onRead?.("bm_read_screen", t);
|
|
43
|
+
idx = screen.indexOf(pattern);
|
|
44
|
+
if (idx >= 0) {
|
|
45
|
+
if (idx === stableIdx) {
|
|
46
|
+
consecutiveMatches += 1;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
stableIdx = idx;
|
|
50
|
+
consecutiveMatches = 1;
|
|
51
|
+
}
|
|
52
|
+
if (consecutiveMatches >= requiredStableReads) {
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
stableIdx = -1;
|
|
58
|
+
consecutiveMatches = 0;
|
|
59
|
+
}
|
|
60
|
+
await exitMonitorIfNeeded(bm);
|
|
61
|
+
if (between)
|
|
62
|
+
await between();
|
|
63
|
+
await new Promise((r) => setTimeout(r, Math.max(1, tickMs)));
|
|
64
|
+
}
|
|
65
|
+
await exitMonitorIfNeeded(bm);
|
|
66
|
+
return consecutiveMatches >= requiredStableReads ? idx : -1;
|
|
67
|
+
}
|
|
33
68
|
/** Wait until any non-blank (non-0x00/0x20) character appears on the text screen. */
|
|
34
69
|
export async function waitForAnyScreenText(bm, timeoutMs, tickMs = 50, onRead, between) {
|
|
35
70
|
const start = nowNs();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const TRUE_VALUES = new Set(["1", "true", "yes", "on"]);
|
|
2
|
+
const FALSE_VALUES = new Set(["0", "false", "no", "off"]);
|
|
3
|
+
function parseVicePort(value) {
|
|
4
|
+
const normalized = value?.trim();
|
|
5
|
+
if (!normalized) {
|
|
6
|
+
return { configuredPort: 6502, hasExplicitPort: false };
|
|
7
|
+
}
|
|
8
|
+
const parsed = Number(normalized);
|
|
9
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65535) {
|
|
10
|
+
return { configuredPort: 6502, hasExplicitPort: false };
|
|
11
|
+
}
|
|
12
|
+
return { configuredPort: parsed, hasExplicitPort: true };
|
|
13
|
+
}
|
|
14
|
+
export function parseEnvBoolean(value) {
|
|
15
|
+
const normalized = value?.trim().toLowerCase();
|
|
16
|
+
if (!normalized) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
if (TRUE_VALUES.has(normalized)) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if (FALSE_VALUES.has(normalized)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
export function resolveViceSmokeOptions(env = process.env, argv = process.argv.slice(2)) {
|
|
28
|
+
const visibleDemo = argv.includes("--visible-demo") || parseEnvBoolean(env.VICE_VISIBLE_DEMO) === true;
|
|
29
|
+
const useMock = String(env.VICE_TEST_TARGET ?? "").trim().toLowerCase() === "mock";
|
|
30
|
+
const { configuredPort, hasExplicitPort } = parseVicePort(env.VICE_PORT);
|
|
31
|
+
const visible = visibleDemo || parseEnvBoolean(env.VICE_VISIBLE) === true;
|
|
32
|
+
const keepOpen = visibleDemo || parseEnvBoolean(env.VICE_KEEP_OPEN) === true;
|
|
33
|
+
const warpSetting = parseEnvBoolean(env.VICE_WARP);
|
|
34
|
+
return {
|
|
35
|
+
useMock,
|
|
36
|
+
configuredPort,
|
|
37
|
+
hasExplicitPort,
|
|
38
|
+
visible,
|
|
39
|
+
keepOpen,
|
|
40
|
+
warp: useMock ? true : visibleDemo ? false : warpSetting ?? true,
|
|
41
|
+
display: env.DISPLAY || ":99",
|
|
42
|
+
visibleDemo,
|
|
43
|
+
};
|
|
44
|
+
}
|
package/dist/vice/viceClient.js
CHANGED
|
@@ -9,6 +9,9 @@ export class ViceClient {
|
|
|
9
9
|
this.pending = new Map();
|
|
10
10
|
this.closing = false;
|
|
11
11
|
}
|
|
12
|
+
setUnsolicitedHandler(handler) {
|
|
13
|
+
this.onUnsolicitedHandler = handler;
|
|
14
|
+
}
|
|
12
15
|
async connect(port, host = "127.0.0.1") {
|
|
13
16
|
this.socket = net.connect({ host, port });
|
|
14
17
|
this.closing = false;
|
|
@@ -77,7 +80,8 @@ export class ViceClient {
|
|
|
77
80
|
const err = frame[7];
|
|
78
81
|
const reqId = frame.readUInt32LE(8);
|
|
79
82
|
if (reqId === 0xffffffff) {
|
|
80
|
-
|
|
83
|
+
this.onUnsolicitedHandler?.(responseType, frame);
|
|
84
|
+
continue;
|
|
81
85
|
}
|
|
82
86
|
const pending = this.pending.get(reqId);
|
|
83
87
|
if (!pending) {
|
package/dist/viceRunner.js
CHANGED
|
@@ -65,6 +65,8 @@ function which(binary) {
|
|
|
65
65
|
return null;
|
|
66
66
|
}
|
|
67
67
|
function shouldUseXvfb() {
|
|
68
|
+
if (process.platform === "darwin" || process.platform === "win32")
|
|
69
|
+
return false;
|
|
68
70
|
if (process.env.FORCE_XVFB === "1")
|
|
69
71
|
return true;
|
|
70
72
|
const ciValue = (process.env.CI || "").toLowerCase();
|
|
@@ -27,13 +27,13 @@ suite can assert expectations in upcoming steps.
|
|
|
27
27
|
|
|
28
28
|
| Family | Baseline Resources (URIs) | Rationale |
|
|
29
29
|
| --- | --- | --- |
|
|
30
|
-
| `basic-program` | `c64://
|
|
31
|
-
| `assembly-program` | `c64://
|
|
32
|
-
| `sid-music` | `c64://
|
|
33
|
-
| `graphics-demo` | `c64://
|
|
34
|
-
| `printer-job` | `c64://
|
|
35
|
-
| `memory-debug` | `c64://
|
|
36
|
-
| `drive-manager` | `c64://
|
|
30
|
+
| `basic-program` | `c64://basic/spec`, `c64://guide/bootstrap`, `c64://guide/index` | Reinforce BASIC token rules, PETSCII gotchas, workflow expectations. |
|
|
31
|
+
| `assembly-program` | `c64://assembly/6510-spec`, `c64://guide/bootstrap`, `c64://graphics/vic/spec`, `c64://sound/sid/spec` | Provide opcode tables, IRQ setup, VIC/SID register references. |
|
|
32
|
+
| `sid-music` | `c64://sound/sid/spec`, `c64://sound/sidwave/spec`, `c64://sound/sid/file-format` | Supply register map, SIDWAVE format, SID file metadata. |
|
|
33
|
+
| `graphics-demo` | `c64://graphics/vic/spec`, `c64://guide/bootstrap` | Cover VIC mode bits, raster constraints, general workflow guidance. |
|
|
34
|
+
| `printer-job` | `c64://printer/spec`, `c64://printer/commodore/text`, `c64://printer/prompt-guide` | Document PETSCII vs ESC/P workflows, sample templates, and safety checks. |
|
|
35
|
+
| `memory-debug` | `c64://guide/bootstrap`, `c64://assembly/6510-spec`, `c64://guide/index` | Highlight addressing safeguards, workflow rules, and knowledge map summaries. |
|
|
36
|
+
| `drive-manager` | `c64://guide/bootstrap` | Ensure awareness of system-wide safety rules before altering drives. |
|
|
37
37
|
|
|
38
38
|
Notes:
|
|
39
39
|
|
package/mcp/prompts.json
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
"description": "Route ultra-fast hello-world and smoke-test requests to the canonical greeting skill.",
|
|
7
7
|
"_meta": {
|
|
8
8
|
"requiredResources": [
|
|
9
|
-
"c64://
|
|
10
|
-
"c64://
|
|
11
|
-
"c64://
|
|
9
|
+
"c64://guide/bootstrap",
|
|
10
|
+
"c64://guide/fast-paths",
|
|
11
|
+
"c64://guide/index"
|
|
12
12
|
],
|
|
13
13
|
"optionalResources": [],
|
|
14
14
|
"tools": [
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
"description": "Route bespoke Commodore BASIC v2 requests to the canonical BASIC skill.",
|
|
30
30
|
"_meta": {
|
|
31
31
|
"requiredResources": [
|
|
32
|
-
"c64://
|
|
33
|
-
"c64://
|
|
34
|
-
"c64://
|
|
32
|
+
"c64://basic/spec",
|
|
33
|
+
"c64://guide/bootstrap",
|
|
34
|
+
"c64://guide/index"
|
|
35
35
|
],
|
|
36
36
|
"optionalResources": [
|
|
37
|
-
"c64://
|
|
37
|
+
"c64://guide/fast-paths"
|
|
38
38
|
],
|
|
39
39
|
"tools": [
|
|
40
40
|
"c64_program",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"description": "Route quick visible demo requests to the cross-platform demo skill.",
|
|
54
54
|
"_meta": {
|
|
55
55
|
"requiredResources": [
|
|
56
|
-
"c64://
|
|
57
|
-
"c64://
|
|
58
|
-
"c64://
|
|
56
|
+
"c64://guide/bootstrap",
|
|
57
|
+
"c64://guide/fast-paths",
|
|
58
|
+
"c64://guide/index"
|
|
59
59
|
],
|
|
60
60
|
"optionalResources": [],
|
|
61
61
|
"tools": [
|
|
@@ -75,12 +75,12 @@
|
|
|
75
75
|
"description": "Route quick recognizable tune requests to the SID music skill.",
|
|
76
76
|
"_meta": {
|
|
77
77
|
"requiredResources": [
|
|
78
|
-
"c64://
|
|
79
|
-
"c64://
|
|
80
|
-
"c64://
|
|
78
|
+
"c64://sound/sid/spec",
|
|
79
|
+
"c64://sound/sidwave/spec",
|
|
80
|
+
"c64://guide/fast-paths"
|
|
81
81
|
],
|
|
82
82
|
"optionalResources": [
|
|
83
|
-
"c64://
|
|
83
|
+
"c64://sound/sid/best-practices"
|
|
84
84
|
],
|
|
85
85
|
"tools": [
|
|
86
86
|
"c64_sound"
|
|
@@ -100,24 +100,18 @@
|
|
|
100
100
|
"arguments": [
|
|
101
101
|
{
|
|
102
102
|
"name": "hardware",
|
|
103
|
-
"description": "Optional focus area for the routine (sid, vic, cia, or multi for combined work)."
|
|
104
|
-
"options": [
|
|
105
|
-
"sid",
|
|
106
|
-
"vic",
|
|
107
|
-
"cia",
|
|
108
|
-
"multi"
|
|
109
|
-
]
|
|
103
|
+
"description": "Optional focus area for the routine (sid, vic, cia, or multi for combined work)."
|
|
110
104
|
}
|
|
111
105
|
],
|
|
112
106
|
"_meta": {
|
|
113
107
|
"requiredResources": [
|
|
114
|
-
"c64://
|
|
115
|
-
"c64://
|
|
116
|
-
"c64://
|
|
117
|
-
"c64://
|
|
108
|
+
"c64://assembly/6510-spec",
|
|
109
|
+
"c64://graphics/vic/spec",
|
|
110
|
+
"c64://sound/sid/spec",
|
|
111
|
+
"c64://guide/bootstrap"
|
|
118
112
|
],
|
|
119
113
|
"optionalResources": [
|
|
120
|
-
"c64://
|
|
114
|
+
"c64://sound/sid/best-practices"
|
|
121
115
|
],
|
|
122
116
|
"tools": [
|
|
123
117
|
"c64_program",
|
|
@@ -143,13 +137,13 @@
|
|
|
143
137
|
"description": "Route SID playback and composition work to the canonical SID skill.",
|
|
144
138
|
"_meta": {
|
|
145
139
|
"requiredResources": [
|
|
146
|
-
"c64://
|
|
147
|
-
"c64://
|
|
148
|
-
"c64://
|
|
149
|
-
"c64://
|
|
140
|
+
"c64://sound/sid/spec",
|
|
141
|
+
"c64://sound/sidwave/spec",
|
|
142
|
+
"c64://sound/sid/file-format",
|
|
143
|
+
"c64://sound/sid/best-practices"
|
|
150
144
|
],
|
|
151
145
|
"optionalResources": [
|
|
152
|
-
"c64://
|
|
146
|
+
"c64://guide/fast-paths"
|
|
153
147
|
],
|
|
154
148
|
"tools": [
|
|
155
149
|
"c64_sound"
|
|
@@ -168,24 +162,18 @@
|
|
|
168
162
|
"arguments": [
|
|
169
163
|
{
|
|
170
164
|
"name": "mode",
|
|
171
|
-
"description": "Target VIC-II technique (text, multicolour, bitmap, or sprite)."
|
|
172
|
-
"options": [
|
|
173
|
-
"text",
|
|
174
|
-
"multicolour",
|
|
175
|
-
"bitmap",
|
|
176
|
-
"sprite"
|
|
177
|
-
]
|
|
165
|
+
"description": "Target VIC-II technique (text, multicolour, bitmap, or sprite)."
|
|
178
166
|
}
|
|
179
167
|
],
|
|
180
168
|
"_meta": {
|
|
181
169
|
"requiredResources": [
|
|
182
|
-
"c64://
|
|
183
|
-
"c64://
|
|
170
|
+
"c64://graphics/vic/spec",
|
|
171
|
+
"c64://guide/bootstrap"
|
|
184
172
|
],
|
|
185
173
|
"optionalResources": [
|
|
186
|
-
"c64://
|
|
187
|
-
"c64://
|
|
188
|
-
"c64://
|
|
174
|
+
"c64://assembly/6510-spec",
|
|
175
|
+
"c64://graphics/character-set",
|
|
176
|
+
"c64://graphics/petscii/style-guide"
|
|
189
177
|
],
|
|
190
178
|
"tools": [
|
|
191
179
|
"c64_program",
|
|
@@ -213,24 +201,19 @@
|
|
|
213
201
|
"arguments": [
|
|
214
202
|
{
|
|
215
203
|
"name": "printerType",
|
|
216
|
-
"description": "Select Commodore (device 4) or Epson FX workflow helpers."
|
|
217
|
-
"options": [
|
|
218
|
-
"commodore",
|
|
219
|
-
"epson"
|
|
220
|
-
]
|
|
204
|
+
"description": "Select Commodore (device 4) or Epson FX workflow helpers."
|
|
221
205
|
}
|
|
222
206
|
],
|
|
223
207
|
"_meta": {
|
|
224
208
|
"requiredResources": [
|
|
225
|
-
"c64://
|
|
226
|
-
"c64://
|
|
227
|
-
"c64://docs/printer/prompts"
|
|
209
|
+
"c64://printer/spec",
|
|
210
|
+
"c64://printer/prompt-guide"
|
|
228
211
|
],
|
|
229
212
|
"optionalResources": [
|
|
230
|
-
"c64://
|
|
231
|
-
"c64://
|
|
232
|
-
"c64://
|
|
233
|
-
"c64://
|
|
213
|
+
"c64://printer/commodore/text",
|
|
214
|
+
"c64://printer/commodore/bitmap",
|
|
215
|
+
"c64://printer/epson/text",
|
|
216
|
+
"c64://printer/epson/bitmap"
|
|
234
217
|
],
|
|
235
218
|
"tools": [
|
|
236
219
|
"c64_printer"
|
|
@@ -252,9 +235,9 @@
|
|
|
252
235
|
"description": "Route reversible memory inspection or patching work to the canonical memory skill.",
|
|
253
236
|
"_meta": {
|
|
254
237
|
"requiredResources": [
|
|
255
|
-
"c64://
|
|
256
|
-
"c64://
|
|
257
|
-
"c64://
|
|
238
|
+
"c64://guide/bootstrap",
|
|
239
|
+
"c64://assembly/6510-spec",
|
|
240
|
+
"c64://guide/index"
|
|
258
241
|
],
|
|
259
242
|
"optionalResources": [],
|
|
260
243
|
"tools": [
|
|
@@ -274,7 +257,7 @@
|
|
|
274
257
|
"description": "Route disk-image and drive-state requests to the canonical drive skill.",
|
|
275
258
|
"_meta": {
|
|
276
259
|
"requiredResources": [
|
|
277
|
-
"c64://
|
|
260
|
+
"c64://guide/bootstrap"
|
|
278
261
|
],
|
|
279
262
|
"optionalResources": [],
|
|
280
263
|
"tools": [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"protocolVersion": "2025-
|
|
2
|
+
"protocolVersion": "2025-11-25",
|
|
3
3
|
"examples": {
|
|
4
4
|
"initialize": {
|
|
5
5
|
"description": "Client initialization request sent immediately after connecting to the stdio MCP server.",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"id": 1,
|
|
9
9
|
"method": "initialize",
|
|
10
10
|
"params": {
|
|
11
|
-
"protocolVersion": "2025-
|
|
11
|
+
"protocolVersion": "2025-11-25",
|
|
12
12
|
"capabilities": {
|
|
13
13
|
"resources": {},
|
|
14
14
|
"tools": {},
|