threenative-engine-mcp 0.2.2 → 0.2.3

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.
Files changed (3) hide show
  1. package/README.md +13 -0
  2. package/dist/index.js +33 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -30,3 +30,16 @@ The first that exists wins, so the manifest can never drift from the engine the
30
30
 
31
31
  A project copy committed at scaffold time is therefore inert whenever the package is installed:
32
32
  the two never need re-syncing by hand.
33
+
34
+ ## The call log
35
+
36
+ Every tool call appends one JSON line to `.threenative/engine-mcp.log` in the launch directory, so
37
+ a finished session's searches can be read back:
38
+
39
+ ```json
40
+ {"time":"2026-09-14T20:20:00.000Z","results":["MultiMesh3D"],"scope":"mechanic","situation":"spawn many identical props","tool":"engine_search_capabilities","verdict":"matched"}
41
+ ```
42
+
43
+ A rejected call is logged with its `error`, which is where an agent asked for something the engine
44
+ could not answer. `THREENATIVE_ENGINE_MCP_LOG` names another file, or `off` to disable the log. A
45
+ log that cannot be written reports once on stderr and never fails a tool call.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { realpathSync, readFileSync, existsSync } from 'fs';
2
+ import { realpathSync, readFileSync, existsSync, mkdirSync, appendFileSync } from 'fs';
3
3
  import path from 'path';
4
4
  import { createInterface } from 'readline';
5
5
  import { fileURLToPath } from 'url';
@@ -417,6 +417,22 @@ var TOOL_DEFINITIONS = [
417
417
  function toolDefinitions() {
418
418
  return TOOL_DEFINITIONS;
419
419
  }
420
+ var DEFAULT_LOG_FILE = path.join(".threenative", "engine-mcp.log");
421
+ var logBroken = false;
422
+ function logToolCall(entry) {
423
+ if (logBroken) return;
424
+ const target = process.env.THREENATIVE_ENGINE_MCP_LOG ?? DEFAULT_LOG_FILE;
425
+ if (target === "off") return;
426
+ try {
427
+ mkdirSync(path.dirname(path.resolve(target)), { recursive: true });
428
+ appendFileSync(target, `${JSON.stringify({ time: (/* @__PURE__ */ new Date()).toISOString(), ...entry })}
429
+ `);
430
+ } catch (error) {
431
+ logBroken = true;
432
+ process.stderr.write(`engine-mcp log disabled (${target}): ${String(error)}
433
+ `);
434
+ }
435
+ }
420
436
  function jsonRpcError(id, code, message) {
421
437
  return JSON.stringify({ id, jsonrpc: "2.0", error: { code, message } });
422
438
  }
@@ -439,12 +455,22 @@ function handleToolCall(params, manifestFile) {
439
455
  const scope = argumentsValue.scope ?? "mechanic";
440
456
  if (scope !== "request" && scope !== "mechanic")
441
457
  throw new Error("engine_search_capabilities scope must be 'request' or 'mechanic'.");
442
- return toolText(searchCapabilities(argumentsValue.situation, manifestFile, scope));
458
+ const response = searchCapabilities(argumentsValue.situation, manifestFile, scope);
459
+ logToolCall({
460
+ results: response.results.map((result) => result.symbol),
461
+ scope,
462
+ situation: argumentsValue.situation,
463
+ tool: name,
464
+ verdict: response.verdict
465
+ });
466
+ return toolText(response);
443
467
  }
444
468
  if (name === "engine_capability_detail") {
445
469
  if (typeof argumentsValue.symbol !== "string")
446
470
  throw new Error("engine_capability_detail requires a string 'symbol' argument.");
447
- return toolText(capabilityDetail(argumentsValue.symbol, manifestFile));
471
+ const detail = capabilityDetail(argumentsValue.symbol, manifestFile);
472
+ logToolCall({ symbol: argumentsValue.symbol, tool: name });
473
+ return toolText(detail);
448
474
  }
449
475
  throw new Error(`Unknown engine MCP tool '${String(name)}'.`);
450
476
  }
@@ -464,7 +490,7 @@ function handleLine(line, manifestFile) {
464
490
  capabilities: { tools: { listChanged: false } },
465
491
  instructions: AUTHORING_INSTRUCTIONS,
466
492
  protocolVersion: "2025-06-18",
467
- serverInfo: { name: "threenative-engine-mcp", version: "0.2.2" }
493
+ serverInfo: { name: "threenative-engine-mcp", version: "0.2.3" }
468
494
  });
469
495
  }
470
496
  if (request.method === "tools/list") {
@@ -476,7 +502,9 @@ function handleLine(line, manifestFile) {
476
502
  }
477
503
  return jsonRpcError(request.id, -32601, `Method not found: ${request.method}`);
478
504
  } catch (error) {
479
- return jsonRpcError(request.id, -32e3, error instanceof Error ? error.message : String(error));
505
+ const message = error instanceof Error ? error.message : String(error);
506
+ if (request.method === "tools/call") logToolCall({ error: message, request: request.params });
507
+ return jsonRpcError(request.id, -32e3, message);
480
508
  }
481
509
  }
482
510
  function runServer(manifestFile = defaultManifestPath()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threenative-engine-mcp",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "license": "MIT",
5
5
  "description": "Offline MCP capability discovery for ThreeNative authoring agents.",
6
6
  "keywords": [