aiterm-mcp 0.53.0 → 0.53.2
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 +23 -1
- package/README.ja.md +3 -1
- package/README.md +3 -1
- package/dist/core.js +1 -1
- package/dist/harnesses/grok.js +17 -8
- package/dist/lazy-relay.js +8 -0
- package/dist/process-runtime.js +2 -1
- package/dist/setup-integrations.js +25 -3
- package/docs/DESIGN.md +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.53.2] - 2026-10-05
|
|
11
|
+
|
|
12
|
+
### 修正
|
|
13
|
+
|
|
14
|
+
- 引数なしの`aiterm-setup`が、中継(`mcp-lazy`)で包んだAitermの登録を直結へ書き戻していた(ADR 0091)。
|
|
15
|
+
連携元が全席の登録を中継つきにした後、1席がsetupを流すだけで、Claude Code・Codex・Grok・Cursorの4つの設定が直結へ戻り、
|
|
16
|
+
本体を眠らせておく節約が次の書き直しまで消えた。Codexは`mcp add`で作り直されるので、待ち時間(`startup_timeout_sec`・
|
|
17
|
+
`tool_timeout_sec`)と`env_vars`も一緒に消えた。
|
|
18
|
+
commandが`mcp-lazy`で始まる名前の実行ファイルで、argsが直結の登録のcommand+args(中継のflagを`--`の前に置いた形も含む)なら、
|
|
19
|
+
同じ登録と数えて書き直さない。包んでいる本体のpathが違う時は、今までどおり直結の登録へ書き直す。
|
|
20
|
+
|
|
21
|
+
## [0.53.1] - 2026-10-05
|
|
22
|
+
|
|
23
|
+
### 修正
|
|
24
|
+
|
|
25
|
+
- 0.53.0で、Grokにログイン済みなのに`agent_auth`の`status`が`blocked`(認証が必要)を返す事があった。
|
|
26
|
+
`grok models`は、生きているログインでも古いtokenを取り直す回だけ`You are not authenticated.`と答える事がある
|
|
27
|
+
(macbook、Grok 1.0.46。1回目は未認証、同じ時刻に`auth.json`が更新され、2回目からは認証済み)。
|
|
28
|
+
「未認証」の答えは1回では決めず、1.5秒置いてもう1回聞く。2回とも未認証の時だけ`blocked`にする。
|
|
29
|
+
|
|
10
30
|
## [0.53.0] - 2026-10-05
|
|
11
31
|
|
|
12
32
|
### 追加
|
|
@@ -2195,7 +2215,9 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
2195
2215
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
2196
2216
|
provenance.
|
|
2197
2217
|
|
|
2198
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.
|
|
2218
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.2...HEAD
|
|
2219
|
+
[0.53.2]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.1...v0.53.2
|
|
2220
|
+
[0.53.1]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.0...v0.53.1
|
|
2199
2221
|
[0.53.0]: https://github.com/kitepon/aiterm-mcp/compare/v0.52.3...v0.53.0
|
|
2200
2222
|
[0.52.3]: https://github.com/kitepon/aiterm-mcp/compare/v0.52.2...v0.52.3
|
|
2201
2223
|
[0.52.2]: https://github.com/kitepon/aiterm-mcp/compare/v0.52.1...v0.52.2
|
package/README.ja.md
CHANGED
|
@@ -209,7 +209,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
|
|
|
209
209
|
場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
|
|
210
210
|
Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
|
|
211
211
|
|
|
212
|
-
**状態:** 開発継続中 · 現行公開版 **v0.53.
|
|
212
|
+
**状態:** 開発継続中 · 現行公開版 **v0.53.2** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
213
213
|
|
|
214
214
|
### 更新と巻き戻し
|
|
215
215
|
|
|
@@ -536,6 +536,8 @@ MCPの本体を初めて使う時まで起こさない中継の後ろにAiterm
|
|
|
536
536
|
`MCP_LAZY_WAKE_COMMAND='["/absolute/path/to/node","/absolute/path/to/aiterm-mcp/dist/delivery-wake-cli.js","--parent","claude"]'`
|
|
537
537
|
持ち主の開始時刻はLinuxでは`/proc`で照合する。それ以外のOSでは、pidがあれば生きている持ち主として扱う。
|
|
538
538
|
|
|
539
|
+
`aiterm-setup`は、中継(`mcp-lazy`)で包んだ同じ登録を作り直さない。commandが`mcp-lazy`で始まる名前の実行ファイルで、argsが直結の登録のcommand+args(中継のflagを`--`の前に置いた形も含む)なら、Claude Code・Codex・Grok・Cursorの登録をそのまま残す。包んでいる本体のpathが違う時は、直結の登録へ書き直す。
|
|
540
|
+
|
|
539
541
|
`agent_launch({ harness, cwd, trust_project: true })`はpromptなしでも既知のworkspace・project hooks・MCP初期同意を
|
|
540
542
|
進め、入力受付とharness生存を確認して`startup.status="ready"`を返す。指定なしのpromptなし起動は`not_checked`。
|
|
541
543
|
Claude Code初回起動の文字表示テーマ選択では、画面で選択済みの項目を確定して起動を続ける。
|
package/README.md
CHANGED
|
@@ -223,7 +223,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
223
223
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
224
224
|
Release re-registers the Official MCP Registry entry.
|
|
225
225
|
|
|
226
|
-
**Status:** actively maintained · current public release **v0.53.
|
|
226
|
+
**Status:** actively maintained · current public release **v0.53.2** · 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).
|
|
227
227
|
|
|
228
228
|
### Update and rollback
|
|
229
229
|
|
|
@@ -572,6 +572,8 @@ same environment as the server:
|
|
|
572
572
|
`MCP_LAZY_WAKE_COMMAND='["/absolute/path/to/node","/absolute/path/to/aiterm-mcp/dist/delivery-wake-cli.js","--parent","claude"]'`.
|
|
573
573
|
Owner start times are checked through `/proc` on Linux; elsewhere an existing PID is treated as a live owner.
|
|
574
574
|
|
|
575
|
+
`aiterm-setup` does not rewrite a registration that wraps the same server in the `mcp-lazy` relay. When the registered command is an executable whose name starts with `mcp-lazy` and its args are the direct registration's command followed by its args (relay flags before `--` are allowed), the Claude Code, Codex, Grok, and Cursor registrations are left as they are. If the wrapped server path differs, setup writes the direct registration.
|
|
576
|
+
|
|
575
577
|
`agent_launch({ harness, cwd, trust_project: true })` completes known workspace, project-hook, and project-MCP startup
|
|
576
578
|
consent even without a prompt, then verifies input readiness and harness liveness before returning `startup.status="ready"`.
|
|
577
579
|
For Claude Code's first-run text-style menu, it confirms the item already selected on screen before continuing startup.
|
package/dist/core.js
CHANGED
|
@@ -3714,7 +3714,7 @@ async function authStatus(kind, bin, cwd, env = process.env) {
|
|
|
3714
3714
|
switch (kind) {
|
|
3715
3715
|
case "claude": return claudeAuthStatus(bin, cwd, env);
|
|
3716
3716
|
case "codex": return await codexAuthStatus(bin, cwd, env);
|
|
3717
|
-
case "grok": return grokAuthStatus(bin, cwd, env);
|
|
3717
|
+
case "grok": return await grokAuthStatus(bin, cwd, env);
|
|
3718
3718
|
case "cursor": return cursorAuthStatus(bin, cwd, env);
|
|
3719
3719
|
}
|
|
3720
3720
|
}
|
package/dist/harnesses/grok.js
CHANGED
|
@@ -530,18 +530,27 @@ export function createGrokAgentMetadata(kind, name, cwd, initialPrompt, authPath
|
|
|
530
530
|
return meta;
|
|
531
531
|
}
|
|
532
532
|
export function grokAuthPlan() { return { args: ["login", "--device-auth"], env: [] }; }
|
|
533
|
+
const GROK_AUTH_RECHECK_MS = 1500;
|
|
533
534
|
/**
|
|
534
535
|
* Grokには認証状態を答える公式commandが無い。`grok models`は、使えるログインが無い時に`You are not authenticated.`と答える
|
|
535
536
|
* (1.0.46。ログイン無しと、期限切れ・無効なtokenの両方。後者ではGrokが`auth.json`を自分で消す)。auth fileの存在は見ない。
|
|
537
|
+
* 生きているログインでも、古いtokenを取り直す回だけ「未認証」と答える事がある(2026-10-05 macbook。1回目は未認証、
|
|
538
|
+
* 同じ時刻に`auth.json`が更新され、2回目からは認証済み)。1回の「未認証」では決めず、少し置いてもう1回聞く。
|
|
536
539
|
*/
|
|
537
|
-
export function grokAuthStatus(bin, cwd, env = process.env) {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
540
|
+
export async function grokAuthStatus(bin, cwd, env = process.env) {
|
|
541
|
+
for (let attempt = 0;; attempt += 1) {
|
|
542
|
+
const result = spawnAgentControlCommand(bin, ["models"], cwd, { cwd, env, encoding: "utf8", timeout: 20000, maxBuffer: 256 * 1024 });
|
|
543
|
+
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
|
|
544
|
+
if (!result.error && /You are not authenticated|Not signed in/i.test(output)) {
|
|
545
|
+
if (attempt > 0)
|
|
546
|
+
return { status: "unauthenticated", message: null };
|
|
547
|
+
await new Promise(resolve => setTimeout(resolve, GROK_AUTH_RECHECK_MS));
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (!result.error && result.status === 0 && /Available models/i.test(output))
|
|
551
|
+
return { status: "authenticated", message: null };
|
|
552
|
+
return { status: "failed", message: "Grokの公式CLIで認証状態を確認できません。" };
|
|
553
|
+
}
|
|
545
554
|
}
|
|
546
555
|
export function grokAuthPane(screen) {
|
|
547
556
|
const url = authUrl(screen, ["auth.x.ai", "accounts.x.ai", "grok.com"]);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// 中継(mcp-lazy)の見分け。取り決めはmcp-lazyのREADMEにある(実行ファイルの名前が`mcp-lazy`で始まる)。
|
|
2
|
+
// process表の読み手(process-runtime)と、登録の読み手(setup-integrations)が同じ決まりを使う。
|
|
3
|
+
// setup-integrationsは連携元のprocessへ直接読み込まれるので、ここはnode:pathだけに依存する。
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
/** 実行ファイルのpathが中継(mcp-lazy)か。名前(basename)が`mcp-lazy`で始まる物。 */
|
|
6
|
+
export function lazyRelayExecutable(file) {
|
|
7
|
+
return path.posix.basename(file.replace(/\\/g, "/")).toLowerCase().startsWith("mcp-lazy");
|
|
8
|
+
}
|
package/dist/process-runtime.js
CHANGED
|
@@ -3,6 +3,7 @@ import { spawnSync } from "node:child_process";
|
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { AitermError } from "./errors.js";
|
|
6
|
+
import { lazyRelayExecutable } from "./lazy-relay.js";
|
|
6
7
|
import { isWin } from "./tmux-runtime.js";
|
|
7
8
|
import { resolveWindowsPowerShell7 } from "./windows-powershell.js";
|
|
8
9
|
export function processIdentity(process) {
|
|
@@ -223,7 +224,7 @@ export function processSubtree(rows, rootPid) {
|
|
|
223
224
|
// 見分けるのは起動した実行ファイルの名前(argvの先頭のbasenameが`mcp-lazy`で始まる)。取り決めはmcp-lazyのREADMEにある。
|
|
224
225
|
export function lazyRelayProcess(command) {
|
|
225
226
|
const first = /^(?:"([^"]+)"|(\S+))/.exec(command);
|
|
226
|
-
return
|
|
227
|
+
return lazyRelayExecutable(first?.[1] ?? first?.[2] ?? "");
|
|
227
228
|
}
|
|
228
229
|
export function backgroundProcesses(rows, root) {
|
|
229
230
|
// 起動時の足場processを除く既存契約。pane開始から60秒以上後に生成された子孫だけを集計する。
|
|
@@ -5,10 +5,29 @@ import { randomUUID } from "node:crypto";
|
|
|
5
5
|
import { isDeepStrictEqual } from "node:util";
|
|
6
6
|
import * as steer from "aiterm-steer-delivery";
|
|
7
7
|
import { resolveAgentBin } from "./agent-resolver.js";
|
|
8
|
+
import { lazyRelayExecutable } from "./lazy-relay.js";
|
|
8
9
|
import { SetupError, runSetupCommand } from "./setup-platform.js";
|
|
9
10
|
import { AITERM_PROFILE } from "./steer-profile.js";
|
|
10
11
|
export { powershellInvocation } from "./setup-platform.js";
|
|
11
12
|
const record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13
|
+
/**
|
|
14
|
+
* 既にある登録が、今から書く登録と同じ本体を指しているか。
|
|
15
|
+
* 直結(commandとargsが同じ)に加えて、中継(mcp-lazy)で包んだ同じ登録も同じと数える。
|
|
16
|
+
* 中継つきの形は、commandが`mcp-lazy`で始まる名前の実行ファイルで、argsが直結のcommand+args
|
|
17
|
+
* (中継のflagを`--`の前に置いた形も含む)。中継は本体を道具が呼ばれるまで起こさない。
|
|
18
|
+
* 連携元が全席の登録を中継つきで書いた後、1席が引数なしのsetupを流しても、直結へ戻さない。
|
|
19
|
+
*/
|
|
20
|
+
export function sameRegistration(command, args, registration) {
|
|
21
|
+
if (typeof command !== "string" || !Array.isArray(args))
|
|
22
|
+
return false;
|
|
23
|
+
if (command === registration.command && isDeepStrictEqual(args, registration.args))
|
|
24
|
+
return true;
|
|
25
|
+
if (!lazyRelayExecutable(command))
|
|
26
|
+
return false;
|
|
27
|
+
const direct = [registration.command, ...registration.args];
|
|
28
|
+
const separator = args.indexOf("--");
|
|
29
|
+
return isDeepStrictEqual(args, direct) || (separator >= 0 && isDeepStrictEqual(args.slice(separator + 1), direct));
|
|
30
|
+
}
|
|
12
31
|
export function mergeJsonMcp(file, registration) {
|
|
13
32
|
let current = {};
|
|
14
33
|
let target = file;
|
|
@@ -36,6 +55,9 @@ export function mergeJsonMcp(file, registration) {
|
|
|
36
55
|
}
|
|
37
56
|
const servers = (current.mcpServers ?? {});
|
|
38
57
|
const previous = record(servers.aiterm) ? servers.aiterm : {};
|
|
58
|
+
// 中継で包んだ同じ登録は、そのまま残す(直結へ書き戻さない)。
|
|
59
|
+
if (previous.command !== registration.command && sameRegistration(previous.command, previous.args, registration))
|
|
60
|
+
return "unchanged";
|
|
39
61
|
const updated = { ...previous, ...registration };
|
|
40
62
|
if (isDeepStrictEqual(servers.aiterm, updated))
|
|
41
63
|
return "unchanged";
|
|
@@ -144,8 +166,8 @@ export function configureIntegrations(home, registration, run = runSetupCommand,
|
|
|
144
166
|
if (!Array.isArray(servers))
|
|
145
167
|
throw new SetupError("config_readback_failed", "CodexのMCP一覧形式を確認できません");
|
|
146
168
|
const existing = servers.find((entry) => entry.name === "aiterm");
|
|
147
|
-
// 公式CLI
|
|
148
|
-
if (existing?.transport?.command
|
|
169
|
+
// 公式CLIの追加は登録を作り直し、利用者が足した項目(待ち時間など)を落とす。同じ登録(中継で包んだ物を含む)なら書き直さない。
|
|
170
|
+
if (!sameRegistration(existing?.transport?.command, existing?.transport?.args, registration)) {
|
|
149
171
|
const envArgs = Object.entries(existing?.transport?.env ?? {}).flatMap(([key, value]) => ["--env", `${key}=${value}`]);
|
|
150
172
|
run(executable, ["mcp", "add", "aiterm", ...envArgs, "--", registration.command, ...registration.args]);
|
|
151
173
|
const value = JSON.parse(run(executable, ["mcp", "get", "aiterm", "--json"]));
|
|
@@ -160,7 +182,7 @@ export function configureIntegrations(home, registration, run = runSetupCommand,
|
|
|
160
182
|
throw new SetupError("config_readback_failed", "GrokのMCP一覧形式を確認できません");
|
|
161
183
|
const existing = servers.find((entry) => entry.name === "aiterm" && entry.scope === "user");
|
|
162
184
|
// Codexと同じく、同じ登録なら書き直さない。
|
|
163
|
-
if (existing?.command
|
|
185
|
+
if (!sameRegistration(existing?.command, existing?.args, registration)) {
|
|
164
186
|
const envArgs = Object.entries(existing?.env ?? {}).flatMap(([key, value]) => ["--env", `${key}=${value}`]);
|
|
165
187
|
run(executable, ["mcp", "add", "--scope", "user", "aiterm", ...envArgs, "--", registration.command, ...registration.args]);
|
|
166
188
|
const value = JSON.parse(run(executable, ["mcp", "list", "--json"]));
|
package/docs/DESIGN.md
CHANGED
|
@@ -16,7 +16,7 @@ Claude/CursorのJSONは参照先を原子的に更新して変更前backupを
|
|
|
16
16
|
各AIの読戻しは登録内容の確認であり、端末の実動作はその前の公開MCP試験で確認する。
|
|
17
17
|
失敗は理由付きJSONと非ゼロ終了で返す。対応外の自動導入と全AI未検出を成功扱いしない。
|
|
18
18
|
global packageは、npmの現在のglobal rootか、実行中のNodeの既定のglobal rootにあるものを指す。
|
|
19
|
-
CodexとGrokは登録が同じなら公式CLI
|
|
19
|
+
CodexとGrokは登録が同じなら公式CLIで作り直さない。中継(`mcp-lazy`)で包んだ同じ登録も「同じ」と数え、4つのclientとも直結へ書き戻さない(ADR 0091)。`aiterm-setup --hooks-only`はClaude Code・Cursorの親配送hookだけを登録し、
|
|
20
20
|
依存準備、端末の実動作確認、MCP登録、Codex Steerに触れない。判断はADR 0077。
|
|
21
21
|
|
|
22
22
|
## Terminal model
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.53.
|
|
3
|
+
"version": "0.53.2",
|
|
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": [
|