codex-custom-mcp 1.0.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/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # Codex MCP Server
2
+
3
+ 自定义的 OpenAI Codex MCP 服务器,解决官方 MCP 不返回 `conversationId` 的问题。
4
+
5
+ ## 功能
6
+
7
+ 提供两个工具:
8
+
9
+ | 工具 | 功能 | 说明 |
10
+ |------|------|------|
11
+ | `codex_run` | 执行新任务 | 可选返回 conversationId |
12
+ | `codex_continue` | 继续会话 | 使用之前的 conversationId |
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ cd /Users/edy/杂项/codex-mcp-server
18
+ npm install
19
+ npm run build
20
+ ```
21
+
22
+ ## 配置到 Claude Code
23
+
24
+ ```bash
25
+ claude mcp add codex-custom --scope user -- node /Users/edy/杂项/codex-mcp-server/dist/index.js
26
+ ```
27
+
28
+ 验证配置:
29
+ ```bash
30
+ claude mcp list
31
+ ```
32
+
33
+ ## 使用方式
34
+
35
+ ### 1. 简单任务(和官方一样)
36
+
37
+ ```
38
+ codex_run: { prompt: "计算 1+1" }
39
+ → "2"
40
+ ```
41
+
42
+ ### 2. 需要后续继续的任务
43
+
44
+ 加上 `return_conversation_id: true` 参数:
45
+
46
+ ```
47
+ codex_run: {
48
+ prompt: "记住这个单词:APPLE",
49
+ return_conversation_id: true
50
+ }
51
+ → "好的,我记住了。\n\n---\nconversationId: 019b7863-5522-7750-9646-1ba7461efc97"
52
+ ```
53
+
54
+ ### 3. 继续对话
55
+
56
+ 使用之前返回的 `conversationId`:
57
+
58
+ ```
59
+ codex_continue: {
60
+ conversation_id: "019b7863-5522-7750-9646-1ba7461efc97",
61
+ prompt: "你记住的单词是什么?"
62
+ }
63
+ → "APPLE"
64
+ ```
65
+
66
+ ## 工具参数详解
67
+
68
+ ### codex_run
69
+
70
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
71
+ |------|------|------|--------|------|
72
+ | `prompt` | string | ✅ | - | 任务描述 |
73
+ | `model` | string | ❌ | - | 模型名称,如 `o3`, `o4-mini` |
74
+ | `cwd` | string | ❌ | - | 工作目录路径 |
75
+ | `sandbox` | enum | ❌ | `danger-full-access` | 沙箱模式:`read-only`, `workspace-write`, `danger-full-access` |
76
+ | `approval_policy` | enum | ❌ | `never` | 审批策略:`untrusted`, `on-failure`, `on-request`, `never` |
77
+ | `return_conversation_id` | boolean | ❌ | `false` | 是否返回 conversationId |
78
+
79
+ ### codex_continue
80
+
81
+ | 参数 | 类型 | 必填 | 说明 |
82
+ |------|------|------|------|
83
+ | `conversation_id` | string | ✅ | 之前返回的会话 ID |
84
+ | `prompt` | string | ✅ | 继续的任务描述 |
85
+
86
+ ## 项目结构
87
+
88
+ ```
89
+ codex-mcp-server/
90
+ ├── src/
91
+ │ └── index.ts # MCP 服务器源码
92
+ ├── dist/
93
+ │ └── index.js # 编译后的代码
94
+ ├── package.json
95
+ ├── tsconfig.json
96
+ └── README.md
97
+ ```
98
+
99
+ ## 开发
100
+
101
+ ```bash
102
+ # 开发模式(自动重新编译)
103
+ npm run dev
104
+
105
+ # 构建
106
+ npm run build
107
+
108
+ # 启动
109
+ npm start
110
+ ```
111
+
112
+ ## 注意事项
113
+
114
+ 1. **会话存储在内存中**:MCP 服务器重启后,之前的会话会丢失,需要重新创建
115
+ 2. **无需 Git 仓库**:已配置 `skipGitRepoCheck: true`,可在任意目录使用
116
+ 3. **重启生效**:修改代码后需要重新 `npm run build`,然后重启 Claude Code 会话
117
+
118
+ ## 与官方 MCP 的区别
119
+
120
+ | 特性 | 官方 `codex mcp-server` | 本项目 `codex-custom` |
121
+ |------|------------------------|----------------------|
122
+ | 返回 conversationId | ❌ 只在事件流中,最终响应不包含 | ✅ 可选返回 |
123
+ | 响应格式 | 只有文本 | 文本 + 可选 conversationId |
124
+ | Git 仓库要求 | 需要在 Git 仓库中 | 无需 |
125
+
126
+ ## 依赖
127
+
128
+ - `@modelcontextprotocol/sdk` - MCP SDK
129
+ - `@openai/codex-sdk` - Codex SDK
130
+ - `zod` - 参数验证
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Codex MCP Server - 自定义版本
4
+ *
5
+ * 解决官方 MCP 不返回 conversationId 的问题
6
+ *
7
+ * 工具:
8
+ * - codex_run: 执行新任务,返回结果 + conversationId
9
+ * - codex_continue: 使用 conversationId 继续会话
10
+ */
11
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Codex MCP Server - 自定义版本
4
+ *
5
+ * 解决官方 MCP 不返回 conversationId 的问题
6
+ *
7
+ * 工具:
8
+ * - codex_run: 执行新任务,返回结果 + conversationId
9
+ * - codex_continue: 使用 conversationId 继续会话
10
+ */
11
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
+ import { Codex } from "@openai/codex-sdk";
14
+ import { z } from "zod";
15
+ // 存储活跃会话
16
+ const activeThreads = new Map();
17
+ // Codex 实例
18
+ const codex = new Codex();
19
+ // MCP 服务器
20
+ const server = new McpServer({
21
+ name: "codex-mcp-server",
22
+ version: "1.0.0"
23
+ });
24
+ // ===== codex_run 工具 =====
25
+ const CodexRunSchema = z.object({
26
+ prompt: z.string().min(1).describe("任务描述"),
27
+ model: z.string().optional().describe("模型: o3, o4-mini 等"),
28
+ cwd: z.string().optional().describe("工作目录"),
29
+ sandbox: z.enum(["read-only", "workspace-write", "danger-full-access"]).optional().default("danger-full-access").describe("沙箱模式,默认 danger-full-access"),
30
+ approval_policy: z.enum(["untrusted", "on-failure", "on-request", "never"]).optional().default("never").describe("审批策略,默认 never(全自动)"),
31
+ return_conversation_id: z.boolean().optional().default(false).describe("是否返回 conversationId,用于后续继续对话")
32
+ }).strict();
33
+ server.registerTool("codex_run", {
34
+ title: "执行 Codex 任务",
35
+ description: `执行新的 Codex 任务,返回结果和 conversationId。
36
+
37
+ 返回格式:
38
+ {
39
+ "result": "Codex 回复",
40
+ "conversationId": "会话ID,用于继续对话"
41
+ }`,
42
+ inputSchema: CodexRunSchema,
43
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
44
+ }, async (params) => {
45
+ try {
46
+ const thread = codex.startThread({
47
+ model: params.model,
48
+ workingDirectory: params.cwd,
49
+ sandboxMode: params.sandbox,
50
+ approvalPolicy: params.approval_policy,
51
+ skipGitRepoCheck: true
52
+ });
53
+ const result = await thread.run(params.prompt);
54
+ const conversationId = thread.id || "unknown";
55
+ if (conversationId !== "unknown") {
56
+ activeThreads.set(conversationId, thread);
57
+ }
58
+ // 根据参数决定返回格式
59
+ if (params.return_conversation_id) {
60
+ return {
61
+ content: [{ type: "text", text: `${result.finalResponse || "完成"}\n\n---\nconversationId: ${conversationId}` }]
62
+ };
63
+ }
64
+ else {
65
+ return {
66
+ content: [{ type: "text", text: result.finalResponse || "完成" }]
67
+ };
68
+ }
69
+ }
70
+ catch (error) {
71
+ return {
72
+ content: [{ type: "text", text: `错误: ${error instanceof Error ? error.message : error}` }],
73
+ isError: true
74
+ };
75
+ }
76
+ });
77
+ // ===== codex_continue 工具 =====
78
+ const CodexContinueSchema = z.object({
79
+ conversation_id: z.string().min(1).describe("之前返回的 conversationId"),
80
+ prompt: z.string().min(1).describe("继续的任务描述")
81
+ }).strict();
82
+ server.registerTool("codex_continue", {
83
+ title: "继续 Codex 会话",
84
+ description: `使用 conversationId 继续之前的 Codex 会话。
85
+
86
+ 当你需要在同一个上下文中进行多轮对话时使用此工具。Codex 会记住之前的对话内容。
87
+
88
+ 参数:
89
+ - conversation_id (必填): 之前 codex_run 返回的会话ID
90
+ - prompt (必填): 继续的任务描述`,
91
+ inputSchema: CodexContinueSchema,
92
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
93
+ }, async (params) => {
94
+ try {
95
+ let thread;
96
+ if (activeThreads.has(params.conversation_id)) {
97
+ thread = activeThreads.get(params.conversation_id);
98
+ }
99
+ else {
100
+ thread = codex.resumeThread(params.conversation_id);
101
+ activeThreads.set(params.conversation_id, thread);
102
+ }
103
+ const result = await thread.run(params.prompt);
104
+ return {
105
+ content: [{ type: "text", text: result.finalResponse || "完成" }]
106
+ };
107
+ }
108
+ catch (error) {
109
+ return {
110
+ content: [{ type: "text", text: `错误: ${error instanceof Error ? error.message : error}` }],
111
+ isError: true
112
+ };
113
+ }
114
+ });
115
+ // 启动
116
+ async function main() {
117
+ const transport = new StdioServerTransport();
118
+ await server.connect(transport);
119
+ console.error("Codex MCP Server 已启动");
120
+ }
121
+ main().catch(e => { console.error("启动失败:", e); process.exit(1); });
122
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "codex-custom-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for OpenAI Codex with conversation/session support",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "codex-custom-mcp": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "start": "node dist/index.js",
15
+ "dev": "tsx watch src/index.ts",
16
+ "build": "tsc",
17
+ "clean": "rm -rf dist",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "codex",
23
+ "openai",
24
+ "claude",
25
+ "ai"
26
+ ],
27
+ "author": "edy",
28
+ "license": "MIT",
29
+ "dependencies": {
30
+ "@modelcontextprotocol/sdk": "^1.6.1",
31
+ "@openai/codex-sdk": "^0.77.0",
32
+ "zod": "^3.23.8"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.10.0",
36
+ "tsx": "^4.19.2",
37
+ "typescript": "^5.7.2"
38
+ },
39
+ "engines": {
40
+ "node": ">=18"
41
+ }
42
+ }