Cheap Labor
An MCP server that splits coding work between ChatGPT web (planning, review) and Codex CLI (implementation), enabling agentic workflows over a local repo with risk-gated execution and safety rails.
README
<!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 --> <a id="readme-top"></a>
<!-- PROJECT SHIELDS --> <p align="center"> <img src="https://img.shields.io/badge/Node.js-%3E%3D20-339933?style=for-the-badge&logo=nodedotjs&logoColor=white" /> <img src="https://img.shields.io/badge/TypeScript-7-3178C6?style=for-the-badge&logo=typescript&logoColor=white" /> </p>
<p align="center"> <img src="https://img.shields.io/badge/Platform-macOS%20%7C%20Linux-green?style=flat-square" /> <img src="https://img.shields.io/badge/License-MIT-blue?style=flat-square" /> </p>
<!-- PROJECT LOGO --> <br /> <div align="center"> <a href="https://github.com/psrisuphan/cheap-labor"> <img src="assets/cheap-labor-icon-1024px.png" alt="Cheap Labor Logo" width="120" height="120"> </a>
<h3 align="center">Cheap Labor</h3>
<p align="center"> <i>ChatGPT thinks. Codex executes. They bill separately.</i> </p>
<p align="center"> A plug-in tool that integrates ChatGPT web and Codex for agentic coding workflows — ChatGPT does the thinking, planning, and reviewing, while Codex spends its pool only on real implementation, all over your local repo. <br /> <br /> <a href="#installation"><strong>Install »</strong></a> <br /> <br /> <a href="#abstract">Abstract</a> · <a href="#use-it">Use It</a> · <a href="#uninstall">Uninstall</a> </p> </div>
<!-- TABLE OF CONTENTS --> <details> <summary>Table of Contents</summary> <ol> <li> <a href="#abstract">Abstract</a> <ul> <li><a href="#built-with">Built With</a></li> </ul> </li> <li><a href="#prerequisites">Prerequisites</a></li> <li> <a href="#installation">Installation</a> <ul> <li><a href="#use-it">Use It</a></li> </ul> </li> <li><a href="#uninstall">Uninstall</a></li> <li> <a href="#how-it-works">How It Works</a> <ul> <li><a href="#the-workflow">The Workflow</a></li> </ul> </li> <li><a href="#features">Features</a></li> <li><a href="#tools-reference">Tools Reference</a></li> <li><a href="#safety-model">Safety Model</a></li> <li><a href="#project-structure">Project Structure</a></li> <li><a href="#testing">Testing</a></li> <li><a href="#local-data--logs">Local Data & Logs</a></li> <li><a href="#license">License</a></li> </ol> </details>
<!-- ABSTRACT -->
Abstract
Cheap Labor exists because Codex usage is a limited pool — and most of what a coding agent does is not writing code. Reading files, exploring the repo, planning, and reviewing diffs all burn the Codex allowance without ever writing code.
Then came the key realization: ChatGPT and Codex usage are counted separately — two independent allowances. So we decided to split the work: ChatGPT does all the thinking on its own allowance, and Codex is spent only on real implementation.
That's the whole idea — a local MCP server joined over a Secure MCP Tunnel: ChatGPT on the web drives a Codex CLI on your machine, over your local repo, with a single @cheap-labor trigger.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Built With
Cheap Labor is built with a deliberately small, cross-platform stack:
- Runtime: Node.js (>= 20) — bridge server runtime
- Language: TypeScript — all bridge code
- Protocol: MCP SDK (
@modelcontextprotocol/sdk) — stdio MCP server + client - Validation: zod — tool argument schemas
- Executor: Codex CLI (
codex mcp-server) — spawned child MCP client for exploration and implementation - Connectivity: Secure MCP Tunnel (
tunnel-client) — private, outbound-only link between ChatGPT web and the local server
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- PREREQUISITES -->
Prerequisites
- macOS or Linux with Node.js >= 20 + npm
- git
- A paid ChatGPT account with developer mode
- Codex CLI, logged in (
codex login) tunnel-client— installed during setup: macOS via Homebrew; Linux via the GitHub releases binary (linux-amd64/arm64) on your PATH- A Secure MCP Tunnel + runtime API key from the OpenAI platform (the installer points you to the right pages)
<!-- INSTALLATION -->
Installation
Jump to: 1. Clone & install → 2. Use it
-
Clone the repo and move into it:
git clone https://github.com/psrisuphan/cheap-labor.git cd cheap-labor -
Run the installer — it installs deps, builds the bridge, writes your tunnel profile, validates all 25 tools, and walks you through connecting the app to ChatGPT web:
./scripts/install.sh
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Use It
-
Start the tunnel — keep it running while you use cheap-labor:
./scripts/tunnel.sh start # stop: ./scripts/tunnel.sh stop -
Open a new ChatGPT chat and type
@cheap-labor(or whatever you named the app/plugin when creating it). -
Confirm the project directory when asked — the session is armed.
-
Approval Mode — defaults to
normal(asks you before running every command). Switch to auto-approve (GPT decides the risk) with@cheap-labor, switch to auto-approve.
<!-- UNINSTALL -->
Uninstall
./scripts/uninstall.sh
Cleans up everything the script can reach: legacy MCP registration, the tunnel daemon, .codex-bridge/ state in every initialized project, the tunnel profile and stored API key, and the build artifacts. Three prompts (press Enter for the recommended answer, n to keep). Afterwards it prints a manual cleanup guide for the parts only you can reach: the ChatGPT app connection, the Platform tunnel, the runtime API key, and the project folder.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- HOW IT WORKS -->
How It Works
The bridge is dormant until armed. While dormant, the server ships only a two-line "ignore these tools" notice as its instructions, so unrelated prompts are answered without the bridge ever being considered. The full workflow rules live in the init tool's return payload and enter the conversation only after arming.
The trigger is the invocation itself — no prompt monitoring, no tag syntax, no phrase scanning:
- The user invokes cheap-labor by typing
@cheap-labor. That's the only trigger. - ChatGPT asks which project you want, resolves it (
find_projectsfor fuzzy names,create_projectfor new directories), confirms the exact path with you, then arms the session —init(project)(orcreate_projectdirectly for a brand-new directory) and receives asession_token. - Every other tool refuses to run without a valid
session_token— a hard backstop that also blocks accidental use outside the workflow.
The Workflow
- Arm the session —
@cheap-labor+ confirm the project →initreturns the token. - Understand —
git_status,list_tree,read_file,grep(all free). - Plan in detail — ChatGPT writes
PLAN.md/SPEC.md/TASKS.mdinto the repo's.codex-bridge/folder withplan_write. The plan is exact step-by-step instructions: which files to create/edit, what each change should be, which commands to run, and how to verify. - Small edits, done directly —
write_file/edit_filehandle one-file changes for free. - Delegate heavy work —
implementhands the plan to Codex, which executes the steps literally, runs builds/tests, fixes what breaks, and returnsIMPLEMENTATION COMPLETE. - Review — ChatGPT reads the returned
git diffand sends targeted corrections back through the same loop.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- FEATURES -->
Features
- One-Trigger Activation:
@cheap-laborin any ChatGPT chat is the only trigger; the bridge stays dormant (zero model attention) until invoked — no prompt monitoring, no tag syntax, no phrase scanning. - Three-Bucket Command Safety: provably-safe read-only commands (git status/log/diff, ls, cat, grep, …) run freely; dangerous ones (file deletes, git rewrites, network installs, interpreter one-liners) always require your explicit approval; everything else depends on the approval mode — ask first (
normal, default) or let ChatGPT judge safe commands itself (auto). Switch modes in chat any time withset_approval_mode. - Built-In Safety Rails: project path scoping, secret redaction, checkpoints before every heavy run, and local-only commits that never push.
- Cross-Platform: macOS and Linux, no public ports, outbound-only tunnel.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- TOOLS REFERENCE -->
Tools Reference
Free bridge tools (deterministic local I/O, no Codex cost):
| Tool | Purpose |
|---|---|
init |
Arm the session for a project (the single entry point); returns the session_token + an operation-mode brief |
list_tree |
Directory structure, depth-limited |
read_file |
File contents, line-ranged, size-capped, secrets redacted (redact_secrets: false to disable) |
grep |
Regex search with include/exclude globs, secrets redacted (redact_secrets: false to disable) |
git_status / git_diff / git_log |
Repo state + the review loop (untracked files surfaced) |
run_command |
Three-bucket execution (tests, build, typecheck): safe allowlist runs freely; dangerous commands always need your approval; the rest follows the approval mode. Output secrets redacted (redact_secrets: false to disable) |
set_approval_mode |
Switch the global approval mode — normal (ask first) or auto (ChatGPT judges safe commands itself); dangerous commands always ask |
get_settings |
Read current bridge settings (e.g. the approval mode) |
write_file |
Create a new file directly (refuses to overwrite) |
edit_file |
Exact-match edit of an existing file (content-based stale guard) |
edit_pack |
Batch edits/writes, all-or-nothing (no partial state) |
checkpoint |
Snapshot HEAD + working tree for rollback (auto before implement) |
rollback |
Restore to a checkpoint (user-confirmed; itself undoable) |
git_commit |
Stage + commit locally with a user-approved message (never pushes) |
checkpoints |
List recorded checkpoints |
find_projects |
Resolve fuzzy names to candidate paths (shallow, well-known locations) |
create_project |
Create a new project directory (no git init); returns a session_token |
plan_read / plan_write / task_update |
Manage .codex-bridge/ handoff files |
Codex-backed tools (spend the Codex pool):
| Tool | Purpose |
|---|---|
deep_explore |
Read-only Codex session for questions free tools can't answer (model upgrade per-call with your confirmation) |
implement |
Workspace-write Codex on the current plan; returns summary + git diff (model upgrade per-call with your confirmation) |
codex_reply |
Continue a session by thread id (approval veto loop, follow-ups); bound to the project that created it |
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- SAFETY MODEL -->
Safety Model
implement/deep_explorealways pass an explicit sandbox (workspace-write/read-only) — neverdanger-full-access.- Fixed Codex model — every Codex call pins
gpt-5.6-lunawithmediumreasoning and Fast Mode off, passed as per-call overrides. The bridge never writes to~/.codex/config.toml. The one exception:implement/deep_exploreaccept a stronger model (e.g.gpt-5.6-sol), but the bridge refuses it unless the call passesmodel_confirmed: true— set only after you explicitly agree to that exact model in chat. Per-call: each non-default model run needs its own confirmation. - Auto-safe approvals — Codex shell approvals surface as MCP elicitations: commands on the provably-safe allowlist are auto-approved; dangerous ones (writes, network, git mutations, interpreter one-liners) are always declined — in
automode too — and recorded so ChatGPT relays them to you for a veto. The veto is executed withcodex_reply. - Approval modes —
run_commandbuckets every command. The safe allowlist (git status/log/diff/show/rev-parse,ls,cat,pwd,echo,grep,rg,sort,uniq,wc,head,tail,printf,date) always runs. Dangerous commands (file deletion/overwrite, git rewrites, network installs, interpreter one-liners) always require your approval — the bridge refuses them withoutapproved: true. Everything else follows the mode:normal(default) asks you first;autolets ChatGPT judge safe commands itself but still makes it ask you for dangerous ones. Change it any time withset_approval_mode— it applies to every chat immediately. write_fileonly creates new files;edit_fileonly edits existing ones via exact-match replacement (stale/ambiguous matches write nothing);edit_packbatches all-or-nothing. All cap sizes and refuse binary files.- Ship mode —
checkpointsnapshots HEAD + working tree (taken automatically before everyimplement);rollbackrestores a checkpoint (itself undoable);git_commitcommits locally with a user-approved message. Push/pull/reset/rebase/checkout are never exposed. - Bridge tools refuse paths outside the session-approved project directory.
read_file/grep/git_diff/run_commandredact known secret patterns by default; passredact_secrets: falsewhen a task genuinely needs the raw content.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- PROJECT STRUCTURE -->
Project Structure
cheap-labor/
├── assets/ # Logo / icons
├── scripts/ # Installer, uninstaller, tunnel control, setup
│ ├── install.sh # All-in-one installer
│ ├── uninstall.sh # Clean uninstaller
│ ├── tunnel-setup.sh # Writes the tunnel-client profile
│ ├── tunnel.sh # start / stop / restart / status / logs the tunnel daemon
│ └── setup.mjs # Prerequisite check
├── src/ # Bridge MCP server
│ ├── index.ts # Server entry, tool registration, server instructions
│ ├── safety.ts # Project scoping, redaction, risk classification, command buckets
│ ├── projects.ts # Session approvals, ledger, find/create
│ ├── planstore.ts # .codex-bridge/ I/O
│ ├── settings.ts # Approval mode (normal / auto)
│ ├── approvals.ts # Auto-safe policy
│ └── tools/ # context, command, codex, deepExplore,
│ # implement, edit, plans, ship
├── tests/ # Node test suite
├── dist/ # Build output (gitignored)
└── package.json
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- TESTING -->
Testing
To run the unit test suites:
npm run typecheck # tsc --noEmit
npm test # node --test (tsx)
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- LOCAL DATA & LOGS -->
Local Data & Logs
Cheap Labor stores its tunnel profile, runtime API key, and daemon logs locally, outside the project directory:
- macOS / Linux:
~/.config/tunnel-client/
Inside this directory you will find:
cheap-labor.yaml— thetunnel-clientprofile (contains the tunnel id).cheap-labor.key— the runtime API key, chmod 600, never committed.cheap-labor.log— the tunnel daemon log.
Bridge settings (the approval mode) live in ~/.codex/cheap-labor-settings.json (chmod 600).
Plans and handoff files are written into each project's .codex-bridge/ folder at runtime (gitignored). Codex's own configuration and auth live in ~/.codex/.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- LICENSE -->
License
This project is licensed under the MIT License. See the LICENSE file for the full license text.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。