@leo000001/codex-mcp 0.2.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/CHANGELOG.md +40 -0
- package/CODE_OF_CONDUCT.md +26 -0
- package/CONTRIBUTING.md +43 -0
- package/LICENSE +21 -0
- package/README.md +354 -0
- package/SECURITY.md +28 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3168 -0
- package/dist/index.js.map +1 -0
- package/package.json +91 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Breaking Changes
|
|
11
|
+
|
|
12
|
+
- `approvalPolicy`, `sandbox`, and `effort` are now **required** parameters in the `codex` tool — callers must explicitly set based on their own permission level and task complexity
|
|
13
|
+
- `effort` parameter promoted from `advanced.effort` to top-level parameter in the `codex` tool
|
|
14
|
+
- `codex_reply` parameter `sandboxPolicy` renamed to `sandbox`
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- All MCP-visible text (tool descriptions, parameter descriptions, resource descriptions) streamlined for conciseness
|
|
19
|
+
- `effort` description now suggests adjusting based on task complexity
|
|
20
|
+
- `replyToSession` now persists successful `model` / `approvalPolicy` / `sandbox` / `cwd` overrides to session metadata
|
|
21
|
+
- Process `exit` / `error` paths now emit terminal `result` payloads so `codex_check(action=\"poll\")` always includes a terminal `result` in error states
|
|
22
|
+
- `SessionManager` now deduplicates concurrent `cancelSession` calls and prevents terminal sessions from re-entering `waiting_approval` on late server requests
|
|
23
|
+
- Approval and user-input timeout timers now call `.unref()` to avoid blocking process exit
|
|
24
|
+
- Documentation aligned with implementation details for event eviction and e2e guidance
|
|
25
|
+
- Tool input defaults are now defined in schema (`cursor`, `maxEvents`, `includeSensitive`, `advanced.approvalTimeoutMs`) and client-facing text avoids duplicated default descriptions
|
|
26
|
+
|
|
27
|
+
## [0.1.0] - 2026-02-15
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Initial release
|
|
32
|
+
- 4 MCP tools: `codex`, `codex_reply`, `codex_session`, `codex_check`
|
|
33
|
+
- Async non-blocking session management
|
|
34
|
+
- Three-layer permission model (approval policy, sandbox, async approval)
|
|
35
|
+
- Cursor-based event polling with pin-protected buffer
|
|
36
|
+
- Session lifecycle: create, reply, cancel, interrupt, fork
|
|
37
|
+
- Command execution and file change approval flow
|
|
38
|
+
- User input request handling
|
|
39
|
+
- Automatic session cleanup (idle/running/terminal timeouts)
|
|
40
|
+
- Zero-config startup via `~/.codex/config.toml` inheritance
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
This project is committed to providing a welcoming and harassment-free experience for everyone.
|
|
4
|
+
|
|
5
|
+
## Our Standards
|
|
6
|
+
|
|
7
|
+
Examples of behavior that contributes to a positive environment include:
|
|
8
|
+
- Being respectful and considerate in language and actions
|
|
9
|
+
- Giving and accepting constructive feedback
|
|
10
|
+
- Focusing on what is best for the community and project
|
|
11
|
+
|
|
12
|
+
Examples of unacceptable behavior include:
|
|
13
|
+
- Harassment, insults, or personal attacks
|
|
14
|
+
- Trolling, deliberate intimidation, or sustained disruption
|
|
15
|
+
- Publishing others' private information without explicit permission
|
|
16
|
+
|
|
17
|
+
## Scope
|
|
18
|
+
|
|
19
|
+
This Code of Conduct applies within all project spaces, including issues, pull requests, and discussions.
|
|
20
|
+
|
|
21
|
+
## Enforcement
|
|
22
|
+
|
|
23
|
+
If you experience or witness unacceptable behavior, please report it via the contact in `SECURITY.md`.
|
|
24
|
+
|
|
25
|
+
Project maintainers may remove, edit, or reject contributions that are not aligned with this Code of Conduct.
|
|
26
|
+
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Contributing to codex-mcp
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing!
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/xihuai18/codex-mcp.git
|
|
9
|
+
cd codex-mcp
|
|
10
|
+
npm install
|
|
11
|
+
npm run build
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Development Workflow
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm run typecheck # Type check
|
|
18
|
+
npm run build # Build
|
|
19
|
+
npm test # Run tests
|
|
20
|
+
npm run lint # Lint (ESLint)
|
|
21
|
+
npm run format:check # Check formatting (Prettier)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Pull Requests
|
|
25
|
+
|
|
26
|
+
1. Fork the repo and create a branch from `master` (or the repository default branch)
|
|
27
|
+
2. Make your changes
|
|
28
|
+
3. Ensure `npm run typecheck` and `npm run build` pass
|
|
29
|
+
4. Submit a PR with a clear description
|
|
30
|
+
|
|
31
|
+
## Reporting Issues
|
|
32
|
+
|
|
33
|
+
Use [GitHub Issues](https://github.com/xihuai18/codex-mcp/issues). Include:
|
|
34
|
+
- Steps to reproduce
|
|
35
|
+
- Expected vs actual behavior
|
|
36
|
+
- Node.js and Codex CLI versions
|
|
37
|
+
|
|
38
|
+
## Code Style
|
|
39
|
+
|
|
40
|
+
- TypeScript strict mode
|
|
41
|
+
- ESM modules
|
|
42
|
+
- Prefer `as const` tuples for shared constants
|
|
43
|
+
- Keep tool handlers thin — delegate to SessionManager
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 xihuai18
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# codex-mcp
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@leo000001/codex-mcp)
|
|
4
|
+
[](https://github.com/xihuai18/codex-mcp/blob/master/LICENSE)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
7
|
+
MCP server that wraps [OpenAI Codex](https://github.com/openai/codex) `app-server` — start coding agents, poll their progress, and manage permissions from any MCP client.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **4 tools, full capability** — `codex`, `codex_reply`, `codex_session`, `codex_check`
|
|
12
|
+
- **Async non-blocking** — sessions run in background, poll for results
|
|
13
|
+
- **Complete permission management** — three-layer model: approval policy, sandbox isolation, async approval arbitration
|
|
14
|
+
- **Zero config** — inherits your local `~/.codex/config.toml` automatically
|
|
15
|
+
- **Session management** — list, inspect, cancel, interrupt, fork sessions
|
|
16
|
+
- **Event streaming** — cursor-based pagination with pin-protected event buffer
|
|
17
|
+
- **Static read-only resources** — `codex-mcp:///server-info`, `codex-mcp:///compat-report`, `codex-mcp:///config`, `codex-mcp:///gotchas`, `codex-mcp:///quickstart`, `codex-mcp:///errors`
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
|
|
21
|
+
- [Node.js](https://nodejs.org) >= 18
|
|
22
|
+
- [OpenAI Codex CLI](https://github.com/openai/codex) installed and configured (`codex` in PATH)
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
### npx (no install)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx @leo000001/codex-mcp
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Global install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g @leo000001/codex-mcp
|
|
36
|
+
codex-mcp
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Windows shell wrapper (if needed)
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
pwsh -NoProfile -Command "npx -y @leo000001/codex-mcp"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### MCP Client Configuration
|
|
46
|
+
|
|
47
|
+
Add to your MCP client config (e.g. Claude Desktop, Cursor, etc.):
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"codex": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["-y", "@leo000001/codex-mcp"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### OpenAI Codex CLI
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
codex mcp add codex-mcp -- npx -y @leo000001/codex-mcp
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Or add to `~/.codex/config.toml`:
|
|
67
|
+
|
|
68
|
+
```toml
|
|
69
|
+
[mcp_servers.codex-mcp]
|
|
70
|
+
command = "npx"
|
|
71
|
+
args = ["-y", "@leo000001/codex-mcp"]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## STDIO Guard Modes
|
|
75
|
+
|
|
76
|
+
`codex-mcp` includes a startup preflight guard for stdout contamination risk.
|
|
77
|
+
|
|
78
|
+
- `CODEX_MCP_STDIO_MODE=auto` (default): run with warnings when risk is elevated
|
|
79
|
+
- `CODEX_MCP_STDIO_MODE=strict`: fail fast on blocking risks (e.g. TTY stdio), keep heuristic risks as warnings
|
|
80
|
+
- `CODEX_MCP_STDIO_MODE=off`: disable the preflight guard
|
|
81
|
+
|
|
82
|
+
Examples:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
CODEX_MCP_STDIO_MODE=strict npx -y @leo000001/codex-mcp
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```powershell
|
|
89
|
+
$env:CODEX_MCP_STDIO_MODE = "strict"; npx -y @leo000001/codex-mcp
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Tools
|
|
93
|
+
|
|
94
|
+
### `codex` — Start a new session
|
|
95
|
+
|
|
96
|
+
Start a Codex agent session asynchronously. Returns immediately with `sessionId`.
|
|
97
|
+
|
|
98
|
+
| Parameter | Type | Required | Description |
|
|
99
|
+
| ---------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
100
|
+
| `prompt` | string | Yes | Task or question for the Codex agent |
|
|
101
|
+
| `approvalPolicy` | string | Yes | Approval policy: `untrusted`, `on-failure`, `on-request`, `never` — caller must set based on its own permission level |
|
|
102
|
+
| `sandbox` | string | Yes | Sandbox mode: `read-only`, `workspace-write`, `danger-full-access` — caller must set based on its own permission level |
|
|
103
|
+
| `effort` | string | No | Reasoning effort: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`. Default: `low`; increase/decrease based on task complexity |
|
|
104
|
+
| `cwd` | string | No | Working directory. Default: server cwd |
|
|
105
|
+
| `model` | string | No | Model override. Default: from `~/.codex/config.toml` |
|
|
106
|
+
| `profile` | string | No | `config.toml` profile name (passed as `codex app-server -p`) |
|
|
107
|
+
| `advanced` | object | No | Low-frequency options (see below) |
|
|
108
|
+
|
|
109
|
+
<details>
|
|
110
|
+
<summary><code>advanced</code> object parameters (9 low-frequency parameters)</summary>
|
|
111
|
+
|
|
112
|
+
| Parameter | Type | Description |
|
|
113
|
+
| -------------------------------- | -------- | ----------------------------------------------------------------------------------------------- |
|
|
114
|
+
| `advanced.baseInstructions` | string | Replace default instructions (thread-level) |
|
|
115
|
+
| `advanced.developerInstructions` | string | Developer instructions (thread-level) |
|
|
116
|
+
| `advanced.personality` | string | Personality: `none`, `friendly`, `pragmatic` (default: from `~/.codex/config.toml`) |
|
|
117
|
+
| `advanced.summary` | string | Reasoning summary: `auto`, `concise`, `detailed`, `none` (default: from `~/.codex/config.toml`) |
|
|
118
|
+
| `advanced.config` | object | Override `config.toml` values (passed as `codex app-server -c key=value`) |
|
|
119
|
+
| `advanced.ephemeral` | boolean | Don't persist thread. Default: `false` |
|
|
120
|
+
| `advanced.outputSchema` | object | JSON Schema for structured output |
|
|
121
|
+
| `advanced.images` | string[] | Local image paths (adds `localImage` inputs) |
|
|
122
|
+
| `advanced.approvalTimeoutMs` | number | Auto-decline timeout (ms) for pending approvals. Default: `60000` |
|
|
123
|
+
|
|
124
|
+
</details>
|
|
125
|
+
|
|
126
|
+
**Returns:** `{ sessionId, threadId, status: "running" | "idle", pollInterval }`
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"prompt": "Fix the failing tests in src/",
|
|
131
|
+
"approvalPolicy": "on-request",
|
|
132
|
+
"sandbox": "workspace-write",
|
|
133
|
+
"effort": "high",
|
|
134
|
+
"cwd": "/path/to/project",
|
|
135
|
+
"model": "o4-mini"
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Resources
|
|
140
|
+
|
|
141
|
+
If your MCP client supports resources, this server exposes a few **read-only** resources:
|
|
142
|
+
|
|
143
|
+
- `codex-mcp:///server-info` (JSON): static server metadata (version/platform/runtime)
|
|
144
|
+
- `codex-mcp:///compat-report` (JSON): capability summary for cross-backend adapter compatibility
|
|
145
|
+
- `codex-mcp:///config` (Markdown): config mapping guide, including how to use `codex.advanced.config`
|
|
146
|
+
- `codex-mcp:///gotchas` (Markdown): practical limits/gotchas
|
|
147
|
+
- `codex-mcp:///quickstart` (Markdown): minimal workflow examples
|
|
148
|
+
- `codex-mcp:///errors` (Markdown): error code catalog + recovery hints
|
|
149
|
+
|
|
150
|
+
### `codex_reply` — Continue a session
|
|
151
|
+
|
|
152
|
+
Send a follow-up message to an existing session.
|
|
153
|
+
|
|
154
|
+
| Parameter | Type | Required | Description |
|
|
155
|
+
| ---------------- | ------ | -------- | ------------------------------------------------------------------------------- |
|
|
156
|
+
| `sessionId` | string | Yes | Session ID from `codex` |
|
|
157
|
+
| `prompt` | string | Yes | Follow-up message |
|
|
158
|
+
| `model` | string | No | Override model for this turn |
|
|
159
|
+
| `approvalPolicy` | string | No | Override approval policy |
|
|
160
|
+
| `effort` | string | No | Override reasoning effort (`none`, `minimal`, `low`, `medium`, `high`, `xhigh`) |
|
|
161
|
+
| `summary` | string | No | Override reasoning summary (`auto`, `concise`, `detailed`, `none`) |
|
|
162
|
+
| `personality` | string | No | Override personality (`none`, `friendly`, `pragmatic`) |
|
|
163
|
+
| `sandbox` | string | No | Override sandbox (`read-only`, `workspace-write`, `danger-full-access`) |
|
|
164
|
+
| `cwd` | string | No | Override working directory |
|
|
165
|
+
| `outputSchema` | object | No | JSON Schema for structured output |
|
|
166
|
+
|
|
167
|
+
**Returns:** `{ sessionId, threadId, status: "running" | "idle", pollInterval }`
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"sessionId": "sess_abc123",
|
|
172
|
+
"prompt": "Now add error handling for the edge cases"
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### `codex_session` — Manage sessions
|
|
177
|
+
|
|
178
|
+
List, inspect, cancel, interrupt, or fork sessions.
|
|
179
|
+
|
|
180
|
+
| Parameter | Type | Required | Description |
|
|
181
|
+
| ------------------ | ------- | ----------------------------- | ---------------------------------------------------------------------- |
|
|
182
|
+
| `action` | string | Yes | `"list"`, `"get"`, `"cancel"`, `"interrupt"`, or `"fork"` |
|
|
183
|
+
| `sessionId` | string | For get/cancel/interrupt/fork | Target session ID |
|
|
184
|
+
| `includeSensitive` | boolean | No | Include `cwd`/`profile`/`config`/`threadId` in `get`. Default: `false` |
|
|
185
|
+
|
|
186
|
+
**Returns:**
|
|
187
|
+
- `action="list"` → `{ sessions: PublicSessionInfo[] }`
|
|
188
|
+
- `action="get"` → `PublicSessionInfo` (or `SensitiveSessionInfo` when `includeSensitive=true`)
|
|
189
|
+
- `action="cancel"|"interrupt"` → `{ success: true, message }`
|
|
190
|
+
- `action="fork"` → `{ sessionId, threadId, status: "idle", pollInterval }`
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{ "action": "list" }
|
|
194
|
+
{ "action": "get", "sessionId": "sess_abc123", "includeSensitive": true }
|
|
195
|
+
{ "action": "cancel", "sessionId": "sess_abc123" }
|
|
196
|
+
{ "action": "interrupt", "sessionId": "sess_abc123" }
|
|
197
|
+
{ "action": "fork", "sessionId": "sess_abc123" }
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### `codex_check` — Poll events & respond
|
|
201
|
+
|
|
202
|
+
Query a running session for events, respond to approval requests, or answer user input.
|
|
203
|
+
|
|
204
|
+
| Parameter | Type | Required | Description |
|
|
205
|
+
| --------------------- | -------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
206
|
+
| `action` | string | Yes | `"poll"`, `"respond_permission"`, `"respond_approval"` (deprecated alias), or `"respond_user_input"` |
|
|
207
|
+
| `sessionId` | string | Yes | Target session ID |
|
|
208
|
+
| `cursor` | number | No | Event cursor for incremental polling (`action="poll"`). For `respond_*`, codex-mcp applies monotonic cursor progression: `max(cursor, sessionLastCursor)`. |
|
|
209
|
+
| `maxEvents` | number | No | Keep this small. `poll` default: `1` (minimum `1`; increase only for catch-up). `respond_*` default: `0` (recommended; compact ACK, no event replay). |
|
|
210
|
+
| `responseMode` | string | No | Response shaping mode: `minimal` (default), `delta_compact`, `full` |
|
|
211
|
+
| `pollOptions` | object | No | Optional controls: `includeEvents` (default `true`), `includeActions` (default `true`), `includeResult` (default `true`), `maxBytes` (default unlimited) |
|
|
212
|
+
| `requestId` | string | For respond_permission/user_input | Request ID from `actions[]` |
|
|
213
|
+
| `decision` | string | For respond_permission | For command approvals: `"accept"`, `"acceptForSession"`, `"acceptWithExecpolicyAmendment"`, `"decline"`, `"cancel"`; for file changes: `"accept"`, `"acceptForSession"`, `"decline"`, `"cancel"` |
|
|
214
|
+
| `execpolicyAmendment` | string[] | For acceptWithExecpolicyAmendment | Exec policy amendment list (required when `decision="acceptWithExecpolicyAmendment"`) |
|
|
215
|
+
| `denyMessage` | string | No | Internal note on deny (not sent to app-server) |
|
|
216
|
+
| `answers` | object | For respond_user_input | For `respond_user_input`: `questionId -> { answers: string[] }` |
|
|
217
|
+
|
|
218
|
+
**Returns (poll and respond_*):** `{ sessionId, status, pollInterval?, cursorResetTo?, events, nextCursor, actions?, result? }`
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{ "action": "poll", "sessionId": "sess_abc123", "cursor": 0 }
|
|
222
|
+
{
|
|
223
|
+
"action": "respond_permission",
|
|
224
|
+
"sessionId": "sess_abc123",
|
|
225
|
+
"requestId": "req_xyz",
|
|
226
|
+
"decision": "accept"
|
|
227
|
+
}
|
|
228
|
+
{
|
|
229
|
+
"action": "respond_user_input",
|
|
230
|
+
"sessionId": "sess_abc123",
|
|
231
|
+
"requestId": "req_abc",
|
|
232
|
+
"answers": { "question_id": { "answers": ["choice_1"] } }
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Event Polling Semantics
|
|
237
|
+
|
|
238
|
+
`codex_check(action="poll")` returns an append-only event stream with cursor pagination:
|
|
239
|
+
|
|
240
|
+
- `cursor`: the first event id you want (use the previous `nextCursor`)
|
|
241
|
+
- `nextCursor`: pass this back on the next poll
|
|
242
|
+
- `cursorResetTo`: when present, older events were evicted; restart from this cursor to avoid gaps
|
|
243
|
+
- `maxEvents`: max events returned per call
|
|
244
|
+
- If `cursor` is omitted, codex-mcp continues from that session's last consumed cursor.
|
|
245
|
+
- If `responseMode` is omitted, codex-mcp uses `minimal`.
|
|
246
|
+
- `pollOptions.includeEvents/includeActions/includeResult` default to `true`.
|
|
247
|
+
- `pollOptions.maxBytes` is optional and enforces best-effort payload truncation (`truncated`, `truncatedFields`).
|
|
248
|
+
- `respond_*` defaults to compact ACK (`events: []`, no cursor advance) unless you explicitly pass `maxEvents`.
|
|
249
|
+
- `poll` defaults to `maxEvents=1` to keep payloads small; increase temporarily (for example `10-20`) when you need to catch up faster.
|
|
250
|
+
- If `poll` is called with `maxEvents=0`, codex-mcp treats it as `1` to avoid no-op polling loops.
|
|
251
|
+
- For `respond_*`, prefer `maxEvents=0` instead of `1`: `0` keeps approval ACK minimal and avoids consuming/replaying stream events in the same call. Use `1-5` only when you explicitly need immediate events.
|
|
252
|
+
- For `poll`, keep windows small to reduce payload spikes and context pressure.
|
|
253
|
+
|
|
254
|
+
Event types include `output`, `progress`, `approval_request`, `approval_result`, `result`, `error`.
|
|
255
|
+
Approvals/results/errors are pinned to reduce eviction risk.
|
|
256
|
+
|
|
257
|
+
## Approvals & User Input
|
|
258
|
+
|
|
259
|
+
When the agent requests approval or user input, `poll` includes an `actions[]` list. Respond with:
|
|
260
|
+
|
|
261
|
+
- `respond_permission`: `decision` is one of `accept`, `acceptForSession`, `decline`, `cancel`.
|
|
262
|
+
- For command approvals, `acceptWithExecpolicyAmendment` is supported and requires `execpolicyAmendment`.
|
|
263
|
+
- `respond_approval` is still accepted as a deprecated alias for `respond_permission`.
|
|
264
|
+
- `respond_user_input`: send `answers` keyed by `questionId`.
|
|
265
|
+
|
|
266
|
+
Pending approvals auto-decline after `advanced.approvalTimeoutMs`.
|
|
267
|
+
|
|
268
|
+
## Session Lifecycle & Cleanup
|
|
269
|
+
|
|
270
|
+
Sessions auto-clean up in the background:
|
|
271
|
+
|
|
272
|
+
- `idle` > 30 minutes → cancelled
|
|
273
|
+
- `running`/`waiting_approval` > 4 hours → cancelled
|
|
274
|
+
- `cancelled`/`error` > 5 minutes → removed from memory
|
|
275
|
+
|
|
276
|
+
## Error Model
|
|
277
|
+
|
|
278
|
+
Tools return errors as:
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{ "content": [{ "type": "text", "text": "Error [CODE]: message" }], "isError": true }
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Common codes include `INVALID_ARGUMENT`, `SESSION_NOT_FOUND`, `SESSION_BUSY`, `SESSION_NOT_RUNNING`, `REQUEST_NOT_FOUND`, `CANCELLED`, `INTERNAL`.
|
|
285
|
+
|
|
286
|
+
## Client compatibility notes
|
|
287
|
+
|
|
288
|
+
- Tool responses follow `@modelcontextprotocol/sdk`'s `CallToolResult` contract: `content` (JSON text for wide compatibility), optional `structuredContent` (the canonical object), and `isError`. `structuredContent` is always object-shaped; when a tool returns a scalar/array, codex-mcp wraps it as `{ "value": ... }`. Claude Desktop and other clients tend to surface the `content` text directly, which shows the raw JSON blob, so they should fall back to `structuredContent` when they want typed data (Cursor already does this automatically whenever structured output is available).
|
|
289
|
+
- When an operation fails we set `isError: true` and return `Error [CODE]: message` in the `content` array instead of raising an MCP transport error. This keeps the STDIO channel healthy so Claude, Cursor, and other MCP clients stay connected even when a tool reports a problem.
|
|
290
|
+
- `codex-mcp` uses the MCP stdio transport (`src/index.ts`), so stdout is reserved for newline-delimited JSON and all diagnostics go to stderr. Anything else on stdout—including shell/profile banners (e.g., PowerShell's oh-my-posh warning) or CLI wrappers that print prompts—will break the MCP handshake for Claude/Cursor. Run `pwsh -NoProfile`, disable profile banners, or wrap the command so stdout stays quiet before piping it into the client.
|
|
291
|
+
- Windows command execution inside `codex app-server` may still inherit PowerShell profile side effects in some environments. This cannot be filtered by codex-mcp once emitted on stdout; if command turns are noisy or fail with profile errors, clean your PowerShell profile and prefer `approvalPolicy="on-failure"` / `"never"` to reduce approval churn.
|
|
292
|
+
- If Windows command output shows mojibake, enforce UTF-8 in the shell (`chcp 65001` and `$OutputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()`).
|
|
293
|
+
- Startup guard behavior is controlled by `CODEX_MCP_STDIO_MODE` (`auto`/`strict`/`off`). Use `strict` in CI or hardened environments to fail fast on blocking contamination risks (while still surfacing heuristic risk warnings).
|
|
294
|
+
- Retryable transport/API interruptions are emitted as `progress` events with `data.method="codex-mcp/reconnect"` and `willRetry=true`, so clients can surface reconnect state without treating it as terminal failure.
|
|
295
|
+
- Approval/user-input flows rely on the `actions[]` array returned by `codex_check(action="poll")`. Claude and Cursor render approval buttons from this payload, so they need to poll at `pollInterval`, honour `cursorResetTo`, and reply within `approvalTimeoutMs` to avoid automatic declines.
|
|
296
|
+
|
|
297
|
+
## Typical Workflow
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
1. codex(prompt="Fix bug X") → { sessionId, threadId, status: "running" }
|
|
301
|
+
2. codex_check(action="poll", ...) → events[], status, actions[]
|
|
302
|
+
3. codex_check(action="respond_permission", decision="accept") (if needed)
|
|
303
|
+
4. codex_check(action="poll", ...) → result when status="idle"
|
|
304
|
+
5. codex_reply(prompt="Also add tests") → new turn starts
|
|
305
|
+
6. codex_check(action="poll", ...) → poll until done
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Permission Model
|
|
309
|
+
|
|
310
|
+
Three layers of protection:
|
|
311
|
+
|
|
312
|
+
| Layer | Mechanism | Options |
|
|
313
|
+
| ----- | --------------- | ---------------------------------------------------------- |
|
|
314
|
+
| 0 | Approval Policy | `never`, `on-failure`, `on-request`, `untrusted` |
|
|
315
|
+
| 1 | Sandbox | `read-only`, `workspace-write`, `danger-full-access` |
|
|
316
|
+
| 2 | Async Approval | Command execution + file change approval via `codex_check` |
|
|
317
|
+
|
|
318
|
+
## Architecture
|
|
319
|
+
|
|
320
|
+
> **Same-platform assumption**: codex-mcp assumes the MCP client and server run on the same machine. All communication uses stdio (local IPC), child processes share the local filesystem and `~/.codex/config.toml`, and `cwd` paths refer to the local filesystem.
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
MCP Client ←stdio→ codex-mcp server ←stdio→ codex app-server ←→ Codex Agent
|
|
324
|
+
(same machine, stdio transport)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Each session spawns an independent `codex app-server` child process. The MCP server translates between MCP tool calls and the app-server's JSON-RPC protocol.
|
|
328
|
+
|
|
329
|
+
## Development
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
git clone https://github.com/xihuai18/codex-mcp.git
|
|
333
|
+
cd codex-mcp
|
|
334
|
+
npm install
|
|
335
|
+
npm run build
|
|
336
|
+
npm run typecheck
|
|
337
|
+
npm test
|
|
338
|
+
npm run check:stdio
|
|
339
|
+
npm run check:stdio:strict
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
End-to-end local test plan (after installing/configuring in an MCP client):
|
|
343
|
+
- Full guide (LLM operator handbook): `docs/E2E_LOCAL_TEST_PLAN.md`
|
|
344
|
+
- Quick English checklist: run `codex` → poll with `codex_check(action="poll")` → respond via `respond_permission`/`respond_user_input` if `actions[]` appears → continue polling until `status` is `idle`/`error`/`cancelled`.
|
|
345
|
+
|
|
346
|
+
## Project Policies
|
|
347
|
+
|
|
348
|
+
- [Contributing](CONTRIBUTING.md)
|
|
349
|
+
- [Security](SECURITY.md)
|
|
350
|
+
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
|
351
|
+
|
|
352
|
+
## License
|
|
353
|
+
|
|
354
|
+
[MIT](LICENSE)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|---------|-----------|
|
|
7
|
+
| 0.1.x | Yes |
|
|
8
|
+
| < 0.1.0 | No |
|
|
9
|
+
|
|
10
|
+
Only the latest released minor line receives security fixes. Critical fixes are backported to the latest two patch releases in that supported minor line.
|
|
11
|
+
|
|
12
|
+
## Reporting a Vulnerability
|
|
13
|
+
|
|
14
|
+
If you discover a security vulnerability, please report it responsibly:
|
|
15
|
+
|
|
16
|
+
1. **Do not** open a public issue
|
|
17
|
+
2. Use GitHub's private vulnerability reporting (Security Advisories → "Report a vulnerability")
|
|
18
|
+
3. Include a description of the vulnerability and steps to reproduce
|
|
19
|
+
|
|
20
|
+
You should receive a response within 48 hours.
|
|
21
|
+
|
|
22
|
+
## Security Considerations
|
|
23
|
+
|
|
24
|
+
- codex-mcp assumes the MCP client and server run on the same machine (stdio transport, shared filesystem). It is not designed for remote/cross-machine deployment.
|
|
25
|
+
- codex-mcp spawns `codex app-server` child processes that can execute commands on your system
|
|
26
|
+
- Always use appropriate `approvalPolicy` and `sandbox` settings
|
|
27
|
+
- The `danger-full-access` sandbox mode grants unrestricted system access — use with caution
|
|
28
|
+
- Approval requests auto-decline after 60 seconds by default
|
package/dist/index.d.ts
ADDED