aiterm-mcp 0.4.1 → 0.7.1
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/README.ja.md +15 -3
- package/README.md +15 -3
- package/dist/core.js +135 -9
- package/dist/index.js +39 -0
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
>
|
|
17
17
|
> *MCP = Model Context Protocol — Claude Code のようなツールが AI に機能を差し込むためのオープン標準。*
|
|
18
18
|
|
|
19
|
-
`pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list` の 6
|
|
19
|
+
`pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list` の PTY 6 ツールに加え、同じ永続端末の中にコーディングエージェントの TUI を起動する**対話エージェント起動 3 ツール**(`codex_agent` / `grok_agent` / `composer_agent`)。バックエンドは tmux なので、MCP サーバや AI クライアントが再起動してもセッションは生き残る。
|
|
20
20
|
|
|
21
21
|
**状態:** 開発継続中 · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
22
22
|
|
|
@@ -83,7 +83,7 @@ claude mcp add --scope user --transport stdio aiterm -- npx -y aiterm-mcp
|
|
|
83
83
|
Claude Code を再起動して、接続を確認:
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
|
-
/mcp # aiterm が connected・
|
|
86
|
+
/mcp # aiterm が connected・9 ツール公開、と出る
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
最初のセッション — 4 回の呼び出しで、1 個の永続端末:
|
|
@@ -111,7 +111,7 @@ claude mcp add --scope user --transport stdio aiterm -- aiterm-mcp
|
|
|
111
111
|
|
|
112
112
|
```mermaid
|
|
113
113
|
flowchart LR
|
|
114
|
-
AI["AI / MCP client"] -->|"pty_send"| S["aiterm-mcp<br/>stdio MCP ·
|
|
114
|
+
AI["AI / MCP client"] -->|"pty_send"| S["aiterm-mcp<br/>stdio MCP · 9 tools"]
|
|
115
115
|
S -->|"pty_read<br/>token-reduced"| AI
|
|
116
116
|
S -->|"tmux send-keys<br/>capture-pane"| P["one local PTY<br/>tmux · persistent"]
|
|
117
117
|
P -->|"ssh · docker · repl"| R["nested<br/>remote · container · REPL"]
|
|
@@ -148,6 +148,18 @@ flowchart LR
|
|
|
148
148
|
| `pty_close` | セッションを閉じる | `session_id` |
|
|
149
149
|
| `pty_list` | セッション一覧 | (なし) |
|
|
150
150
|
|
|
151
|
+
### 対話エージェント起動ツール
|
|
152
|
+
|
|
153
|
+
各ツールは特定ベンダーの対話型コーディングエージェント TUI を新しい永続 PTY の中に起動し、`session_id` を返す。以後は他のセッションと同様に `pty_read` / `pty_send` で操作する。モデルごとに 1 ツール=ツール名を見ればどのモデルか分かる。
|
|
154
|
+
|
|
155
|
+
| ツール | 起動するもの | 主な引数 |
|
|
156
|
+
| --- | --- | --- |
|
|
157
|
+
| `codex_agent` | Codex CLI(OpenAI・モデルは CLI の既定) | `prompt?`, `reasoning_effort?`, `cwd?`, `session_name?` |
|
|
158
|
+
| `grok_agent` | Grok Build の `grok-build` モデル(xAI) | `prompt?`, `reasoning_effort?`(`low`/`medium`/`high`/`xhigh`/`max`), `cwd?`, `session_name?` |
|
|
159
|
+
| `composer_agent` | Grok Build の `grok-composer-2.5-fast` モデル(xAI) | `grok_agent` と同じ |
|
|
160
|
+
|
|
161
|
+
各ベンダーの CLI が導入・認証済みであること(`codex_agent` は `codex`、Grok 系 2 つは `grok`)。バイナリは `CODEX_BIN` / `GROK_BIN` → `~/.local/bin/codex` / `~/.grok/bin/grok` → `PATH` の順で解決する。前提はすべて**セッション作成前に検証**する——不正な `reasoning_effort`・CLI 不在・実在しない `cwd` は明示エラーになり、セッションの残骸を残さない。
|
|
162
|
+
|
|
151
163
|
### 完了検出(4 層)
|
|
152
164
|
|
|
153
165
|
`pty_read({ wait: true })` は、プロセス終了 / `until` 正規表現一致 / 出力静止 ∧ シェル復帰(quiescence)/ timeout の 4 層で「コマンドが終わったか」を判定する。ネスト中(SSH 先)はシェル復帰判定が効かないので `until` でプロンプトを指定すると綺麗に判定できる。
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
>
|
|
17
17
|
> *MCP = Model Context Protocol — the open standard that lets tools like Claude Code plug capabilities into an AI.*
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Six PTY tools — `pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list` — plus three interactive **agent launchers** (`codex_agent` / `grok_agent` / `composer_agent`) that start a coding-agent TUI inside that same persistent terminal. The backend is **tmux**, so sessions survive even if the MCP server or the AI client restarts.
|
|
20
20
|
|
|
21
21
|
**Status:** actively maintained · runs on Linux · WSL2 · macOS · native Windows · MIT · see the [CHANGELOG](CHANGELOG.md).
|
|
22
22
|
|
|
@@ -83,7 +83,7 @@ claude mcp add --scope user --transport stdio aiterm -- npx -y aiterm-mcp
|
|
|
83
83
|
Restart Claude Code, then verify the connection:
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
|
-
/mcp # aiterm should show as connected, exposing
|
|
86
|
+
/mcp # aiterm should show as connected, exposing 9 tools
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
Your first session — four calls, one persistent terminal:
|
|
@@ -111,7 +111,7 @@ This registers it in `~/.claude.json`; you'll get an approval prompt the first t
|
|
|
111
111
|
|
|
112
112
|
```mermaid
|
|
113
113
|
flowchart LR
|
|
114
|
-
AI["AI / MCP client"] -->|"pty_send"| S["aiterm-mcp<br/>stdio MCP ·
|
|
114
|
+
AI["AI / MCP client"] -->|"pty_send"| S["aiterm-mcp<br/>stdio MCP · 9 tools"]
|
|
115
115
|
S -->|"pty_read<br/>token-reduced"| AI
|
|
116
116
|
S -->|"tmux send-keys<br/>capture-pane"| P["one local PTY<br/>tmux · persistent"]
|
|
117
117
|
P -->|"ssh · docker · repl"| R["nested<br/>remote · container · REPL"]
|
|
@@ -148,6 +148,18 @@ One PTY is the only primitive. Everything else — SSH, containers, REPLs — is
|
|
|
148
148
|
| `pty_close` | Close a session | `session_id` |
|
|
149
149
|
| `pty_list` | List sessions | (none) |
|
|
150
150
|
|
|
151
|
+
### Interactive agent launchers
|
|
152
|
+
|
|
153
|
+
Each launcher starts a specific vendor's interactive coding-agent TUI inside a fresh persistent PTY and returns its `session_id` — from there you drive it with plain `pty_read` / `pty_send`, exactly like any other session. One tool per model, so the tool name itself tells you which model you get.
|
|
154
|
+
|
|
155
|
+
| Tool | Launches | Key args |
|
|
156
|
+
| --- | --- | --- |
|
|
157
|
+
| `codex_agent` | Codex CLI (OpenAI; the CLI's default model) | `prompt?`, `reasoning_effort?`, `cwd?`, `session_name?` |
|
|
158
|
+
| `grok_agent` | Grok Build, model `grok-build` (xAI) | `prompt?`, `reasoning_effort?` (`low`/`medium`/`high`/`xhigh`/`max`), `cwd?`, `session_name?` |
|
|
159
|
+
| `composer_agent` | Grok Build, model `grok-composer-2.5-fast` (xAI) | same as `grok_agent` |
|
|
160
|
+
|
|
161
|
+
The vendor CLI must be installed and authenticated (`codex` for `codex_agent`; `grok` for both Grok tools). aiterm resolves the binary via `CODEX_BIN` / `GROK_BIN`, then `~/.local/bin/codex` / `~/.grok/bin/grok`, then `PATH`. All prerequisites are validated **before** a session is created — an invalid `reasoning_effort`, a missing CLI, or a nonexistent `cwd` fails with an explicit error and leaves no session behind.
|
|
162
|
+
|
|
151
163
|
### Completion detection (4 layers)
|
|
152
164
|
|
|
153
165
|
`pty_read({ wait: true })` decides "is the command done?" via four layers: process exit / `until` regex match / output is quiescent ∧ the shell is back (quiescence) / timeout. While nested (inside SSH), the "shell is back" check cannot fire, so pass `until` with the remote prompt for a clean decision.
|
package/dist/core.js
CHANGED
|
@@ -11,7 +11,7 @@ import { spawnSync } from "node:child_process";
|
|
|
11
11
|
import * as fs from "node:fs";
|
|
12
12
|
import * as path from "node:path";
|
|
13
13
|
import * as os from "node:os";
|
|
14
|
-
import { createHash } from "node:crypto";
|
|
14
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
15
15
|
import * as rtk from "./rtk.js";
|
|
16
16
|
// Windows ネイティブには tmux が無い。その場合だけ全 tmux 呼び出しを WSL 経由へ橋渡しする
|
|
17
17
|
// (POSIX = Linux/WSL2/macOS は従来どおり tmux を直接叩く)。
|
|
@@ -305,6 +305,11 @@ function autoName() {
|
|
|
305
305
|
i++;
|
|
306
306
|
return `t${i}`;
|
|
307
307
|
}
|
|
308
|
+
// 衝突リトライ用の乱数名。線形 t{i} は高並行だと全員が同じ「最小の空き番号」を見て衝突し続ける
|
|
309
|
+
// (TOCTOU)ため、2回目以降は 1600万通りの nonce 名に切り替えてリトライ上限内で実質確実に確保する。
|
|
310
|
+
function nonceName() {
|
|
311
|
+
return `t-${randomBytes(3).toString("hex")}`;
|
|
312
|
+
}
|
|
308
313
|
function captureScreen(name, lines) {
|
|
309
314
|
const args = ["capture-pane", "-p", "-J", "-t", name];
|
|
310
315
|
if (lines)
|
|
@@ -417,26 +422,49 @@ function rtkRewrite(text) {
|
|
|
417
422
|
// ---------------------------------------------------------------- 操作(return で返す / 失敗は AitermError)
|
|
418
423
|
export function openSession(name, shell = "bash") {
|
|
419
424
|
fs.mkdirSync(SOCKDIR, { recursive: true });
|
|
420
|
-
const nm = name || autoName();
|
|
421
|
-
assertSessionName(nm);
|
|
422
|
-
if (sessionExists(nm))
|
|
423
|
-
throw new AitermError(`session '${nm}' は既に存在します(list で確認)`, 2);
|
|
424
425
|
// macOS の /bin/bash は 3.2 で、起動時に zsh 移行バナーを出して最初の read を汚す。darwin かつ bash の
|
|
425
426
|
// ときだけ -e で環境変数を渡して抑止する。-e は tmux>=3.2 が必要だが macOS の Homebrew tmux は常に該当。
|
|
426
427
|
// (古い tmux<3.2 が残る Linux/WSL で -e を渡すと new-session が落ちるため、darwin 限定にする。)
|
|
427
428
|
const banner = process.platform === "darwin" && path.basename(shell) === "bash"
|
|
428
429
|
? ["-e", "BASH_SILENCE_DEPRECATION_WARNING=1"]
|
|
429
430
|
: [];
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
431
|
+
// 並行性対策: 複数エージェントが同時に名前なし open すると autoName が同じ t{i} を返し得る(TOCTOU)。
|
|
432
|
+
// 自動採番は初回のみ読みやすい t{i}、衝突したら乱数 nonce 名でリトライする(線形リトライは高並行で
|
|
433
|
+
// 全員が同じ空き番号に殺到してスケールしない)。明示名は既存ならエラー(呼び手責任=意図的共有と区別)。
|
|
434
|
+
const explicit = !!name;
|
|
435
|
+
let nm = name || autoName();
|
|
436
|
+
assertSessionName(nm);
|
|
437
|
+
for (let attempt = 0;; attempt++) {
|
|
438
|
+
if (attempt >= 20)
|
|
439
|
+
throw new AitermError("openSession: 自動採番のリトライ上限(tmux new-session が重複以外で失敗し続けている可能性)", 2);
|
|
440
|
+
if (sessionExists(nm)) {
|
|
441
|
+
if (explicit)
|
|
442
|
+
throw new AitermError(`session '${nm}' は既に存在します(list で確認)`, 2);
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
const r = tmux("new-session", "-d", "-s", nm, ...banner, "-f", "/dev/null", shell);
|
|
446
|
+
if (r.code === 0)
|
|
447
|
+
break;
|
|
448
|
+
// 自動採番かつ「重複名」由来の失敗(他エージェントが同名を先に取った)なら次名でリトライ。
|
|
449
|
+
const dup = /duplicate|already exists/i.test(r.stderr);
|
|
450
|
+
if (explicit || !dup)
|
|
451
|
+
throw new AitermError("tmux new-session 失敗: " + r.stderr.trim(), 2);
|
|
452
|
+
}
|
|
453
|
+
nm = nonceName();
|
|
454
|
+
assertSessionName(nm);
|
|
455
|
+
}
|
|
433
456
|
fs.closeSync(fs.openSync(logpath(nm), "a")); // touch
|
|
434
457
|
// pipe-pane の引数は tmux 内部の /bin/sh -c で再解釈される(argv ではない)。パスは単一引用符で包み、
|
|
435
458
|
// パス自身の ' は '\'' イディオムでエスケープする(名前は検証済みだが、Windows ユーザー名 O'Brien 等が
|
|
436
459
|
// 一時パスに ' を持ち込み redirect を壊すのを防ぐ。空白対策も兼ねる)。Windows は WSL から見える /mnt/c 形へ。
|
|
437
460
|
const pipeTarget = isWin ? toWslPath(logpath(nm)) : logpath(nm);
|
|
438
461
|
const quoted = `'${pipeTarget.replace(/'/g, "'\\''")}'`;
|
|
439
|
-
tmux("pipe-pane", "-t", nm, "-o", `cat >> ${quoted}`);
|
|
462
|
+
const pr = tmux("pipe-pane", "-t", nm, "-o", `cat >> ${quoted}`);
|
|
463
|
+
if (pr.code !== 0) {
|
|
464
|
+
// 配管に失敗した session は pty_read が永遠に空を返す=成功を装わない。作った session を片付けて明示エラー。
|
|
465
|
+
tmux("kill-session", "-t", nm);
|
|
466
|
+
throw new AitermError("tmux pipe-pane 失敗(出力ログを配管できないため session を破棄): " + pr.stderr.trim(), 2);
|
|
467
|
+
}
|
|
440
468
|
writeOffset(nm, 0);
|
|
441
469
|
return [nm, attachHint(nm)];
|
|
442
470
|
}
|
|
@@ -564,3 +592,101 @@ export function killAll() {
|
|
|
564
592
|
tmux("kill-server");
|
|
565
593
|
return "killed all sessions on this socket";
|
|
566
594
|
}
|
|
595
|
+
function resolveAgentBin(kind) {
|
|
596
|
+
const home = process.env.HOME ?? os.homedir();
|
|
597
|
+
const [envVar, rel, name] = kind === "codex"
|
|
598
|
+
? ["CODEX_BIN", [".local", "bin", "codex"], "codex"]
|
|
599
|
+
: ["GROK_BIN", [".grok", "bin", "grok"], "grok"];
|
|
600
|
+
const fromEnv = process.env[envVar];
|
|
601
|
+
if (fromEnv)
|
|
602
|
+
return fromEnv;
|
|
603
|
+
const cand = path.join(home, ...rel);
|
|
604
|
+
if (fs.existsSync(cand))
|
|
605
|
+
return cand;
|
|
606
|
+
const w = spawnSync(isWin ? "where" : "which", [name], {
|
|
607
|
+
encoding: "utf8",
|
|
608
|
+
timeout: 5000,
|
|
609
|
+
});
|
|
610
|
+
if (w.status === 0 && (w.stdout ?? "").trim())
|
|
611
|
+
return w.stdout.trim().split(/\r?\n/)[0];
|
|
612
|
+
return null;
|
|
613
|
+
}
|
|
614
|
+
// 単一引用符で安全に包む(' は '\'' で脱出)。send は raw:true で送るため自前で quote する。
|
|
615
|
+
function shq(s) {
|
|
616
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
617
|
+
}
|
|
618
|
+
function buildAgentCmd(kind, bin, effort, prompt) {
|
|
619
|
+
const parts = [shq(bin)];
|
|
620
|
+
if (kind === "codex") {
|
|
621
|
+
// codex は config override で reasoning effort(例: low/medium/high)を渡す。
|
|
622
|
+
if (effort)
|
|
623
|
+
parts.push("-c", `model_reasoning_effort=${shq(effort)}`);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
// grok / composer は同じ grok CLI をモデル違いで起動。effort は low/medium/high/xhigh/max。
|
|
627
|
+
parts.push("--model", kind === "composer" ? "grok-composer-2.5-fast" : "grok-build");
|
|
628
|
+
if (effort)
|
|
629
|
+
parts.push("--effort", shq(effort));
|
|
630
|
+
}
|
|
631
|
+
if (prompt)
|
|
632
|
+
parts.push(shq(prompt)); // 初手プロンプト(任意)
|
|
633
|
+
return parts.join(" ");
|
|
634
|
+
}
|
|
635
|
+
function agentLabel(kind) {
|
|
636
|
+
return kind === "composer"
|
|
637
|
+
? "Grok Build(Composer)"
|
|
638
|
+
: kind === "grok"
|
|
639
|
+
? "Grok Build(Grok)"
|
|
640
|
+
: "Codex";
|
|
641
|
+
}
|
|
642
|
+
// grok CLI の --effort が受ける値集合(codex は CLI 側の値集合が版で変わるため縛らない)。
|
|
643
|
+
const GROK_EFFORTS = new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
644
|
+
export function openAgent(kind, opts = {}) {
|
|
645
|
+
const label = agentLabel(kind);
|
|
646
|
+
// 前提検証は session を作る前に全部済ませる(失敗の残骸 session を作らない)。
|
|
647
|
+
// effort → bin → cwd の順: effort 検証は CLI 不在の端末でも同じ結果になる(テスト可能性)。
|
|
648
|
+
const effort = opts.reasoning_effort ?? null;
|
|
649
|
+
if (effort && kind !== "codex" && !GROK_EFFORTS.has(effort)) {
|
|
650
|
+
throw new AitermError(`reasoning_effort '${effort}' は不正です(${label} は low/medium/high/xhigh/max)`, 2);
|
|
651
|
+
}
|
|
652
|
+
const bin = resolveAgentBin(kind);
|
|
653
|
+
if (!bin) {
|
|
654
|
+
const where = kind === "codex" ? "~/.local/bin/codex" : "~/.grok/bin/grok";
|
|
655
|
+
throw new AitermError(`${label} の CLI が見つかりません(${where} か PATH が必要)`, 2);
|
|
656
|
+
}
|
|
657
|
+
if (opts.cwd) {
|
|
658
|
+
// cd 失敗はシェル内で静かに死に、エージェント未起動のまま「起動した」と偽の成功を返してしまう。
|
|
659
|
+
// session を作る前に実在を検証して明示エラーにする。
|
|
660
|
+
let st = null;
|
|
661
|
+
try {
|
|
662
|
+
st = fs.statSync(opts.cwd);
|
|
663
|
+
}
|
|
664
|
+
catch {
|
|
665
|
+
st = null;
|
|
666
|
+
}
|
|
667
|
+
if (!st || !st.isDirectory()) {
|
|
668
|
+
throw new AitermError(`cwd '${opts.cwd}' がディレクトリとして存在しません`, 2);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
const [sid, hint] = openSession(opts.session_name ?? null, "bash");
|
|
672
|
+
const cmd = buildAgentCmd(kind, bin, effort, opts.prompt ?? null);
|
|
673
|
+
const full = opts.cwd ? `cd ${shq(opts.cwd)} && ${cmd}` : cmd;
|
|
674
|
+
try {
|
|
675
|
+
send(sid, full, { enter: true, mark: false, force: false, rtk: false, raw: true });
|
|
676
|
+
}
|
|
677
|
+
catch (e) {
|
|
678
|
+
// 起動コマンドを投入できなかった session は空のまま残る=残骸を作らない。片付けてから元エラーを伝える。
|
|
679
|
+
try {
|
|
680
|
+
closeSession(sid);
|
|
681
|
+
}
|
|
682
|
+
catch {
|
|
683
|
+
/* 片付け失敗より元エラーの伝達を優先 */
|
|
684
|
+
}
|
|
685
|
+
throw e;
|
|
686
|
+
}
|
|
687
|
+
return [
|
|
688
|
+
sid,
|
|
689
|
+
`${label} を session ${sid} で起動した。\n${hint}\n` +
|
|
690
|
+
`pty_read(${sid}) で TUI を読み、pty_send(${sid}, "...") で操作する(対話)。`,
|
|
691
|
+
];
|
|
692
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -135,6 +135,45 @@ server.registerTool("pty_list", {
|
|
|
135
135
|
return fail(e);
|
|
136
136
|
}
|
|
137
137
|
});
|
|
138
|
+
// 対話型エージェント起動ツール(モデルごとに1つ=ツール名/説明でどのモデルか一目で分かる)。
|
|
139
|
+
// いずれも永続端末に TUI を起動し session_id を返す。以後 pty_read/pty_send で対話操作する。
|
|
140
|
+
const agentEffortDesc = (grokLike) => "reasoning effort(思考レベル)。" +
|
|
141
|
+
(grokLike ? "low/medium/high/xhigh/max" : "low/medium/high 等") +
|
|
142
|
+
"。省略時は CLI 既定。";
|
|
143
|
+
function registerAgentTool(toolName, kind, desc, grokLike) {
|
|
144
|
+
server.registerTool(toolName, {
|
|
145
|
+
description: desc,
|
|
146
|
+
inputSchema: {
|
|
147
|
+
prompt: z.string().nullish().describe("起動時に渡す初手プロンプト(任意)。省略で素のTUI起動"),
|
|
148
|
+
// grok/composer の effort は有限集合=schema で拒否(session を作る前に弾く)。
|
|
149
|
+
// codex は CLI 側の値集合が版で変わるため縛らない(core 側も同方針)。
|
|
150
|
+
reasoning_effort: (grokLike ? z.enum(["low", "medium", "high", "xhigh", "max"]) : z.string())
|
|
151
|
+
.nullish()
|
|
152
|
+
.describe(agentEffortDesc(grokLike)),
|
|
153
|
+
cwd: z.string().nullish().describe("作業ディレクトリ(対象リポのルート等・任意)"),
|
|
154
|
+
session_name: z.string().nullish().describe("セッション名(省略で自動採番)"),
|
|
155
|
+
},
|
|
156
|
+
}, async ({ prompt, reasoning_effort, cwd, session_name }) => {
|
|
157
|
+
try {
|
|
158
|
+
const [sid, hint] = core.openAgent(kind, {
|
|
159
|
+
prompt: prompt ?? undefined,
|
|
160
|
+
reasoning_effort: reasoning_effort ?? undefined,
|
|
161
|
+
cwd: cwd ?? undefined,
|
|
162
|
+
session_name: session_name ?? undefined,
|
|
163
|
+
});
|
|
164
|
+
return ok(`session_id: ${sid}\n${hint}`);
|
|
165
|
+
}
|
|
166
|
+
catch (e) {
|
|
167
|
+
return fail(e);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
registerAgentTool("codex_agent", "codex", "【Codex (OpenAI・モデルは Codex CLI の既定)】の対話エージェント TUI を永続端末に起動する。実装・レビュー・調査を対話で回す。" +
|
|
172
|
+
"起動後は pty_read で画面を読み pty_send で操作する。reasoning_effort を引数で指定可。", false);
|
|
173
|
+
registerAgentTool("grok_agent", "grok", "【Grok Build の Grok モデル (grok-build)】の対話エージェント TUI を永続端末に起動する。" +
|
|
174
|
+
"起動後は pty_read/pty_send で対話操作。reasoning_effort を引数で指定可。", true);
|
|
175
|
+
registerAgentTool("composer_agent", "composer", "【Grok Build の Composer モデル (grok-composer-2.5-fast)】の対話エージェント TUI を永続端末に起動する。" +
|
|
176
|
+
"起動後は pty_read/pty_send で対話操作。reasoning_effort を引数で指定可。", true);
|
|
138
177
|
async function main() {
|
|
139
178
|
const transport = new StdioServerTransport();
|
|
140
179
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"mcpName": "io.github.kitepon-rgb/aiterm-mcp",
|
|
5
5
|
"description": "AI-driven persistent terminal as a local stdio MCP server (tmux-backed). Holds one local PTY; SSH and containers are just commands you send into it. Token-reducing reads.",
|
|
6
6
|
"keywords": [
|