@yali-engine/mcp 0.0.0-stage → 0.4.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/bin/yali-mcp.mjs +13 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +87 -0
- package/dist/main.js.map +1 -0
- package/dist/protocol.d.ts +53 -0
- package/dist/protocol.js +122 -0
- package/dist/protocol.js.map +1 -0
- package/dist/yali-tools.d.ts +45 -0
- package/dist/yali-tools.js +152 -0
- package/dist/yali-tools.js.map +1 -0
- package/package.json +28 -3
- package/README.md +0 -3
package/bin/yali-mcp.mjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The `yali-mcp` server. Workspace packages export TypeScript sources, which Node 22 loads
|
|
3
|
+
// only with --experimental-strip-types (ADR-0027), so this re-runs the server under that
|
|
4
|
+
// flag. stdin and stdout pass straight through: they carry the MCP protocol.
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
|
|
9
|
+
// In the workspace: the TypeScript source; published (no src): the built JS.
|
|
10
|
+
const source = fileURLToPath(new URL('../src/main.ts', import.meta.url));
|
|
11
|
+
const main = existsSync(source) ? source : fileURLToPath(new URL('../dist/main.js', import.meta.url));
|
|
12
|
+
const r = spawnSync(process.execPath, ['--experimental-strip-types', '--no-warnings', main, ...process.argv.slice(2)], { stdio: 'inherit' });
|
|
13
|
+
process.exit(r.status ?? 1);
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@yali-engine/mcp`: an MCP server that lets an agent drive a running Yali app (ADR-0029).
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* const tools = yaliTools({ traceDir: '.yali/traces', connect: () => openPage(url, 9224, { reuse: true }) });
|
|
6
|
+
* const server = new McpServer({ name: 'yali', version: '0.4.0' }, tools, (m) => process.stdout.write(m + '\n'));
|
|
7
|
+
*/
|
|
8
|
+
export { type Content, type McpTool, McpServer, PROTOCOL_VERSIONS, type ToolProvider, type ToolResult } from './protocol.ts';
|
|
9
|
+
export { type BridgeOptions, mcpName, type PageLike, yaliTools } from './yali-tools.ts';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@yali-engine/mcp`: an MCP server that lets an agent drive a running Yali app (ADR-0029).
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* const tools = yaliTools({ traceDir: '.yali/traces', connect: () => openPage(url, 9224, { reuse: true }) });
|
|
6
|
+
* const server = new McpServer({ name: 'yali', version: '0.4.0' }, tools, (m) => process.stdout.write(m + '\n'));
|
|
7
|
+
*/
|
|
8
|
+
export { McpServer, PROTOCOL_VERSIONS } from "./protocol.js";
|
|
9
|
+
export { mcpName, yaliTools } from "./yali-tools.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAA8B,SAAS,EAAE,iBAAiB,EAAsC,MAAM,eAAe,CAAC;AAC7H,OAAO,EAAsB,OAAO,EAAiB,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// `yali-mcp`: the MCP server over stdio (DESIGN.md §19, ADR-0029). stdout carries protocol
|
|
2
|
+
// messages only; diagnostics go to stderr.
|
|
3
|
+
//
|
|
4
|
+
// yali-mcp [--root dir] [--url http://localhost:3150/] [--cdp-port 9224] [--probe __yali]
|
|
5
|
+
//
|
|
6
|
+
// Register it with an agent, e.g. `claude mcp add yali -- node packages/mcp/bin/yali-mcp.mjs --root examples/first-pixels`.
|
|
7
|
+
import { spawn } from 'node:child_process';
|
|
8
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { tmpdir } from 'node:os';
|
|
10
|
+
import { createInterface } from 'node:readline';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { parseArgs } from 'node:util';
|
|
14
|
+
import { cdpPort, loadProject, openPage, pageUrl } from '@yali-engine/cli';
|
|
15
|
+
import { McpServer } from "./protocol.js";
|
|
16
|
+
import { yaliTools } from "./yali-tools.js";
|
|
17
|
+
const { values } = parseArgs({
|
|
18
|
+
args: process.argv.slice(2),
|
|
19
|
+
options: { root: { type: 'string' }, url: { type: 'string' }, 'cdp-port': { type: 'string' }, probe: { type: 'string' } },
|
|
20
|
+
});
|
|
21
|
+
const project = await loadProject(values.root);
|
|
22
|
+
const url = pageUrl(project, values.url, undefined);
|
|
23
|
+
const port = cdpPort(values['cdp-port']);
|
|
24
|
+
const log = (s) => process.stderr.write(`[yali-mcp] ${s}\n`);
|
|
25
|
+
// `run_headless` runs `yali headless` in a child process: the game's code then cannot hang
|
|
26
|
+
// or crash the server, and every run starts from fresh module state.
|
|
27
|
+
const cli = fileURLToPath(new URL('../../cli/bin/yali.mjs', import.meta.url));
|
|
28
|
+
const headless = project.config.headless
|
|
29
|
+
? (args) => new Promise((resolve, reject) => {
|
|
30
|
+
const argv = [cli, 'headless', '--root', project.root, '--json'];
|
|
31
|
+
if (args.frames !== undefined)
|
|
32
|
+
argv.push('--frames', String(args.frames));
|
|
33
|
+
if (args.seed !== undefined)
|
|
34
|
+
argv.push('--seed', String(args.seed));
|
|
35
|
+
if (args.query)
|
|
36
|
+
argv.push('--query', args.query);
|
|
37
|
+
if (args.expect)
|
|
38
|
+
argv.push('--expect', args.expect);
|
|
39
|
+
let dir = '';
|
|
40
|
+
if (args.recording !== undefined) {
|
|
41
|
+
dir = mkdtempSync(join(tmpdir(), 'yali-rec-'));
|
|
42
|
+
writeFileSync(join(dir, 'recording.json'), JSON.stringify(args.recording));
|
|
43
|
+
argv.push('--recording', join(dir, 'recording.json'));
|
|
44
|
+
}
|
|
45
|
+
const child = spawn(process.execPath, argv, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
46
|
+
let out = '';
|
|
47
|
+
child.stdout.on('data', (d) => (out += d));
|
|
48
|
+
child.on('close', () => {
|
|
49
|
+
if (dir)
|
|
50
|
+
rmSync(dir, { recursive: true, force: true });
|
|
51
|
+
try {
|
|
52
|
+
const env = JSON.parse(out);
|
|
53
|
+
if (env.ok)
|
|
54
|
+
resolve(env.result);
|
|
55
|
+
else
|
|
56
|
+
reject(Object.assign(new Error(env.error.message), { code: env.error.code, detail: env.error.message, fix: env.error.fix }));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
reject(new Error(`yali headless printed no JSON: ${out.slice(0, 500)}`));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
})
|
|
63
|
+
: undefined;
|
|
64
|
+
const tools = yaliTools({
|
|
65
|
+
headless,
|
|
66
|
+
probe: values.probe,
|
|
67
|
+
traceDir: join(project.root, '.yali', 'traces'),
|
|
68
|
+
log,
|
|
69
|
+
connect: async () => {
|
|
70
|
+
const page = await openPage(url, port, { reuse: true });
|
|
71
|
+
log(`attached to ${page.url} (CDP ${port})`);
|
|
72
|
+
return page;
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
const server = new McpServer({ name: 'yali', version: '0.4.0' }, tools, (m) => process.stdout.write(`${m}\n`));
|
|
76
|
+
log(`serving ${project.root} → ${url} over stdio`);
|
|
77
|
+
// Requests run concurrently (a slow screenshot does not hold up a ping); responses carry ids.
|
|
78
|
+
// On end of input, answer what is in flight first (a client may close its side right after
|
|
79
|
+
// its last request), then exit.
|
|
80
|
+
const inFlight = new Set();
|
|
81
|
+
createInterface({ input: process.stdin }).on('line', (line) => {
|
|
82
|
+
const p = server.receive(line).catch((e) => log(String(e)));
|
|
83
|
+
inFlight.add(p);
|
|
84
|
+
void p.finally(() => inFlight.delete(p));
|
|
85
|
+
});
|
|
86
|
+
process.stdin.on('end', () => void Promise.allSettled([...inFlight]).then(() => process.exit(0)));
|
|
87
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Protocol revisions this server speaks, newest first. */
|
|
2
|
+
export declare const PROTOCOL_VERSIONS: readonly ["2025-06-18", "2025-03-26", "2024-11-05"];
|
|
3
|
+
/** One content block of a tool result. */
|
|
4
|
+
export type Content = {
|
|
5
|
+
type: 'text';
|
|
6
|
+
text: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'image';
|
|
9
|
+
data: string;
|
|
10
|
+
mimeType: string;
|
|
11
|
+
};
|
|
12
|
+
/** What a tool returns. `isError` marks a failure the model should read and act on. */
|
|
13
|
+
export interface ToolResult {
|
|
14
|
+
content: Content[];
|
|
15
|
+
structuredContent?: Record<string, unknown>;
|
|
16
|
+
isError?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** A tool as MCP lists it. Names match `^[a-zA-Z0-9_-]{1,64}$` (what model APIs accept). */
|
|
19
|
+
export interface McpTool {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
inputSchema: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/** What the server asks of whoever provides the tools. */
|
|
25
|
+
export interface ToolProvider {
|
|
26
|
+
list(): Promise<McpTool[]>;
|
|
27
|
+
call(name: string, args: Record<string, unknown>, signal: AbortSignal): Promise<ToolResult>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* One MCP session. Feed it lines with `receive`; it writes responses and notifications
|
|
31
|
+
* through `send` (one JSON message per call).
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const server = new McpServer({ name: 'yali', version: '0.4.0' }, tools, (m) => process.stdout.write(m + '\n'));
|
|
35
|
+
* readline.createInterface({ input: process.stdin }).on('line', (l) => void server.receive(l));
|
|
36
|
+
*/
|
|
37
|
+
export declare class McpServer {
|
|
38
|
+
#private;
|
|
39
|
+
readonly info: {
|
|
40
|
+
name: string;
|
|
41
|
+
version: string;
|
|
42
|
+
};
|
|
43
|
+
/** The revision agreed in `initialize` (null before it). */
|
|
44
|
+
protocolVersion: string | null;
|
|
45
|
+
constructor(info: {
|
|
46
|
+
name: string;
|
|
47
|
+
version: string;
|
|
48
|
+
}, tools: ToolProvider, send: (message: string) => void);
|
|
49
|
+
/** Tells the client the tool list changed (it calls `tools/list` again). */
|
|
50
|
+
notifyToolsChanged(): void;
|
|
51
|
+
/** Handles one incoming line. Resolves when its response (if any) has been sent. */
|
|
52
|
+
receive(line: string): Promise<void>;
|
|
53
|
+
}
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// The Model Context Protocol, the part Yali serves: JSON-RPC 2.0 over newline-delimited
|
|
2
|
+
// stdio, `initialize`, `ping`, `tools/list`, `tools/call`, cancellation and
|
|
3
|
+
// `notifications/tools/list_changed`. Hand-rolled (ADR-0029): the official SDK measured 92
|
|
4
|
+
// packages and 16.4 MB for a surface this small.
|
|
5
|
+
/** Protocol revisions this server speaks, newest first. */
|
|
6
|
+
export const PROTOCOL_VERSIONS = ['2025-06-18', '2025-03-26', '2024-11-05'];
|
|
7
|
+
const PARSE_ERROR = -32700;
|
|
8
|
+
const INVALID_REQUEST = -32600;
|
|
9
|
+
const METHOD_NOT_FOUND = -32601;
|
|
10
|
+
const INVALID_PARAMS = -32602;
|
|
11
|
+
/**
|
|
12
|
+
* One MCP session. Feed it lines with `receive`; it writes responses and notifications
|
|
13
|
+
* through `send` (one JSON message per call).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const server = new McpServer({ name: 'yali', version: '0.4.0' }, tools, (m) => process.stdout.write(m + '\n'));
|
|
17
|
+
* readline.createInterface({ input: process.stdin }).on('line', (l) => void server.receive(l));
|
|
18
|
+
*/
|
|
19
|
+
export class McpServer {
|
|
20
|
+
info;
|
|
21
|
+
#tools;
|
|
22
|
+
#send;
|
|
23
|
+
#inflight = new Map();
|
|
24
|
+
#listed = null;
|
|
25
|
+
/** The revision agreed in `initialize` (null before it). */
|
|
26
|
+
protocolVersion = null;
|
|
27
|
+
constructor(info, tools, send) {
|
|
28
|
+
this.info = info;
|
|
29
|
+
this.#tools = tools;
|
|
30
|
+
this.#send = send;
|
|
31
|
+
}
|
|
32
|
+
#reply(id, body) {
|
|
33
|
+
this.#send(JSON.stringify({ jsonrpc: '2.0', id, ...body }));
|
|
34
|
+
}
|
|
35
|
+
/** Tells the client the tool list changed (it calls `tools/list` again). */
|
|
36
|
+
notifyToolsChanged() {
|
|
37
|
+
this.#send(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/tools/list_changed' }));
|
|
38
|
+
}
|
|
39
|
+
/** Handles one incoming line. Resolves when its response (if any) has been sent. */
|
|
40
|
+
async receive(line) {
|
|
41
|
+
if (!line.trim())
|
|
42
|
+
return;
|
|
43
|
+
let msg;
|
|
44
|
+
try {
|
|
45
|
+
msg = JSON.parse(line);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return this.#reply(null, { error: { code: PARSE_ERROR, message: 'Parse error: the line is not JSON.' } });
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(msg))
|
|
51
|
+
return this.#reply(null, { error: { code: INVALID_REQUEST, message: 'Batches are not supported (removed in MCP 2025-06-18).' } });
|
|
52
|
+
if (msg.jsonrpc !== '2.0' || typeof msg.method !== 'string') {
|
|
53
|
+
if (msg.id !== undefined && msg.method === undefined)
|
|
54
|
+
return; // a response to us; we send no requests
|
|
55
|
+
return this.#reply(msg.id ?? null, { error: { code: INVALID_REQUEST, message: 'Expected a JSON-RPC 2.0 request with a method.' } });
|
|
56
|
+
}
|
|
57
|
+
if (msg.id === undefined || msg.id === null)
|
|
58
|
+
return this.#notification(msg.method, msg.params ?? {});
|
|
59
|
+
const id = msg.id;
|
|
60
|
+
const params = msg.params ?? {};
|
|
61
|
+
switch (msg.method) {
|
|
62
|
+
case 'initialize': {
|
|
63
|
+
const asked = String(params.protocolVersion ?? '');
|
|
64
|
+
this.protocolVersion = PROTOCOL_VERSIONS.includes(asked) ? asked : PROTOCOL_VERSIONS[0];
|
|
65
|
+
return this.#reply(id, {
|
|
66
|
+
result: {
|
|
67
|
+
protocolVersion: this.protocolVersion,
|
|
68
|
+
capabilities: { tools: { listChanged: true } },
|
|
69
|
+
serverInfo: this.info,
|
|
70
|
+
instructions: 'Tools drive a running Yali app in a browser over CDP. Start with app_status; world_components and world_query read the scene; screenshot shows it.',
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
case 'ping':
|
|
75
|
+
return this.#reply(id, { result: {} });
|
|
76
|
+
case 'tools/list': {
|
|
77
|
+
const tools = await this.#tools.list();
|
|
78
|
+
this.#listed = tools.map((t) => t.name).join(',');
|
|
79
|
+
return this.#reply(id, { result: { tools } });
|
|
80
|
+
}
|
|
81
|
+
case 'tools/call': {
|
|
82
|
+
const name = params.name;
|
|
83
|
+
if (typeof name !== 'string')
|
|
84
|
+
return this.#reply(id, { error: { code: INVALID_PARAMS, message: 'tools/call needs params.name.' } });
|
|
85
|
+
const args = (params.arguments ?? {});
|
|
86
|
+
const abort = new AbortController();
|
|
87
|
+
this.#inflight.set(id, abort);
|
|
88
|
+
try {
|
|
89
|
+
const result = await this.#tools.call(name, args, abort.signal);
|
|
90
|
+
if (!abort.signal.aborted)
|
|
91
|
+
this.#reply(id, { result });
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
if (!abort.signal.aborted) {
|
|
95
|
+
this.#reply(id, { result: { isError: true, content: [{ type: 'text', text: err instanceof Error ? err.message : String(err) }] } });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
this.#inflight.delete(id);
|
|
100
|
+
}
|
|
101
|
+
// A call can change what the app offers (a page loaded, a plugin registered tools).
|
|
102
|
+
const now = (await this.#tools.list().catch(() => [])).map((t) => t.name).join(',');
|
|
103
|
+
if (this.#listed !== null && now !== this.#listed) {
|
|
104
|
+
this.#listed = now;
|
|
105
|
+
this.notifyToolsChanged();
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
default:
|
|
110
|
+
return this.#reply(id, { error: { code: METHOD_NOT_FOUND, message: `Method not found: ${msg.method}` } });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
#notification(method, params) {
|
|
114
|
+
if (method === 'notifications/cancelled') {
|
|
115
|
+
const id = params.requestId;
|
|
116
|
+
if (id !== undefined)
|
|
117
|
+
this.#inflight.get(id)?.abort();
|
|
118
|
+
}
|
|
119
|
+
// notifications/initialized and others need no answer.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ToolProvider } from './protocol.ts';
|
|
2
|
+
/** The page as the bridge needs it (`@yali-engine/cli`'s `CdpPage` fits; tests pass a fake). */
|
|
3
|
+
export interface PageLike {
|
|
4
|
+
evaluate<T>(expression: string): Promise<T>;
|
|
5
|
+
screenshot(): Promise<string>;
|
|
6
|
+
reload(): Promise<void>;
|
|
7
|
+
readonly connected: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** How the bridge reaches the app. */
|
|
10
|
+
export interface BridgeOptions {
|
|
11
|
+
/** Opens (or re-attaches to) the app's tab. Called lazily and after a disconnect. */
|
|
12
|
+
connect(): Promise<PageLike>;
|
|
13
|
+
/**
|
|
14
|
+
* The page global the app sets (default `__yali`). The bridge uses its `tools` (list,
|
|
15
|
+
* call) and `trace()` when present, which is how a worker-render-mode app is reached
|
|
16
|
+
* (`RenderWorkerHost.tools`); otherwise `app.tools` and `app.profiler`.
|
|
17
|
+
*/
|
|
18
|
+
readonly probe?: string;
|
|
19
|
+
/** Where `trace` writes files. */
|
|
20
|
+
readonly traceDir: string;
|
|
21
|
+
/** Diagnostics (stderr in the server; stdout belongs to the protocol). */
|
|
22
|
+
readonly log?: (line: string) => void;
|
|
23
|
+
/** Longest text result before it is cut (default 60,000 characters). */
|
|
24
|
+
readonly maxText?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Runs the project's headless entry (`yali headless`) and returns its JSON result; with
|
|
27
|
+
* it, the server offers `run_headless`, which needs no browser (ADR-0041).
|
|
28
|
+
*/
|
|
29
|
+
readonly headless?: (args: {
|
|
30
|
+
frames?: number;
|
|
31
|
+
seed?: number;
|
|
32
|
+
query?: string;
|
|
33
|
+
recording?: unknown;
|
|
34
|
+
expect?: string;
|
|
35
|
+
}) => Promise<unknown>;
|
|
36
|
+
}
|
|
37
|
+
/** MCP tool names allow `[a-zA-Z0-9_-]`; Yali's are `plugin.what`. */
|
|
38
|
+
export declare const mcpName: (name: string) => string;
|
|
39
|
+
/**
|
|
40
|
+
* The tools `yali-mcp` serves: the three server tools above, plus every tool the running
|
|
41
|
+
* app registered (`app.tools`: `app.status`, `app.profile`, `world.query`, plugin tools…),
|
|
42
|
+
* renamed with `mcpName`. When no app is reachable, the server tools are still listed and
|
|
43
|
+
* a call explains how to start one.
|
|
44
|
+
*/
|
|
45
|
+
export declare function yaliTools(options: BridgeOptions): ToolProvider;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import { YaliError } from '@yali-engine/core';
|
|
4
|
+
/** MCP tool names allow `[a-zA-Z0-9_-]`; Yali's are `plugin.what`. */
|
|
5
|
+
export const mcpName = (name) => name.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 64);
|
|
6
|
+
const SERVER_TOOLS = [
|
|
7
|
+
{
|
|
8
|
+
name: 'screenshot',
|
|
9
|
+
description: 'A PNG of the app as it is now. Colours are converted by the browser; read exact pixels with an app tool instead.',
|
|
10
|
+
inputSchema: { type: 'object', properties: {} },
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'trace',
|
|
14
|
+
description: 'Saves the profiler ring as a Chrome trace file (open in https://ui.perfetto.dev) and returns its path and a summary.',
|
|
15
|
+
inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'File name stem (default: trace-<time>).' } } },
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'reload_page',
|
|
19
|
+
description: 'Reloads the app (a fresh start of its state) and waits for the page to load.',
|
|
20
|
+
inputSchema: { type: 'object', properties: {} },
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
const RUN_HEADLESS = {
|
|
24
|
+
name: 'run_headless',
|
|
25
|
+
description: 'Runs the game without a browser or GPU (its headless entry from yali.config) for N fixed frames with a seed, optionally replaying an input recording from input.stop_recording, and returns the world hash, the render checksum, the costliest systems and leaks. Same inputs, same hashes.',
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
frames: { type: 'integer', description: 'Fixed frames at 1/60 s (default 240).' },
|
|
30
|
+
seed: { type: 'integer', description: 'The app rng seed (default 1).' },
|
|
31
|
+
query: { type: 'string', description: 'Options for the entry as a query string, e.g. n=2000.' },
|
|
32
|
+
recording: { type: 'object', description: 'An input recording to replay.' },
|
|
33
|
+
expect: { type: 'string', description: 'Fail unless the world hash equals this.' },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The tools `yali-mcp` serves: the three server tools above, plus every tool the running
|
|
39
|
+
* app registered (`app.tools`: `app.status`, `app.profile`, `world.query`, plugin tools…),
|
|
40
|
+
* renamed with `mcpName`. When no app is reachable, the server tools are still listed and
|
|
41
|
+
* a call explains how to start one.
|
|
42
|
+
*/
|
|
43
|
+
export function yaliTools(options) {
|
|
44
|
+
const probe = JSON.stringify(options.probe ?? '__yali');
|
|
45
|
+
const maxText = options.maxText ?? 60_000;
|
|
46
|
+
let page = null;
|
|
47
|
+
// Requests run concurrently: they share one connection attempt instead of each attaching.
|
|
48
|
+
let connecting = null;
|
|
49
|
+
const connect = async () => {
|
|
50
|
+
if (page?.connected)
|
|
51
|
+
return page;
|
|
52
|
+
connecting ??= options.connect().then((p) => ((page = p), (connecting = null), p), (e) => {
|
|
53
|
+
connecting = null;
|
|
54
|
+
throw e;
|
|
55
|
+
});
|
|
56
|
+
return connecting;
|
|
57
|
+
};
|
|
58
|
+
const app = `globalThis[${probe}]?.app`;
|
|
59
|
+
const toolsExpr = `(globalThis[${probe}]?.tools ?? ${app}?.tools)`;
|
|
60
|
+
const traceExpr = `(globalThis[${probe}]?.trace ? globalThis[${probe}].trace() : ${app}?.profiler?.trace())`;
|
|
61
|
+
const text = (value) => {
|
|
62
|
+
let t = typeof value === 'string' ? value : JSON.stringify(value, null, 2) ?? 'null';
|
|
63
|
+
if (t.length > maxText)
|
|
64
|
+
t = `${t.slice(0, maxText)}\n… cut at ${maxText} characters; ask for less (a smaller limit or window).`;
|
|
65
|
+
const structured = value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
|
|
66
|
+
return { content: [{ type: 'text', text: t }], ...(structured ? { structuredContent: structured } : {}) };
|
|
67
|
+
};
|
|
68
|
+
const fail = (code, message, fix, path) => ({
|
|
69
|
+
isError: true,
|
|
70
|
+
content: [{ type: 'text', text: `${code}: ${message}\nfix: ${fix}${path ? `\nargument: ${path}` : ''}` }],
|
|
71
|
+
});
|
|
72
|
+
/** The app's tools, or null when the page or probe is not there. */
|
|
73
|
+
const appTools = async () => {
|
|
74
|
+
try {
|
|
75
|
+
const p = await connect();
|
|
76
|
+
return await p.evaluate(`${toolsExpr}?.list() ?? null`);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
options.log?.(`app tools unavailable: ${err instanceof Error ? err.message : String(err)}`);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const serverTools = options.headless ? [...SERVER_TOOLS, RUN_HEADLESS] : SERVER_TOOLS;
|
|
84
|
+
return {
|
|
85
|
+
async list() {
|
|
86
|
+
// run_headless needs no browser: answer it before trying to reach the page.
|
|
87
|
+
const tools = (await appTools()) ?? [];
|
|
88
|
+
const seen = new Set(serverTools.map((t) => t.name));
|
|
89
|
+
const bridged = [];
|
|
90
|
+
for (const t of tools) {
|
|
91
|
+
const name = mcpName(t.name);
|
|
92
|
+
if (seen.has(name))
|
|
93
|
+
continue; // a server tool or an earlier app tool owns the name
|
|
94
|
+
seen.add(name);
|
|
95
|
+
bridged.push({ name, description: `${t.description} (app tool ${t.name})`, inputSchema: t.input });
|
|
96
|
+
}
|
|
97
|
+
return [...serverTools, ...bridged];
|
|
98
|
+
},
|
|
99
|
+
async call(name, args, signal) {
|
|
100
|
+
if (name === 'run_headless' && options.headless) {
|
|
101
|
+
try {
|
|
102
|
+
return text(await options.headless(args));
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
const e = err;
|
|
106
|
+
return fail(e.code ?? 'HEADLESS_FAILED', e.detail ?? e.message ?? String(err), e.fix ?? 'See the message.');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
let p;
|
|
110
|
+
try {
|
|
111
|
+
p = await connect();
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
const e = err;
|
|
115
|
+
return fail(e.code ?? 'CDP_UNREACHABLE', e.detail ?? String(err), e.fix ?? 'Start the app (`yali dev`) and a Chrome with --remote-debugging-port.');
|
|
116
|
+
}
|
|
117
|
+
if (signal.aborted)
|
|
118
|
+
return fail('CANCELLED', 'The call was cancelled.', 'Call again if still needed.');
|
|
119
|
+
if (name === 'screenshot') {
|
|
120
|
+
return { content: [{ type: 'image', data: await p.screenshot(), mimeType: 'image/png' }] };
|
|
121
|
+
}
|
|
122
|
+
if (name === 'reload_page') {
|
|
123
|
+
await p.reload();
|
|
124
|
+
return text({ reloaded: true });
|
|
125
|
+
}
|
|
126
|
+
if (name === 'trace') {
|
|
127
|
+
const trace = await p.evaluate(`(${traceExpr}) ?? null`);
|
|
128
|
+
if (!trace)
|
|
129
|
+
return fail('NO_PROBE', `The page has no globalThis.${options.probe ?? '__yali'}.app.`, 'The app sets its tools probe: globalThis.__yali = { app, … }.');
|
|
130
|
+
mkdirSync(options.traceDir, { recursive: true });
|
|
131
|
+
const stem = typeof args.name === 'string' && /^[\w.-]+$/.test(args.name) ? args.name : `trace-${new Date().toISOString().replace(/[:.]/g, '-')}`;
|
|
132
|
+
const file = resolve(join(options.traceDir, `${stem}.json`));
|
|
133
|
+
writeFileSync(file, JSON.stringify(trace));
|
|
134
|
+
const spans = trace.traceEvents.filter((e) => e.ph === 'X').length;
|
|
135
|
+
const counters = trace.traceEvents.filter((e) => e.ph === 'C').length;
|
|
136
|
+
return text({ file, spans, counterSamples: counters, ...trace.otherData, open: 'https://ui.perfetto.dev' });
|
|
137
|
+
}
|
|
138
|
+
const tools = await appTools();
|
|
139
|
+
if (!tools)
|
|
140
|
+
return fail('NO_PROBE', `The page has no globalThis.${options.probe ?? '__yali'}.app.tools.`, 'The app sets its tools probe: globalThis.__yali = { app, … }.');
|
|
141
|
+
const tool = tools.find((t) => mcpName(t.name) === name);
|
|
142
|
+
if (!tool)
|
|
143
|
+
return fail('UNKNOWN_TOOL', `No tool named ${name}.`, `Tools: ${[...SERVER_TOOLS.map((t) => t.name), ...tools.map((t) => mcpName(t.name))].join(', ')}.`);
|
|
144
|
+
const r = await p.evaluate(`(async () => {
|
|
145
|
+
try { return { ok: true, value: await ${toolsExpr}.call(${JSON.stringify(tool.name)}, ${JSON.stringify(args)}) }; }
|
|
146
|
+
catch (e) { return { ok: false, code: e.code ?? 'TOOL_FAILED', message: e.detail ?? e.message ?? String(e), fix: e.fix ?? 'See the message.', path: e.path }; }
|
|
147
|
+
})()`);
|
|
148
|
+
return r.ok ? text(r.value) : fail(r.code, r.message, r.fix, r.path);
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=yali-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yali-tools.js","sourceRoot":"","sources":["../src/yali-tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yali-engine/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Yali's MCP server: an agent drives the running app (status, profile, trace, screenshot, scene query and edit, plugin tools). Hand-rolled stdio JSON-RPC, no dependencies beyond Yali's own.",
|
|
5
|
+
"license": "MIT OR Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"yali-mcp": "./bin/yali-mcp.mjs"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"bin",
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@yali-engine/cli": "0.4.0",
|
|
25
|
+
"@yali-engine/core": "0.4.0"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
29
|
+
"test": "node --experimental-strip-types --no-warnings --test \"test/*.test.ts\""
|
|
30
|
+
}
|
|
6
31
|
}
|
package/README.md
DELETED