ai-cli-mcp 2.10.0 → 2.12.0
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/.github/workflows/watch-session-prs.yml +276 -0
- package/CHANGELOG.md +17 -0
- package/README.ja.md +104 -5
- package/README.md +104 -5
- package/dist/__tests__/app-cli.test.js +285 -0
- package/dist/__tests__/cli-bin-smoke.test.js +54 -0
- package/dist/__tests__/cli-builder.test.js +49 -2
- package/dist/__tests__/cli-process-service.test.js +233 -0
- package/dist/__tests__/cli-utils.test.js +109 -0
- package/dist/__tests__/error-cases.test.js +2 -1
- package/dist/__tests__/mcp-contract.test.js +195 -0
- package/dist/__tests__/process-management.test.js +15 -8
- package/dist/__tests__/server.test.js +29 -3
- package/dist/__tests__/validation.test.js +2 -2
- package/dist/__tests__/wait.test.js +31 -0
- package/dist/app/cli.js +304 -0
- package/dist/app/mcp.js +362 -0
- package/dist/bin/ai-cli-mcp.js +6 -0
- package/dist/bin/ai-cli.js +10 -0
- package/dist/cli-builder.js +29 -22
- package/dist/cli-process-service.js +328 -0
- package/dist/cli-utils.js +142 -88
- package/dist/cli.js +1 -1
- package/dist/model-catalog.js +50 -0
- package/dist/process-service.js +198 -0
- package/dist/server.js +3 -577
- package/docs/cli-architecture.md +275 -0
- package/package.json +3 -2
- package/src/__tests__/app-cli.test.ts +362 -0
- package/src/__tests__/cli-bin-smoke.test.ts +71 -0
- package/src/__tests__/cli-builder.test.ts +62 -3
- package/src/__tests__/cli-process-service.test.ts +278 -0
- package/src/__tests__/cli-utils.test.ts +132 -0
- package/src/__tests__/error-cases.test.ts +3 -4
- package/src/__tests__/mcp-contract.test.ts +250 -0
- package/src/__tests__/process-management.test.ts +15 -9
- package/src/__tests__/server.test.ts +27 -6
- package/src/__tests__/validation.test.ts +2 -2
- package/src/__tests__/wait.test.ts +38 -0
- package/src/app/cli.ts +373 -0
- package/src/app/mcp.ts +398 -0
- package/src/bin/ai-cli-mcp.ts +7 -0
- package/src/bin/ai-cli.ts +11 -0
- package/src/cli-builder.ts +32 -22
- package/src/cli-process-service.ts +415 -0
- package/src/cli-utils.ts +185 -99
- package/src/cli.ts +1 -1
- package/src/model-catalog.ts +60 -0
- package/src/process-service.ts +261 -0
- package/src/server.ts +3 -667
- package/.github/workflows/watch-codex-fork-pr.yml +0 -98
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
name: Watch Session PRs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '17 0 * * *'
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
issues: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
watch-codex-fork:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Check Codex fork PR and update issue
|
|
17
|
+
uses: actions/github-script@v7
|
|
18
|
+
env:
|
|
19
|
+
UPSTREAM_OWNER: openai
|
|
20
|
+
UPSTREAM_REPO: codex
|
|
21
|
+
UPSTREAM_PR_NUMBER: '13537'
|
|
22
|
+
TARGET_ISSUE_NUMBER: '7'
|
|
23
|
+
COMMENT_MARKER: '<!-- codex-fork-pr-13537-status -->'
|
|
24
|
+
READY_LABEL: '[ready]'
|
|
25
|
+
STOP_LABEL: '[stop]'
|
|
26
|
+
with:
|
|
27
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
28
|
+
script: |
|
|
29
|
+
const owner = process.env.UPSTREAM_OWNER;
|
|
30
|
+
const repo = process.env.UPSTREAM_REPO;
|
|
31
|
+
const pull_number = Number(process.env.UPSTREAM_PR_NUMBER);
|
|
32
|
+
const issue_number = Number(process.env.TARGET_ISSUE_NUMBER);
|
|
33
|
+
const marker = process.env.COMMENT_MARKER;
|
|
34
|
+
const readyLabel = process.env.READY_LABEL;
|
|
35
|
+
const stopLabel = process.env.STOP_LABEL;
|
|
36
|
+
|
|
37
|
+
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number });
|
|
38
|
+
const desiredLabel = pr.merged_at ? readyLabel : stopLabel;
|
|
39
|
+
const staleLabel = pr.merged_at ? stopLabel : readyLabel;
|
|
40
|
+
const { data: issue } = await github.rest.issues.get({
|
|
41
|
+
owner: context.repo.owner,
|
|
42
|
+
repo: context.repo.repo,
|
|
43
|
+
issue_number,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (!issue.labels.some((label) => label.name === desiredLabel)) {
|
|
47
|
+
await github.rest.issues.addLabels({
|
|
48
|
+
owner: context.repo.owner,
|
|
49
|
+
repo: context.repo.repo,
|
|
50
|
+
issue_number,
|
|
51
|
+
labels: [desiredLabel],
|
|
52
|
+
});
|
|
53
|
+
core.info(`Added label ${desiredLabel} to issue #${issue_number}.`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (issue.labels.some((label) => label.name === staleLabel)) {
|
|
57
|
+
try {
|
|
58
|
+
await github.rest.issues.removeLabel({
|
|
59
|
+
owner: context.repo.owner,
|
|
60
|
+
repo: context.repo.repo,
|
|
61
|
+
issue_number,
|
|
62
|
+
name: staleLabel,
|
|
63
|
+
});
|
|
64
|
+
core.info(`Removed label ${staleLabel} from issue #${issue_number}.`);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
core.warning(`Failed to remove label ${staleLabel}: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
core.summary
|
|
71
|
+
.addHeading('Codex PR status')
|
|
72
|
+
.addTable([
|
|
73
|
+
[
|
|
74
|
+
{ data: 'Field', header: true },
|
|
75
|
+
{ data: 'Value', header: true },
|
|
76
|
+
],
|
|
77
|
+
['PR', `${owner}/${repo}#${pr.number}`],
|
|
78
|
+
['Title', pr.title],
|
|
79
|
+
['State', pr.state],
|
|
80
|
+
['Merged', pr.merged_at ? 'yes' : 'no'],
|
|
81
|
+
['Merged at', pr.merged_at ?? 'not merged'],
|
|
82
|
+
['Updated at', pr.updated_at],
|
|
83
|
+
['URL', pr.html_url],
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
87
|
+
owner: context.repo.owner,
|
|
88
|
+
repo: context.repo.repo,
|
|
89
|
+
issue_number,
|
|
90
|
+
per_page: 100,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const existingComment = comments.find((comment) => comment.body?.includes(marker));
|
|
94
|
+
const body = [
|
|
95
|
+
marker,
|
|
96
|
+
'upstream PR `openai/codex#13537` status watcher',
|
|
97
|
+
'',
|
|
98
|
+
`- PR: ${pr.html_url}`,
|
|
99
|
+
`- State: ${pr.state}`,
|
|
100
|
+
`- Merged: ${pr.merged_at ? 'yes' : 'no'}`,
|
|
101
|
+
`- Merged at: ${pr.merged_at ?? 'not merged'}`,
|
|
102
|
+
`- Updated at: ${pr.updated_at}`,
|
|
103
|
+
'',
|
|
104
|
+
pr.merged_at
|
|
105
|
+
? 'This PR has been merged. `codex exec --fork <SESSION_ID> [PROMPT]` should become available once the change lands in the installed Codex version.'
|
|
106
|
+
: 'This PR is not merged yet. Non-interactive forking is still not available in released Codex builds.',
|
|
107
|
+
'A new session ID is expected when using `--fork`; `resume` itself continues the same session.',
|
|
108
|
+
].join('\n');
|
|
109
|
+
|
|
110
|
+
if (existingComment?.body === body) {
|
|
111
|
+
core.info(`Issue #${issue_number} status comment is already up to date.`);
|
|
112
|
+
await core.summary.addRaw(`No update needed: ${existingComment.html_url}\n`).write();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (existingComment) {
|
|
117
|
+
const { data: comment } = await github.rest.issues.updateComment({
|
|
118
|
+
owner: context.repo.owner,
|
|
119
|
+
repo: context.repo.repo,
|
|
120
|
+
comment_id: existingComment.id,
|
|
121
|
+
body,
|
|
122
|
+
});
|
|
123
|
+
core.info(`Updated issue #${issue_number}: ${comment.html_url}`);
|
|
124
|
+
await core.summary.addRaw(`Updated status comment: ${comment.html_url}\n`).write();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const { data: comment } = await github.rest.issues.createComment({
|
|
129
|
+
owner: context.repo.owner,
|
|
130
|
+
repo: context.repo.repo,
|
|
131
|
+
issue_number,
|
|
132
|
+
body,
|
|
133
|
+
});
|
|
134
|
+
core.info(`Created issue #${issue_number} status comment: ${comment.html_url}`);
|
|
135
|
+
await core.summary.addRaw(`Created status comment: ${comment.html_url}\n`).write();
|
|
136
|
+
|
|
137
|
+
watch-gemini-session-work:
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
steps:
|
|
140
|
+
- name: Check Gemini session PRs and update issue
|
|
141
|
+
uses: actions/github-script@v7
|
|
142
|
+
env:
|
|
143
|
+
UPSTREAM_OWNER: google-gemini
|
|
144
|
+
UPSTREAM_REPO: gemini-cli
|
|
145
|
+
TARGET_ISSUE_NUMBER: '16'
|
|
146
|
+
COMMENT_MARKER: '<!-- gemini-session-pr-status -->'
|
|
147
|
+
WATCH_PR_NUMBERS: '17921,19629,19994'
|
|
148
|
+
READY_PR_NUMBERS: '17921,19629'
|
|
149
|
+
READY_LABEL: '[ready]'
|
|
150
|
+
STOP_LABEL: '[stop]'
|
|
151
|
+
with:
|
|
152
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
153
|
+
script: |
|
|
154
|
+
const owner = process.env.UPSTREAM_OWNER;
|
|
155
|
+
const repo = process.env.UPSTREAM_REPO;
|
|
156
|
+
const issue_number = Number(process.env.TARGET_ISSUE_NUMBER);
|
|
157
|
+
const marker = process.env.COMMENT_MARKER;
|
|
158
|
+
const pullNumbers = process.env.WATCH_PR_NUMBERS.split(',').map((value) => Number(value.trim()));
|
|
159
|
+
const readyPullNumbers = process.env.READY_PR_NUMBERS.split(',').map((value) => Number(value.trim()));
|
|
160
|
+
const readyLabel = process.env.READY_LABEL;
|
|
161
|
+
const stopLabel = process.env.STOP_LABEL;
|
|
162
|
+
|
|
163
|
+
const pulls = await Promise.all(
|
|
164
|
+
pullNumbers.map(async (pull_number) => {
|
|
165
|
+
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number });
|
|
166
|
+
return pr;
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
169
|
+
const isReady = pulls.some((pr) => readyPullNumbers.includes(pr.number) && Boolean(pr.merged_at));
|
|
170
|
+
const desiredLabel = isReady ? readyLabel : stopLabel;
|
|
171
|
+
const staleLabel = isReady ? stopLabel : readyLabel;
|
|
172
|
+
|
|
173
|
+
const { data: issue } = await github.rest.issues.get({
|
|
174
|
+
owner: context.repo.owner,
|
|
175
|
+
repo: context.repo.repo,
|
|
176
|
+
issue_number,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
if (!issue.labels.some((label) => label.name === desiredLabel)) {
|
|
180
|
+
await github.rest.issues.addLabels({
|
|
181
|
+
owner: context.repo.owner,
|
|
182
|
+
repo: context.repo.repo,
|
|
183
|
+
issue_number,
|
|
184
|
+
labels: [desiredLabel],
|
|
185
|
+
});
|
|
186
|
+
core.info(`Added label ${desiredLabel} to issue #${issue_number}.`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (issue.labels.some((label) => label.name === staleLabel)) {
|
|
190
|
+
try {
|
|
191
|
+
await github.rest.issues.removeLabel({
|
|
192
|
+
owner: context.repo.owner,
|
|
193
|
+
repo: context.repo.repo,
|
|
194
|
+
issue_number,
|
|
195
|
+
name: staleLabel,
|
|
196
|
+
});
|
|
197
|
+
core.info(`Removed label ${staleLabel} from issue #${issue_number}.`);
|
|
198
|
+
} catch (error) {
|
|
199
|
+
core.warning(`Failed to remove label ${staleLabel}: ${error.message}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const lines = pulls.flatMap((pr) => [
|
|
204
|
+
`- \`${owner}/${repo}#${pr.number}\` ${pr.title}`,
|
|
205
|
+
` - State: ${pr.state}`,
|
|
206
|
+
` - Merged: ${pr.merged_at ? 'yes' : 'no'}`,
|
|
207
|
+
` - Merged at: ${pr.merged_at ?? 'not merged'}`,
|
|
208
|
+
` - Updated at: ${pr.updated_at}`,
|
|
209
|
+
` - URL: ${pr.html_url}`,
|
|
210
|
+
]);
|
|
211
|
+
|
|
212
|
+
core.summary
|
|
213
|
+
.addHeading('Gemini PR status')
|
|
214
|
+
.addTable([
|
|
215
|
+
[
|
|
216
|
+
{ data: 'PR', header: true },
|
|
217
|
+
{ data: 'State', header: true },
|
|
218
|
+
{ data: 'Merged', header: true },
|
|
219
|
+
{ data: 'Updated at', header: true },
|
|
220
|
+
],
|
|
221
|
+
...pulls.map((pr) => [
|
|
222
|
+
`${owner}/${repo}#${pr.number}`,
|
|
223
|
+
pr.state,
|
|
224
|
+
pr.merged_at ? 'yes' : 'no',
|
|
225
|
+
pr.updated_at,
|
|
226
|
+
]),
|
|
227
|
+
]);
|
|
228
|
+
|
|
229
|
+
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
230
|
+
owner: context.repo.owner,
|
|
231
|
+
repo: context.repo.repo,
|
|
232
|
+
issue_number,
|
|
233
|
+
per_page: 100,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const existingComment = comments.find((comment) => comment.body?.includes(marker));
|
|
237
|
+
const body = [
|
|
238
|
+
marker,
|
|
239
|
+
'upstream Gemini CLI session-related PR status watcher',
|
|
240
|
+
'',
|
|
241
|
+
'Tracked PRs:',
|
|
242
|
+
...lines,
|
|
243
|
+
'',
|
|
244
|
+
'Interpretation:',
|
|
245
|
+
'- `#19994` is a fix for resumed session ID stats mismatch, not a fork/new-session feature.',
|
|
246
|
+
'- `#17921` is the `/new` command proposal for starting a fresh session while preserving the previous one.',
|
|
247
|
+
'- `#19629` is the `--session-id` proposal for explicit session UUID control.',
|
|
248
|
+
'- Even if these land, that still does not automatically imply Codex-style headless fork semantics from `--resume` alone.',
|
|
249
|
+
].join('\n');
|
|
250
|
+
|
|
251
|
+
if (existingComment?.body === body) {
|
|
252
|
+
core.info(`Issue #${issue_number} Gemini status comment is already up to date.`);
|
|
253
|
+
await core.summary.addRaw(`No update needed: ${existingComment.html_url}\n`).write();
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (existingComment) {
|
|
258
|
+
const { data: comment } = await github.rest.issues.updateComment({
|
|
259
|
+
owner: context.repo.owner,
|
|
260
|
+
repo: context.repo.repo,
|
|
261
|
+
comment_id: existingComment.id,
|
|
262
|
+
body,
|
|
263
|
+
});
|
|
264
|
+
core.info(`Updated issue #${issue_number}: ${comment.html_url}`);
|
|
265
|
+
await core.summary.addRaw(`Updated status comment: ${comment.html_url}\n`).write();
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const { data: comment } = await github.rest.issues.createComment({
|
|
270
|
+
owner: context.repo.owner,
|
|
271
|
+
repo: context.repo.repo,
|
|
272
|
+
issue_number,
|
|
273
|
+
body,
|
|
274
|
+
});
|
|
275
|
+
core.info(`Created issue #${issue_number} status comment: ${comment.html_url}`);
|
|
276
|
+
await core.summary.addRaw(`Created status comment: ${comment.html_url}\n`).write();
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# [2.12.0](https://github.com/mkXultra/ai-cli-mcp/compare/v2.11.0...v2.12.0) (2026-03-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* ai-cliコマンドを追加しアーキテクチャをリファクタリング ([10a1209](https://github.com/mkXultra/ai-cli-mcp/commit/10a120933d5893d47e47001a165f0abc5e4557aa))
|
|
7
|
+
* CliProcessServiceとCLIサブコマンドを追加 ([0043ee4](https://github.com/mkXultra/ai-cli-mcp/commit/0043ee4a73bbf2d48f57b0b0ded8f12e29e8ebf2))
|
|
8
|
+
* CLIサブコマンドhelpとcleanupを追加し状態保存先を再設計 ([63dc1a2](https://github.com/mkXultra/ai-cli-mcp/commit/63dc1a238e9883cab04e818413576ad265b600ab))
|
|
9
|
+
* doctorとmodelsサブコマンドを追加しモデルカタログをモジュール化 ([15222e3](https://github.com/mkXultra/ai-cli-mcp/commit/15222e3c29c18bc16fa0bc7d6c4f3bdc621f6ff6))
|
|
10
|
+
|
|
11
|
+
# [2.11.0](https://github.com/mkXultra/ai-cli-mcp/compare/v2.10.0...v2.11.0) (2026-03-08)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* ClaudeモデルへのReasoning Effort(--effort)サポートを追加 ([ac6b8cc](https://github.com/mkXultra/ai-cli-mcp/commit/ac6b8cc47a06a2d207258e85cc21b1d4ce83e5b2))
|
|
17
|
+
|
|
1
18
|
# [2.10.0](https://github.com/mkXultra/ai-cli-mcp/compare/v2.9.1...v2.10.0) (2026-03-07)
|
|
2
19
|
|
|
3
20
|
|
package/README.ja.md
CHANGED
|
@@ -9,6 +9,10 @@ AI CLIツール(Claude, Codex, Gemini)をバックグラウンドプロセ
|
|
|
9
9
|
|
|
10
10
|
Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦戦していることに気づいたことはありませんか?このサーバーは、強力な統合 `run` ツールを提供し、複数のAIエージェントを活用してコーディングタスクをより効果的に処理できるようにします。
|
|
11
11
|
|
|
12
|
+
## デモ
|
|
13
|
+
|
|
14
|
+
[](https://github.com/mkXultra/ai-cli-mcp/releases/download/v2.11.0/demo-jp.mp4)
|
|
15
|
+
|
|
12
16
|
## 概要
|
|
13
17
|
|
|
14
18
|
このMCPサーバーは、LLMがAI CLIツールと対話するためのツールを提供します。MCPクライアントと統合することで、LLMは以下のことが可能になります:
|
|
@@ -45,6 +49,8 @@ Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦
|
|
|
45
49
|
> - `gpt-5.2-codex` で `README.md` にアーキテクチャの解説を追記
|
|
46
50
|
> 4. 最後に再び `wait` して、両方の結果をまとめてください。
|
|
47
51
|
|
|
52
|
+
[](https://github.com/mkXultra/ai-cli-mcp/releases/download/v2.11.0/demo-resume-jp.mp4)
|
|
53
|
+
|
|
48
54
|
## メリット
|
|
49
55
|
|
|
50
56
|
- **真の非同期マルチタスク**: エージェントの実行はバックグラウンドで行われ、即座に制御が戻ります。呼び出し元のAIは実行完了を待つことなく、並行して次のタスクの実行や別のエージェントの呼び出しを行うことができます。
|
|
@@ -61,9 +67,16 @@ Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦
|
|
|
61
67
|
|
|
62
68
|
## インストールと使い方
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
現在の主な使い方は 2 つあります。
|
|
71
|
+
|
|
72
|
+
- `ai-cli-mcp`: MCP サーバーの起動
|
|
73
|
+
- `ai-cli`: 人間向け CLI
|
|
74
|
+
|
|
75
|
+
### MCP 利用 (`npx`)
|
|
65
76
|
|
|
66
|
-
|
|
77
|
+
MCP サーバーとして使う場合は、`npx` 経由が推奨です。
|
|
78
|
+
|
|
79
|
+
#### MCP設定ファイルでnpxを使用する場合:
|
|
67
80
|
|
|
68
81
|
```json
|
|
69
82
|
"ai-cli-mcp": {
|
|
@@ -75,12 +88,47 @@ Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦
|
|
|
75
88
|
},
|
|
76
89
|
```
|
|
77
90
|
|
|
78
|
-
|
|
91
|
+
#### Claude CLI mcp add コマンドを使用する場合:
|
|
79
92
|
|
|
80
93
|
```bash
|
|
81
94
|
claude mcp add ai-cli '{"name":"ai-cli","command":"npx","args":["-y","ai-cli-mcp@latest"]}'
|
|
82
95
|
```
|
|
83
96
|
|
|
97
|
+
### 人間向け CLI 利用 (グローバルインストール)
|
|
98
|
+
|
|
99
|
+
シェルから `ai-cli` を直接使いたい場合は、グローバルインストールしてください。
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm install -g ai-cli-mcp
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
これで以下の 2 つのコマンドが使えるようになります。
|
|
106
|
+
|
|
107
|
+
- `ai-cli`
|
|
108
|
+
- `ai-cli-mcp`
|
|
109
|
+
|
|
110
|
+
例:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
ai-cli doctor
|
|
114
|
+
ai-cli models
|
|
115
|
+
ai-cli run --cwd "$PWD" --model sonnet --prompt "summarize this repository"
|
|
116
|
+
ai-cli ps
|
|
117
|
+
ai-cli result 12345
|
|
118
|
+
ai-cli wait 12345 --timeout 300
|
|
119
|
+
ai-cli kill 12345
|
|
120
|
+
ai-cli cleanup
|
|
121
|
+
ai-cli-mcp
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 人間向け CLI 利用 (`npx`)
|
|
125
|
+
|
|
126
|
+
公開パッケージ名はまだ `ai-cli-mcp` のままなので、`npx` で `ai-cli` を使う場合は次の形になります。
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npx -y --package ai-cli-mcp@latest ai-cli run --cwd "$PWD" --model sonnet --prompt "hello"
|
|
130
|
+
```
|
|
131
|
+
|
|
84
132
|
## 重要な初回セットアップ
|
|
85
133
|
|
|
86
134
|
### Claude CLIの場合:
|
|
@@ -112,6 +160,56 @@ gemini auth login
|
|
|
112
160
|
|
|
113
161
|
macOSでは、これらのツールを初めて実行する際にフォルダへのアクセス許可を求められる場合があります。最初の実行が失敗しても、2回目以降は動作するはずです。
|
|
114
162
|
|
|
163
|
+
## CLI コマンド
|
|
164
|
+
|
|
165
|
+
`ai-cli` は現在以下をサポートしています。
|
|
166
|
+
|
|
167
|
+
- `run`
|
|
168
|
+
- `ps`
|
|
169
|
+
- `result`
|
|
170
|
+
- `wait`
|
|
171
|
+
- `kill`
|
|
172
|
+
- `cleanup`
|
|
173
|
+
- `doctor`
|
|
174
|
+
- `models`
|
|
175
|
+
- `mcp`
|
|
176
|
+
|
|
177
|
+
基本的な流れ:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
ai-cli doctor
|
|
181
|
+
ai-cli models
|
|
182
|
+
ai-cli run --cwd "$PWD" --model codex-ultra --prompt "fix failing tests"
|
|
183
|
+
ai-cli ps
|
|
184
|
+
ai-cli wait 12345
|
|
185
|
+
ai-cli result 12345
|
|
186
|
+
ai-cli cleanup
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`run` の作業ディレクトリ指定は `--cwd` が基本です。互換性のために `--workFolder` / `--work-folder` も受け付けます。
|
|
190
|
+
|
|
191
|
+
`doctor` は CLI バイナリの存在確認と path 解決だけを行います。ログイン状態や利用規約同意までは確認しません。
|
|
192
|
+
|
|
193
|
+
## CLI の状態保存先
|
|
194
|
+
|
|
195
|
+
バックグラウンド実行した `ai-cli` の状態は、次のディレクトリに保存されます。
|
|
196
|
+
|
|
197
|
+
```text
|
|
198
|
+
~/.local/state/ai-cli/cwds/<normalized-cwd>/<pid>/
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
各 PID ディレクトリには以下が入ります。
|
|
202
|
+
|
|
203
|
+
- `meta.json`
|
|
204
|
+
- `stdout.log`
|
|
205
|
+
- `stderr.log`
|
|
206
|
+
|
|
207
|
+
完了済み・失敗済みの実行は `ai-cli cleanup` で削除できます。`running` のものは保持されます。
|
|
208
|
+
|
|
209
|
+
## 既知の制約
|
|
210
|
+
|
|
211
|
+
detached 実行された `ai-cli` の自然終了 exit code は、まだ永続化していません。そのため、CLI は出力と running/completed 状態は返せますが、自然終了したバックグラウンド実行の `exitCode` は現時点では保証しません。
|
|
212
|
+
|
|
115
213
|
## MCPクライアントへの接続
|
|
116
214
|
|
|
117
215
|
サーバーのセットアップ後、MCPクライアント(CursorやWindsurfなど)の設定ファイル(`mcp.json` や `mcp_config.json`)に設定を追加してください。
|
|
@@ -131,11 +229,11 @@ Claude CLI、Codex CLI、またはGemini CLIを使用してプロンプトを実
|
|
|
131
229
|
- `prompt_file` (string, 任意): プロンプトを含むファイルへのパス。`prompt` または `prompt_file` のいずれかが必須です。絶対パス、または `workFolder` からの相対パスが指定可能です。
|
|
132
230
|
- `workFolder` (string, 必須): CLIを実行する作業ディレクトリ。絶対パスである必要があります。
|
|
133
231
|
- **モデル (Models):**
|
|
134
|
-
- **Ultra エイリアス:** `claude-ultra
|
|
232
|
+
- **Ultra エイリアス:** `claude-ultra` (自動的に high effort に設定), `codex-ultra` (自動的に xhigh reasoning に設定), `gemini-ultra`
|
|
135
233
|
- Claude: `sonnet`, `sonnet[1m]`, `opus`, `opusplan`, `haiku`
|
|
136
234
|
- Codex: `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5`
|
|
137
235
|
- Gemini: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3-flash-preview`
|
|
138
|
-
- `reasoning_effort` (string, 任意): Codex
|
|
236
|
+
- `reasoning_effort` (string, 任意): Claude と Codex の推論制御。Claude では `--effort` を使います(許容値: "low", "medium", "high")。Codex では `model_reasoning_effort` を使います(許容値: "low", "medium", "high", "xhigh")。
|
|
139
237
|
- `session_id` (string, 任意): 以前のセッションを再開するためのセッションID。対応モデル: haiku, sonnet, opus, gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview。
|
|
140
238
|
|
|
141
239
|
### `wait`
|
|
@@ -167,6 +265,7 @@ PIDを指定して、実行中のAIエージェントプロセスを終了しま
|
|
|
167
265
|
## トラブルシューティング
|
|
168
266
|
|
|
169
267
|
- **"Command not found" (claude-code-mcp):** グローバルにインストールした場合、npmのグローバルbinディレクトリがシステムのPATHに含まれているか確認してください。`npx` を使用している場合、`npx` 自体が機能しているか確認してください。
|
|
268
|
+
- **"Command not found" (`ai-cli`):** グローバルインストール時は npm のグローバル bin ディレクトリが `PATH` に入っているか確認してください。`npx` の場合は `npx -y --package ai-cli-mcp@latest ai-cli ...` を使ってください。
|
|
170
269
|
- **"Command not found" (claude または ~/.claude/local/claude):** Claude CLIが正しくインストールされていることを確認してください。`claude/doctor` を実行するか、公式ドキュメントを確認してください。
|
|
171
270
|
- **権限の問題:** 「重要な初回セットアップ」の手順を実行したか確認してください。
|
|
172
271
|
- **サーバーからのJSONエラー:** `MCP_CLAUDE_DEBUG` が `true` の場合、エラーメッセージやログがMCPのJSON解析を妨げる可能性があります。通常動作時は `false` に設定してください。
|
package/README.md
CHANGED
|
@@ -11,6 +11,10 @@ An MCP (Model Context Protocol) server that allows running AI CLI tools (Claude,
|
|
|
11
11
|
|
|
12
12
|
Did you notice that Cursor sometimes struggles with complex, multi-step edits or operations? This server, with its powerful unified `run` tool, enables multiple AI agents to handle your coding tasks more effectively.
|
|
13
13
|
|
|
14
|
+
## Demo
|
|
15
|
+
|
|
16
|
+
[](https://github.com/mkXultra/ai-cli-mcp/releases/download/v2.11.0/demo.mp4)
|
|
17
|
+
|
|
14
18
|
## Overview
|
|
15
19
|
|
|
16
20
|
This MCP server provides tools that can be used by LLMs to interact with AI CLI tools. When integrated with MCP clients, it allows LLMs to:
|
|
@@ -44,6 +48,8 @@ You can reuse heavy context (like large codebases) using session IDs to save cos
|
|
|
44
48
|
> - Add architecture documentation to `README.md` using `gpt-5.2-codex`
|
|
45
49
|
> 4. Finally, `wait` again to combine both results.
|
|
46
50
|
|
|
51
|
+
[](https://github.com/mkXultra/ai-cli-mcp/releases/download/v2.11.0/demo-resume.mp4)
|
|
52
|
+
|
|
47
53
|
## Benefits
|
|
48
54
|
|
|
49
55
|
- **True Async Multitasking**: Agent execution happens in the background, returning control immediately. The calling AI can proceed with the next task or invoke another agent without waiting for completion.
|
|
@@ -60,9 +66,16 @@ The only prerequisite is that the AI CLI tools you want to use are locally insta
|
|
|
60
66
|
|
|
61
67
|
## Installation & Usage
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
There are now two primary ways to use this package:
|
|
70
|
+
|
|
71
|
+
- `ai-cli-mcp`: MCP server entrypoint
|
|
72
|
+
- `ai-cli`: human-facing CLI for background AI runs
|
|
73
|
+
|
|
74
|
+
### MCP usage with `npx`
|
|
64
75
|
|
|
65
|
-
|
|
76
|
+
The recommended way to use the MCP server is via `npx`.
|
|
77
|
+
|
|
78
|
+
#### Using npx in your MCP configuration:
|
|
66
79
|
|
|
67
80
|
```json
|
|
68
81
|
"ai-cli-mcp": {
|
|
@@ -74,12 +87,47 @@ The recommended way to use this server is by installing it by using `npx`.
|
|
|
74
87
|
},
|
|
75
88
|
```
|
|
76
89
|
|
|
77
|
-
|
|
90
|
+
#### Using Claude CLI mcp add command:
|
|
78
91
|
|
|
79
92
|
```bash
|
|
80
93
|
claude mcp add ai-cli '{"name":"ai-cli","command":"npx","args":["-y","ai-cli-mcp@latest"]}'
|
|
81
94
|
```
|
|
82
95
|
|
|
96
|
+
### Human CLI usage with global install
|
|
97
|
+
|
|
98
|
+
If you want to use the production CLI directly from your shell, install the package globally:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm install -g ai-cli-mcp
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This exposes both commands:
|
|
105
|
+
|
|
106
|
+
- `ai-cli`
|
|
107
|
+
- `ai-cli-mcp`
|
|
108
|
+
|
|
109
|
+
Examples:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
ai-cli doctor
|
|
113
|
+
ai-cli models
|
|
114
|
+
ai-cli run --cwd "$PWD" --model sonnet --prompt "summarize this repository"
|
|
115
|
+
ai-cli ps
|
|
116
|
+
ai-cli result 12345
|
|
117
|
+
ai-cli wait 12345 --timeout 300
|
|
118
|
+
ai-cli kill 12345
|
|
119
|
+
ai-cli cleanup
|
|
120
|
+
ai-cli-mcp
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Human CLI usage with `npx`
|
|
124
|
+
|
|
125
|
+
Because the published package name is still `ai-cli-mcp`, the shortest `npx` form for the CLI is:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx -y --package ai-cli-mcp@latest ai-cli run --cwd "$PWD" --model sonnet --prompt "hello"
|
|
129
|
+
```
|
|
130
|
+
|
|
83
131
|
## Important First-Time Setup
|
|
84
132
|
|
|
85
133
|
### For Claude CLI:
|
|
@@ -111,6 +159,56 @@ gemini auth login
|
|
|
111
159
|
|
|
112
160
|
macOS might ask for folder permissions the first time any of these tools run. If the first run fails, subsequent runs should work.
|
|
113
161
|
|
|
162
|
+
## CLI Commands
|
|
163
|
+
|
|
164
|
+
`ai-cli` currently supports:
|
|
165
|
+
|
|
166
|
+
- `run`
|
|
167
|
+
- `ps`
|
|
168
|
+
- `result`
|
|
169
|
+
- `wait`
|
|
170
|
+
- `kill`
|
|
171
|
+
- `cleanup`
|
|
172
|
+
- `doctor`
|
|
173
|
+
- `models`
|
|
174
|
+
- `mcp`
|
|
175
|
+
|
|
176
|
+
Example flow:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
ai-cli doctor
|
|
180
|
+
ai-cli models
|
|
181
|
+
ai-cli run --cwd "$PWD" --model codex-ultra --prompt "fix failing tests"
|
|
182
|
+
ai-cli ps
|
|
183
|
+
ai-cli wait 12345
|
|
184
|
+
ai-cli result 12345
|
|
185
|
+
ai-cli cleanup
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`run` accepts `--cwd` as the primary working-directory flag and also accepts the older aliases `--workFolder` / `--work-folder` for compatibility.
|
|
189
|
+
|
|
190
|
+
`doctor` checks only binary existence and path resolution. It does not verify login state or terms acceptance.
|
|
191
|
+
|
|
192
|
+
## CLI State Storage
|
|
193
|
+
|
|
194
|
+
Background CLI runs are stored under:
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
~/.local/state/ai-cli/cwds/<normalized-cwd>/<pid>/
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Each PID directory contains:
|
|
201
|
+
|
|
202
|
+
- `meta.json`
|
|
203
|
+
- `stdout.log`
|
|
204
|
+
- `stderr.log`
|
|
205
|
+
|
|
206
|
+
Use `ai-cli cleanup` to remove completed and failed runs. Running processes are preserved.
|
|
207
|
+
|
|
208
|
+
## Known Limitation
|
|
209
|
+
|
|
210
|
+
Detached `ai-cli` runs do not currently persist natural process exit codes. As a result, the CLI can report process output and running/completed state, but it does not yet guarantee `exitCode` for naturally finished background runs.
|
|
211
|
+
|
|
114
212
|
## Connecting to Your MCP Client
|
|
115
213
|
|
|
116
214
|
After setting up the server, add the configuration to your MCP client's settings file (e.g., `mcp.json` for Cursor, `mcp_config.json` for Windsurf).
|
|
@@ -130,11 +228,11 @@ Executes a prompt using Claude CLI, Codex CLI, or Gemini CLI. The appropriate CL
|
|
|
130
228
|
- `prompt_file` (string, optional): Path to a file containing the prompt. Either `prompt` or `prompt_file` is required. Can be absolute path or relative to `workFolder`.
|
|
131
229
|
- `workFolder` (string, required): The working directory for the CLI execution. Must be an absolute path.
|
|
132
230
|
**Models:**
|
|
133
|
-
- **Ultra Aliases:** `claude-ultra
|
|
231
|
+
- **Ultra Aliases:** `claude-ultra` (defaults to high effort), `codex-ultra` (defaults to xhigh reasoning), `gemini-ultra`
|
|
134
232
|
- Claude: `sonnet`, `sonnet[1m]`, `opus`, `opusplan`, `haiku`
|
|
135
233
|
- Codex: `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5`
|
|
136
234
|
- Gemini: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3-flash-preview`
|
|
137
|
-
- `reasoning_effort` (string, optional): Codex
|
|
235
|
+
- `reasoning_effort` (string, optional): Reasoning control for Claude and Codex. Claude uses `--effort` (allowed: "low", "medium", "high"). Codex uses `model_reasoning_effort` (allowed: "low", "medium", "high", "xhigh").
|
|
138
236
|
- `session_id` (string, optional): Optional session ID to resume a previous session. Supported for: haiku, sonnet, opus, gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview.
|
|
139
237
|
|
|
140
238
|
### `wait`
|
|
@@ -166,6 +264,7 @@ Terminates a running AI agent process by PID.
|
|
|
166
264
|
## Troubleshooting
|
|
167
265
|
|
|
168
266
|
- **"Command not found" (claude-code-mcp):** If installed globally, ensure the npm global bin directory is in your system's PATH. If using `npx`, ensure `npx` itself is working.
|
|
267
|
+
- **"Command not found" (`ai-cli`):** If installed globally, ensure your npm global bin directory is in `PATH`. If using `npx`, use `npx -y --package ai-cli-mcp@latest ai-cli ...`.
|
|
169
268
|
- **"Command not found" (claude or ~/.claude/local/claude):** Ensure the Claude CLI is installed correctly. Run `claude/doctor` or check its documentation.
|
|
170
269
|
- **Permissions Issues:** Make sure you've run the "Important First-Time Setup" step.
|
|
171
270
|
- **JSON Errors from Server:** If `MCP_CLAUDE_DEBUG` is `true`, error messages or logs might interfere with MCP's JSON parsing. Set to `false` for normal operation.
|