chatgpt-local-mcp-bridge
# ChatGPT Local MCP Bridge
A narrow, read-only MCP server that lets **ChatGPT Web** inspect one local
workspace through the official **OpenAI Secure MCP Tunnel**.
This repository is deliberately smaller than a general local-agent runtime. It
has no Electron app, no shell tool, no file writes, no browser automation, no
child MCP bridge, and no public HTTP listener.
## What this gives us
```text
ChatGPT Web (Developer mode)
|
| OpenAI Secure MCP Tunnel (outbound HTTPS)
v
Official tunnel-client on the local host
|
| MCP stdio
v
chatgpt-local-mcp-bridge
|
v
One allowlisted workspace (read-only)
```
ChatGPT cannot connect to localhost directly. For a private MCP server on a
developer machine, OpenAI documents Secure MCP Tunnel as the supported
connection path. The tunnel keeps the MCP process private and forwards MCP
requests over an outbound connection.
- [OpenAI Secure MCP Tunnel](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels)
- [Connect and test an MCP app in ChatGPT](https://developers.openai.com/plugins/deploy/connect-chatgpt)
- [ChatGPT Developer mode](https://developers.openai.com/api/docs/guides/developer-mode)
## Current scope: v0.1.0
The bridge exposes exactly six read-only tools:
| Tool | Purpose |
|---|---|
| `workspace_list` | Show the one configured workspace without exposing its full path |
| `list_files` | List bounded files/directories, skipping generated and sensitive paths |
| `read_file` | Read bounded UTF-8 text files under the workspace |
| `search_text` | Recursively search bounded text files while skipping noise |
| `git_status` | Run a fixed, read-only `git status` command |
| `git_diff` | Run a fixed, bounded, read-only `git diff` command |
There is intentionally no `shell`, `write_file`, `delete`, `browser`,
`process_start`, `mcp_call`, or arbitrary URL fetch tool in this version.
## Local setup
Requirements:
- Python 3.11+
- Git for the read-only Git tools
- An official `tunnel-client` binary for the host OS if connecting ChatGPT Web
Create the isolated environment and install the project:
```bash
cd /home/mike/projects/chatgpt-local-mcp-bridge
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/pip install -e '.[dev]'
```
Choose one workspace explicitly:
```bash
export CHATGPT_BRIDGE_WORKSPACE="$HOME/projects/chatgpt-local-mcp-bridge"
```
Run the local server directly:
```bash
.venv/bin/chatgpt-local-mcp-bridge
```
This is an MCP stdio process. Its stdout is reserved for MCP protocol traffic;
configuration errors go to stderr. Do not run it by opening it as an
interactive CLI.
For this repository, the helper script sets the workspace to the repository
root when no override is supplied:
```bash
./scripts/run-bridge.sh
```
## Connect to ChatGPT Web
The concrete command below assumes the official `tunnel-client` runs in the
same WSL environment as the bridge. Use the official binary and current OpenAI
tunnel-client instructions for your host OS.
1. Create an OpenAI Platform tunnel and record its `tunnel_id`.
2. Create a restricted runtime key with **Tunnels Read + Use**.
3. Keep the key in the environment for the current process; do not commit it
or put it in a YAML profile.
4. Initialize a stdio tunnel profile:
```bash
export CONTROL_PLANE_API_KEY='replace-for-this-shell-only'
export CHATGPT_BRIDGE_WORKSPACE="$HOME/projects/chatgpt-local-mcp-bridge"
tunnel-client init \
--sample sample_mcp_stdio_local \
--profile chatgpt-local-mcp-bridge \
--tunnel-id 'tunnel_replace_me' \
--mcp-command "$PWD/scripts/run-bridge.sh"
```
5. Validate and run the tunnel:
```bash
tunnel-client doctor \
--profile chatgpt-local-mcp-bridge \
--explain
tunnel-client run --profile chatgpt-local-mcp-bridge
```
6. In ChatGPT Web, enable **Developer mode**, create an app from the plus
button, choose **Tunnel** under Connection, select the associated tunnel,
and review the discovered tool list.
7. Start with a read-only smoke prompt:
```text
Use the local MCP bridge to list the configured workspace, show its top-level
files, report Git status, and summarize the current diff. Do not modify anything.
```
The ChatGPT workspace must be associated with the OpenAI Platform tunnel, and
the account/workspace must have Developer mode enabled. Tunnel access and
ChatGPT Developer mode are separate permissions.
## Security model
This bridge uses a single canonical workspace root. Requested paths are
resolved, checked for traversal and symlink escapes, and then filtered for
common sensitive names. File and search results are bounded.
The bridge is **not** an OS sandbox. It is a narrow capability boundary for the
first experiment. Any file content returned to ChatGPT can leave the local
machine through the OpenAI tunnel. Use a disposable or non-sensitive workspace
first.
Do not add shell or write tools until a separate approval design exists. A
ChatGPT UI confirmation is not a substitute for server-side authorization or
an OS/container boundary.
## Tests and verification
Run the full local suite:
```bash
.venv/bin/pytest
```
The suite covers:
- workspace containment and traversal rejection;
- symlink escape rejection;
- sensitive-path blocking;
- bounded UTF-8 reads;
- generated/sensitive directory filtering;
- recursive text search;
- fixed Git status/diff behavior;
- real MCP stdio handshake, tool discovery, and tool invocation through the
official Python MCP client.
## Project status
This is a working local slice, not a claim that the ChatGPT account/tunnel has
been connected end to end. The local MCP protocol is testable without
credentials; ChatGPT Web connection still requires the user's OpenAI Platform
permissions and tunnel setup.
See [ROADMAP.md](ROADMAP.md) for the deliberate next steps and stop line.
TDQS
Scored across 6 tools
Each tool has a distinct purpose: workspace info, file listing, file reading, text search, git status, and git diff. The only minor ambiguity is that workspace_list could be mistaken for a file-listing tool, but the description clarifies it.
Names mix verb-first patterns like list_files and read_file with noun-phrase patterns like git_status and git_diff, plus the unusual workspace_list. All names are readable and consistently snake_case, but the convention is not uniform.
Six tools is a well-scoped count for a read-only local workspace bridge. Each tool covers a necessary operation without redundancy or bloat.
The toolset covers the core read-only workspace needs: discover, list, read, search, and inspect git state. Minor gaps like file metadata or git log are not critical for the stated read-only purpose.