Skip to main content
Glama
walterwhite91

chatgpt-mcp-bridge

README.md
# chatgpt-mcp-bridge

A small self-hosted [MCP](https://modelcontextprotocol.io) server that gives ChatGPT (Developer Mode / custom connectors) read-only access to a few free public data sources:

- **WHOIS** domain lookups (`whois_domain`)
- **UK Companies House** company search and profile lookup (`companies_house_search`, `companies_house_company`)
- **SEC EDGAR** US public filings, proxied through this same server from [`sec-edgar-mcp`](https://github.com/stefanoamorelli/sec-edgar-mcp)

[Wikidata](https://www.wikidata.org/wiki/Wikidata:MCP) is not hosted here — it's already public at `https://wd-mcp.wmcloud.org/mcp/`, so just add that URL directly as a fourth ChatGPT connector.

## Architecture

```
ChatGPT ──HTTPS (ngrok tunnel)──> bridge (Express, port 3939)
                                    ├── /mcp           whois + Companies House tools
                                    └── /sec-edgar/mcp ──proxy──> sec-edgar container (port 9870)
```

One public hostname serves both tool sets — a free ngrok account only grants one static domain, so SEC EDGAR is reverse-proxied under a sub-path instead of getting its own tunnel.

Built on the current official MCP TypeScript SDK pattern: `@modelcontextprotocol/server` + `@modelcontextprotocol/express` + `@modelcontextprotocol/node`.

## Setup

### 1. Environment

```
cp .env.example .env
```

Fill in:
- `COMPANIES_HOUSE_API_KEY` — free key from [developer.company-information.service.gov.uk](https://developer.company-information.service.gov.uk/)
- `SEC_EDGAR_USER_AGENT` — your real name + email, e.g. `Jane Doe (jane@example.com)` (SEC requires a genuine identifying user-agent)
- `NGROK_AUTHTOKEN` — from your [ngrok dashboard](https://dashboard.ngrok.com)
- `PUBLIC_HOSTNAME` — your ngrok static domain (free accounts get exactly one, claimed once via the dashboard)

### 2. Run everything

```
docker compose up -d
```

Starts three containers: the bridge, the SEC EDGAR MCP server, and an ngrok tunnel pointing at the bridge.

### 3. Verify

```
docker compose logs -f
curl -s -X POST https://<your-domain>.ngrok-free.dev/mcp \
  -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

### 4. Register in ChatGPT

Settings → Apps → Advanced settings → enable **Developer mode** → add connectors (Streamable HTTP, no auth):

- `https://<your-domain>.ngrok-free.dev/mcp`
- `https://<your-domain>.ngrok-free.dev/sec-edgar/mcp`
- `https://wd-mcp.wmcloud.org/mcp/`

## Security notes

- No-auth public endpoint: anyone holding the tunnel URL can call these tools while it's up. All tools here are read-only, but keep the URL private — don't post it anywhere public.
- `createMcpExpressApp`'s built-in DNS-rebinding protection is configured via `PUBLIC_HOSTNAME` in `allowedHosts`/`allowedOrigins` — requests with an unrecognized `Host` header get `403`.
- Keep `COMPANIES_HOUSE_API_KEY` and `NGROK_AUTHTOKEN` in `.env` only; never commit it (already gitignored).

## Local dev (without Docker)

```
npm install
npm start          # bridge on :3939
```

SEC EDGAR needs to be running separately on :9870 for the `/sec-edgar/mcp` proxy to work — see `docker-compose.yml` for the exact command, or run the container manually:

```
docker run -i --rm -p 9870:9870 \
  -e SEC_EDGAR_USER_AGENT="Your Name (your-email@domain.com)" \
  stefanoamorelli/sec-edgar-mcp:latest \
  python -m sec_edgar_mcp.server --transport streamable-http --port 9870
```