| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- import { existsSync } from "node:fs";
- import { mkdtemp, rm } from "node:fs/promises";
- import { tmpdir } from "node:os";
- import { join, resolve } from "node:path";
- import { describe, expect, it } from "vitest";
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
- import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
- import { MCP_SERVER_NAME } from "../src/mcp-server.js";
- import { newProject } from "../src/template.js";
- const entry = resolve(process.cwd(), "dist/main/mcp-stdio.js");
- function textOf(result: { content?: { type: string; text?: string }[] }): string {
- return result.content?.find((block) => block.type === "text")?.text ?? "";
- }
- describe("editor --mcp-stdio headless mode (spawned entry over stdio)", () => {
- it("spawns a drop-in stdio MCP server for --dir: handshake + full surface + a tool call", async () => {
- expect(existsSync(entry)).toBe(true);
- const dir = await mkdtemp(join(tmpdir(), "editor-stdio-"));
- try {
- const project = await newProject("Stdio Farm", dir);
- const client = new Client({ name: "editor-stdio-test", version: "0.0.1" });
- const transport = new StdioClientTransport({ command: "node", args: [entry, "--dir", project.root] });
- await client.connect(transport);
- try {
- expect(client.getServerVersion()).toMatchObject({ name: MCP_SERVER_NAME, version: "0.1.0" });
- const tools = await client.listTools();
- expect(tools.tools).toHaveLength(132);
- const info = JSON.parse(textOf(await client.callTool({ name: "server.info", arguments: {} }))) as {
- engine: string;
- content: { map: string[]; time: string[]; item: string[] };
- };
- expect(info.engine).toBe("nengine");
- expect(info.content.map).toEqual(["stdio-farm"]);
- expect(info.content.item.sort()).toEqual(["hoe", "stdio-farm", "stdio-farm-seed"]);
- } finally {
- await client.close();
- }
- } finally {
- await rm(dir, { recursive: true, force: true });
- }
- });
- it("item.create over stdio writes content into the project's content dir", async () => {
- expect(existsSync(entry)).toBe(true);
- const dir = await mkdtemp(join(tmpdir(), "editor-stdio-"));
- try {
- const project = await newProject("Stdio Farm", dir);
- const client = new Client({ name: "editor-stdio-test", version: "0.0.1" });
- const transport = new StdioClientTransport({ command: "node", args: [entry, "--dir", project.root] });
- await client.connect(transport);
- try {
- const created = await client.callTool({
- name: "item.create",
- arguments: { def: { id: "sickle", name: "Sickle", kind: "tool", stackable: false } },
- });
- expect(created.isError).not.toBe(true);
- const file = resolve(project.root, "content/items/sickle.yaml");
- expect(existsSync(file)).toBe(true);
- } finally {
- await client.close();
- }
- } finally {
- await rm(dir, { recursive: true, force: true });
- }
- });
- });
|