testToolsRunInAWorker
The server runs quick tools' commands in a worker it keeps up: each answers as the command would at a terminal,
an error doesn't leak into the next, what one changes the next sees, and calls made while it's busy are answered
too (by a tcm of their own), as is a command it doesn't run (tcm run).
import { plainEnv, tcmBin, tempDir, withChildren } from "#codebase/tcmts/cli/test/e2e/harness"; import { session } from "#codebase/tcmts/cli/test/e2e/mcp"; import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; export const testToolsRunInAWorker = () => withChildren(async (keep) => { const dir = tempDir("mcp worker"); const env = plainEnv(); assert.equal(spawnSync(process.execPath, [tcmBin(), "init"], { cwd: dir, env }).status, 0); fs.writeFileSync( path.join(dir, "scratch.ts"), `// tcm: namespace lib\nexport const square = (x: number): number => x * x;\nexport const area = (s: number): number => square(s);\n`, ); assert.equal(spawnSync(process.execPath, [tcmBin(), "add"], { cwd: dir, env }).status, 0); // (on the codebase's own branch: this is about the worker, not sessions) const s = session(dir, keep, "--direct"); await s.request("initialize", { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "test", version: "0" }, }); const view = await s.call("tcm_view", { names: ["lib.square"] }); assert.equal(view.isError, false); assert.match(view.text, /x \* x/); // an error, then not const missing = await s.call("tcm_view", { names: ["lib.nothing"] }); assert.equal(missing.isError, true); assert.match(missing.text, /'lib\.nothing' not found/); // a name that isn't there doesn't hide the ones that are, and says what was meant const some = await s.call("tcm_view", { names: ["lib.sqare", "lib.square"], lines: '"1-3"' }); assert.equal(some.isError, false); assert.match(some.text, /^'lib\.sqare' not found; did you mean lib\.square\?/); assert.match(some.text, /\*\*lib\.square\*\*[\s\S]*x \* x/); assert.equal((await s.call("tcm_todo")).isError, false); // a change, seen by what comes next assert.match( (await s.call("tcm_patch", { name: "lib.square", edits: [{ old: "x * x", new: "x ** 2" }] })) .text, /~ update +lib\.square/, ); assert.match((await s.call("tcm_view", { names: ["lib.square"] })).text, /x \*\* 2/); assert.match((await s.call("tcm_dependents", { name: "lib.square" })).text, /^lib\.area$/m); // several at once: one in the worker, the rest each in a tcm of its own const [a, b, c] = await Promise.all([ s.call("tcm_view", { names: ["lib.area"] }), s.call("tcm_find", { query: "square" }), s.call("tcm_status"), ]); assert.match(a.text, /square\(s\)/); assert.match(b.text, /lib\.square/); assert.match(c.text, /named definitions/); // a command the worker doesn't run assert.match((await s.call("tcm_run", { name: "lib.area", args: ["3"] })).text, /^9$/m); s.close(); })