aiterm-mcp 0.43.5 → 0.43.7

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/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.43.7] - 2026-09-29
11
+
12
+ ### 修正
13
+
14
+ - Cursor CLIの親で、子の回答が作業中にもidle中にも届かなかった(Linux・macOS)。Cursor CLIはMCPを削った環境で起動し、hookと背景の受信processは画面側の環境で起動する。state rootの置き場(XDG_RUNTIME_DIR・TMPDIR・AITERM_STATE_BASE)が割れ、hookが配送記録を見つけられずに何もしていなかった。hookと受信processは、同じ利用者の置き場の候補のうち配送記録のある方を使う(aiterm-steer-delivery 0.1.8)。
15
+ - Cursor CLIのmodelはtool結果のstructuredContentを見ないため、idle中に受け取る背景コマンド(wait_process)を知らずにターンを終えていた。Cursor親への結果の本文にもそのコマンド行を書く。
16
+
17
+ ## [0.43.6] - 2026-09-29
18
+
19
+ ### 修正
20
+
21
+ - Cursor CLI(cursor-agent)の親を、Cursor親として見分けていなかった。CLIはMCPのinitializeで`"Cursor"`と名乗り、`"cursor-vscode"`(Desktop)しか見ていなかったため、子の回答は汎用の`wait_process`でしか受け取れなかった。今はDesktopと同じく、作業中は次のtool返りへ差し込み、idle中は背景受信で届く(aiterm-steer-delivery 0.1.6、紅蓮氏の報告)。
22
+ - WindowsのCursorは、hookのstdinのJSONの先頭にBOMを付ける。そのまま読んで失敗していたため、作業中の差し込みが起きず、配送が`sending`のまま止まっていた。先頭のBOMを落とす(aiterm-steer-delivery 0.1.7、紅蓮氏の報告)。
23
+
10
24
  ## [0.43.5] - 2026-09-29
11
25
 
12
26
  ### 修正
@@ -1893,7 +1907,9 @@ prototype (preserved under `prototype/python/` as the porting source and referen
1893
1907
  `ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
1894
1908
  provenance.
1895
1909
 
1896
- [Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.43.5...HEAD
1910
+ [Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.43.7...HEAD
1911
+ [0.43.7]: https://github.com/kitepon/aiterm-mcp/compare/v0.43.6...v0.43.7
1912
+ [0.43.6]: https://github.com/kitepon/aiterm-mcp/compare/v0.43.5...v0.43.6
1897
1913
  [0.43.5]: https://github.com/kitepon/aiterm-mcp/compare/v0.43.4...v0.43.5
1898
1914
  [0.43.4]: https://github.com/kitepon/aiterm-mcp/compare/v0.43.3...v0.43.4
1899
1915
  [0.43.3]: https://github.com/kitepon/aiterm-mcp/compare/v0.43.2...v0.43.3
package/README.ja.md CHANGED
@@ -203,7 +203,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
203
203
  場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
204
204
  Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
205
205
 
206
- **状態:** 開発継続中 · 現行公開版 **v0.43.5** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
206
+ **状態:** 開発継続中 · 現行公開版 **v0.43.7** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
207
207
 
208
208
  ### 更新と巻き戻し
209
209
 
package/README.md CHANGED
@@ -217,7 +217,7 @@ collection is off by default and performs no network I/O. It ships via
217
217
  tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
218
218
  Release re-registers the Official MCP Registry entry.
219
219
 
220
- **Status:** actively maintained · current public release **v0.43.5** · runs on Linux · WSL2 · macOS · native Windows (tmux on POSIX, the tmux-CLI-compatible [psmux](https://github.com/psmux/psmux) on native Windows — no WSL required) · MIT · see the [CHANGELOG](CHANGELOG.md).
220
+ **Status:** actively maintained · current public release **v0.43.7** · runs on Linux · WSL2 · macOS · native Windows (tmux on POSIX, the tmux-CLI-compatible [psmux](https://github.com/psmux/psmux) on native Windows — no WSL required) · MIT · see the [CHANGELOG](CHANGELOG.md).
221
221
 
222
222
  ### Update and rollback
223
223
 
@@ -1,6 +1,7 @@
1
1
  // harness中立の共有プリミティブ。core と harnesses/ の両方が依存する最下層で、
2
2
  // tmux-runtime / errors 以外の内部moduleへ依存しない(依存方向: core → harnesses → agent-shared)。
3
3
  import * as fs from "node:fs";
4
+ import * as os from "node:os";
4
5
  import * as path from "node:path";
5
6
  import { randomBytes } from "node:crypto";
6
7
  import { AitermError } from "./errors.js";
@@ -99,6 +100,16 @@ export function stateRoot() {
99
100
  const base = runtimeStateBase();
100
101
  return path.join(base, `aiterm-mcp-${uid}`);
101
102
  }
103
+ /**
104
+ * 同じ利用者のAitermが使いうるstate rootの候補(先頭はこのprocessのもの)。
105
+ * Cursor CLIはMCPを削った環境(XDG_RUNTIME_DIR・TMPDIR・AITERM_STATE_BASE無し)で起動し、hookと背景processは画面側の環境で起動する。
106
+ * 置き場は環境で決まるので両者で割れる。hook側はこの候補のうち配送記録のある置き場を使う。
107
+ */
108
+ export function stateRootCandidates() {
109
+ const name = `aiterm-mcp-${currentUid()}`;
110
+ const bases = [runtimeStateBase(), process.env.AITERM_STATE_BASE, process.env.XDG_RUNTIME_DIR, os.tmpdir(), process.platform === "win32" ? undefined : "/tmp"];
111
+ return [...new Set(bases.filter((base) => typeof base === "string" && base !== "").map(base => path.join(base, name)))];
112
+ }
102
113
  export function ensureStateRoot() {
103
114
  // state root は OS が与えるper-user runtime dir(Windows隔離時TMPDIR/XDG_RUNTIME_DIR/os.tmpdir())の下に作る。
104
115
  // 以前はここで symlink・owner・mode を検査していたが、共有 /tmp に敵対的な同居主体がいる
package/dist/core.js CHANGED
@@ -13,6 +13,7 @@ import * as path from "node:path";
13
13
  import { createHash, randomBytes } from "node:crypto";
14
14
  import { fileURLToPath } from "node:url";
15
15
  import * as rtk from "./rtk.js";
16
+ import { isCursorMcpClient } from "aiterm-steer-delivery";
16
17
  import { paneTokenHint } from "./harnesses/pane-tokens.js";
17
18
  import { readRuntimeProcesses, processSubtree, parentProcess, processIdentity, backgroundProcesses } from "./process-runtime.js";
18
19
  import { AitermError, telemetryOwnedFailure, ownTelemetryFailure } from "./errors.js";
@@ -2598,7 +2599,7 @@ function autoDeliveryParent() {
2598
2599
  return "Codex";
2599
2600
  if (parentClientName === "claude-code")
2600
2601
  return "Claude Code";
2601
- if (parentClientName === "cursor-vscode" || parentClientName?.startsWith("cursor-vscode "))
2602
+ if (isCursorMcpClient(parentClientName ?? undefined))
2602
2603
  return "Cursor";
2603
2604
  return null;
2604
2605
  }
@@ -2619,7 +2620,7 @@ export function agentDispatchGuide(session, cursor) {
2619
2620
  const parent = autoDeliveryParent();
2620
2621
  if (parent === "Cursor") {
2621
2622
  return "回答はこの会話へ自動で届く。作業を続ければ次のツール返りに差し込まれる。" +
2622
- "ターンを終える前にreceiptのwait_processを背景(block_until_ms: 0)で起動しておけば、idle中に完了しても起きられる。" +
2623
+ "ターンを終える前に、この結果のwait_processのコマンドを背景(block_until_ms: 0)で起動しておけば、idle中に完了しても起きられる。" +
2623
2624
  "ポーリング・pty_read(agent_transcript:true)は不要。";
2624
2625
  }
2625
2626
  if (parent) {
@@ -2,5 +2,7 @@
2
2
  // Cursorが起動する公式hook。MCP stdioとは別processで、差し込み文をstdoutのJSONへ返す。本体はaiterm-steer-delivery。
3
3
  import { isDirectExecution, runCursorHookMain } from "aiterm-steer-delivery";
4
4
  import { AITERM_PROFILE } from "./steer-profile.js";
5
+ import { cursorHookRoots } from "./cursor-parent-receiver.js";
6
+ // Cursor CLIではMCPとhookの環境が違い、state rootが割れる。候補の置き場すべてで結び付けと差し込みを行う。
5
7
  if (isDirectExecution(import.meta.url))
6
- await runCursorHookMain(AITERM_PROFILE);
8
+ await runCursorHookMain(AITERM_PROFILE, cursorHookRoots());
@@ -2,12 +2,19 @@
2
2
  // Cursor親がidleのとき、背景で起動して回答本文の到着を待つ受け口。本体はaiterm-steer-delivery。
3
3
  import { fileURLToPath } from "node:url";
4
4
  import * as steer from "aiterm-steer-delivery";
5
- import { cursorHookRoot } from "./cursor-parent-receiver.js";
5
+ import { cursorHookRoots } from "./cursor-parent-receiver.js";
6
6
  export function cursorReceiveProcess(deliveryId, executable = process.execPath) {
7
7
  return steer.cursorReceiveProcess(fileURLToPath(import.meta.url), deliveryId, executable);
8
8
  }
9
+ /** 背景processの起動情報を、親のshellへ書ける1行にする(Windowsの既定shellはPowerShell)。 */
10
+ export function waitProcessCommandLine(wait, platform = process.platform) {
11
+ const values = [wait.executable, ...wait.args];
12
+ if (platform === "win32")
13
+ return `& ${values.map(value => `'${value.replace(/'/g, "''")}'`).join(" ")}`;
14
+ return values.map(value => `'${value.replace(/'/g, "'\\''")}'`).join(" ");
15
+ }
9
16
  export async function main(argv) {
10
- return steer.runCursorReceive(cursorHookRoot(), argv);
17
+ return steer.runCursorReceive(cursorHookRoots(), argv);
11
18
  }
12
19
  if (steer.isDirectExecution(import.meta.url)) {
13
20
  main(process.argv.slice(2)).then(code => { process.exitCode = code; }).catch(error => {
@@ -3,7 +3,7 @@
3
3
  import * as path from "node:path";
4
4
  import { z } from "zod";
5
5
  import * as steer from "aiterm-steer-delivery";
6
- import { ensureStateRoot } from "./agent-shared.js";
6
+ import { ensureStateRoot, stateRootCandidates } from "./agent-shared.js";
7
7
  import { AITERM_PROFILE } from "./steer-profile.js";
8
8
  // 配送記録の検証はAitermのzodで行う(パッケージのschemaと同じ形)。
9
9
  export const cursorParentSchema = z.object({ kind: z.literal("cursor"), hook_root: z.string() }).strict();
@@ -12,6 +12,10 @@ export const { isCursorMcpClient, cursorHooksFile, prepareCursorDelivery, submit
12
12
  export function cursorHookRoot(state = ensureStateRoot()) {
13
13
  return path.join(state, "cursor-parent-hooks");
14
14
  }
15
+ /** hookと受信processが配送記録を探す置き場(先頭はこのprocessのもの)。理由は stateRootCandidates。 */
16
+ export function cursorHookRoots() {
17
+ return stateRootCandidates().map(state => cursorHookRoot(state));
18
+ }
15
19
  export function cursorParentHooksRegistered(document) { return steer.cursorParentHooksRegistered(AITERM_PROFILE, document); }
16
20
  export function verifyCursorParent(parent, hooksFile = cursorHooksFile()) { steer.verifyCursorParent(AITERM_PROFILE, parent, hooksFile); }
17
21
  export function cursorParentFromRequest(clientName, options = {}) {
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ import { acceptRemote, callRemoteTool, observeRemoteAgentDone, remoteInputDescri
20
20
  import { codexParentFromRequest } from "./codex-parent-receiver.js";
21
21
  import { claudeParentFromRequest } from "./claude-parent-receiver.js";
22
22
  import { cursorParentFromRequest, isCursorMcpClient } from "./cursor-parent-receiver.js";
23
+ import { waitProcessCommandLine } from "./cursor-parent-receive.js";
23
24
  import { INTERIM_RESULT_META_KEY, interimRequestFromMeta } from "./interim-words.js";
24
25
  // package.json の version を実行時に読み、MCP initialize で配るサーバ版と一致させる。
25
26
  // createRequire を使うのは、import 属性 `with { type: "json" }` が Node 18.20+ 限定で
@@ -50,7 +51,11 @@ async function deliveryForRequest(extra, remote = false) {
50
51
  }
51
52
  function deliveryIdLine(delivery) {
52
53
  const id = delivery?.result()?.delivery_id;
53
- return id ? `\ndelivery_id=${id}` : "";
54
+ if (!id)
55
+ return "";
56
+ // Cursor CLIのmodelはtool結果のstructuredContentを見ないので、idle中に受け取る背景コマンドも本文に書く。
57
+ const wait = delivery?.wait_process();
58
+ return `\ndelivery_id=${id}` + (wait ? `\nwait_process(ターンを終える前に背景で起動): ${waitProcessCommandLine(wait)}` : "");
54
59
  }
55
60
  function completionWait(delivery, session, eventCursor) {
56
61
  if (eventCursor === null)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiterm-mcp",
3
- "version": "0.43.5",
3
+ "version": "0.43.7",
4
4
  "mcpName": "io.github.kitepon/aiterm-mcp",
5
5
  "description": "Persistent terminal MCP with one harness-based launcher for Claude Code, Codex CLI, Grok CLI, and Cursor Agent CLI, plus durable PTYs for SSH, containers, and REPLs.",
6
6
  "keywords": [
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "@modelcontextprotocol/sdk": "^1.29.0",
73
- "aiterm-steer-delivery": "^0.1.5",
73
+ "aiterm-steer-delivery": "^0.1.8",
74
74
  "ws": "8.21.3",
75
75
  "zod": "^4.4.3"
76
76
  },