OOMOL OpenConnector self-hosting guide
OOMOL OpenConnector is an open-source, self-hostable connector service. Use it when agents or internal tools need to call real external services while provider credentials, permissions, and execution history stay in your own environment. It exposes typed actions for services such as GitHub, Gmail, Notion, Hacker News, Ably, Abstract, and A-Leads through MCP or HTTP.
Agents see schemas, scopes, execution status, and safe account labels; raw provider tokens, action permissions, and execution history stay inside your deployment boundary.
What it gives you
- A runtime that exposes provider actions through MCP, HTTP, OpenAPI, and a web console.
- Credential storage for API keys, custom credentials, OAuth2 connections, and no-auth providers.
- Typed action schemas so agents can discover what they can call before they call it.
- Connection identity and scopes so users and agents can see which account an action will run as.
- Temporary file transit for actions that need file URLs.
- Recent run logs with redacted input summaries and provider errors.
- A provider catalog with local executors that load only when an action is used.
Start by choosing where to run the runtime, then configure storage, access control, provider connections, and the agent-facing MCP or HTTP entry point.
Choose a deployment target
| Target | Use it when | Storage |
|---|---|---|
| Docker Compose | You want the fastest local or single-server deployment. | Docker volume mounted at /app/data, with SQLite at /app/data/connect.sqlite. |
| Source runtime | You are developing OOMOL OpenConnector or provider executors. | Local ./data/connect.sqlite unless OOMOL_CONNECT_DATA_DIR is set. |
| Cloudflare Workers | You want a Cloudflare-hosted runtime state and metadata deployment. | D1 for runtime records and R2 for temporary transit files. |
Prepare the runtime
Before deploying, decide these values:
| Value | Why it matters |
|---|---|
OOMOL_CONNECT_ADMIN_TOKEN | Protects the web console, /api, and local API reference when they are reachable outside your own shell. |
OOMOL_CONNECT_ENCRYPTION_KEY | Encrypts stored provider credentials and OAuth client secrets. Keep it in your secret manager. |
OOMOL_CONNECT_ORIGIN | Sets the public origin used for OAuth callback URLs. Required when the browser reaches the runtime through a tunnel, domain, or Worker URL. |
| Runtime tokens | Authenticate agent and client calls to /v1 and /mcp. Create them from the web console Access tab or the admin API. |
| Action policy | Limits which actions can execute through /v1 and MCP. Use OOMOL_CONNECT_ALLOWED_ACTIONS and OOMOL_CONNECT_BLOCKED_ACTIONS. |
Treat the runtime database as sensitive. Without OOMOL_CONNECT_ENCRYPTION_KEY, OOMOL OpenConnector still works, but provider secrets are stored in a sensitive local SQLite file.
Run with Docker Compose
Clone the OOMOL OpenConnector repository, enter the project directory, and start the runtime:
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
docker compose up --build
Open the web console:
http://localhost:3000
Open the generated API reference:
http://localhost:3000/docs
Verify the runtime with a no-auth action:
curl -s -X POST http://localhost:3000/v1/actions/hackernews.get_top_stories \
-H 'content-type: application/json' \
-d '{"input":{}}'
Docker Compose stores runtime state in the connector-data volume. The container stores SQLite at:
/app/data/connect.sqlite
For a private server deployment, set at least the admin token and encryption key before starting:
OOMOL_CONNECT_ADMIN_TOKEN="replace-with-an-admin-token" \
OOMOL_CONNECT_ENCRYPTION_KEY="replace-with-a-long-random-secret" \
docker compose up --build
When the runtime is exposed through a public domain or tunnel, set the public origin too:
OOMOL_CONNECT_ORIGIN="https://connect.example.com" \
OOMOL_CONNECT_ADMIN_TOKEN="replace-with-an-admin-token" \
OOMOL_CONNECT_ENCRYPTION_KEY="replace-with-a-long-random-secret" \
docker compose up --build
The Docker image binds to 0.0.0.0 inside the container. Control external access with your host firewall, reverse proxy, or container platform.
Protect admin and runtime access
Admin HTTP clients call /api, /docs, or the web console with:
Authorization: Bearer replace-with-an-admin-token
Create runtime tokens for agents and SDK-style clients from the web console Access tab. The token is shown once; only a hash is stored.
You can also create one through the admin API:
curl -s -X POST http://localhost:3000/api/runtime-tokens \
-H 'authorization: Bearer replace-with-an-admin-token' \
-H 'content-type: application/json' \
-d '{"name":"Claude Desktop"}'
Runtime clients then call /v1 or /mcp with:
Authorization: Bearer oct_...
For bootstrap scripts and backward compatibility, OOMOL_CONNECT_RUNTIME_TOKEN is still accepted:
OOMOL_CONNECT_ADMIN_TOKEN="replace-with-an-admin-token" \
OOMOL_CONNECT_RUNTIME_TOKEN="replace-with-a-runtime-token" \
docker compose up --build
Limit the actions agents can execute:
OOMOL_CONNECT_ALLOWED_ACTIONS="hackernews.*,github.get_current_user" docker compose up --build
Block specific actions even when a broader allowlist includes them:
OOMOL_CONNECT_ALLOWED_ACTIONS="github.*" \
OOMOL_CONNECT_BLOCKED_ACTIONS="github.delete_repository" \
docker compose up --build
Connect an API-key provider
GitHub is a compact API-key example because it can use a personal access token.
Inspect the provider contract:
curl -s http://localhost:3000/api/providers/github \
-H 'authorization: Bearer replace-with-an-admin-token'
Store the default GitHub connection:
curl -s -X PUT http://localhost:3000/api/connections/github \
-H 'authorization: Bearer replace-with-an-admin-token' \
-H 'content-type: application/json' \
-d '{"authType":"api_key","values":{"apiKey":"github_pat_..."}}'
Call GitHub through the runtime:
curl -s -X POST http://localhost:3000/v1/actions/github.get_current_user \
-H 'authorization: Bearer oct_...' \
-H 'content-type: application/json' \
-d '{"input":{}}'
Check configured connections and the safe account identity exposed to agents:
curl -s http://localhost:3000/api/connections \
-H 'authorization: Bearer replace-with-an-admin-token'
Named connections
Add connectionName when the same provider needs multiple accounts:
curl -s -X PUT http://localhost:3000/api/connections/github \
-H 'authorization: Bearer replace-with-an-admin-token' \
-H 'content-type: application/json' \
-d '{"authType":"api_key","connectionName":"work","values":{"apiKey":"github_pat_..."}}'
Select that account during execution:
curl -s -X POST http://localhost:3000/v1/actions/github.get_current_user \
-H 'authorization: Bearer oct_...' \
-H 'x-oo-connector-alias: work' \
-H 'content-type: application/json' \
-d '{"input":{}}'
The alias query parameter is also accepted.
Connect an OAuth provider
OAuth providers use your own provider OAuth app. First list OAuth-capable providers and copy the expectedRedirectUri for the service:
curl -s http://localhost:3000/api/oauth/configs \
-H 'authorization: Bearer replace-with-an-admin-token'
With the default port, GitHub uses this callback URL:
http://localhost:3000/oauth/callback
Paste the exact callback URL returned by /api/oauth/configs into the provider OAuth app. If you change PORT, HOST, or expose the runtime through another origin, set OOMOL_CONNECT_ORIGIN before starting the runtime and read the callback URL again.
Store the OAuth client locally:
curl -s -X PUT http://localhost:3000/api/oauth/configs/github \
-H 'authorization: Bearer replace-with-an-admin-token' \
-H 'content-type: application/json' \
-d '{"clientId":"...","clientSecret":"..."}'
Start authorization:
curl -s -X POST http://localhost:3000/api/oauth/authorizations \
-H 'authorization: Bearer replace-with-an-admin-token' \
-H 'content-type: application/json' \
-d '{"service":"github"}'
Open the returned authorizationUrl in a browser. After the provider redirects to the callback URL, OOMOL OpenConnector stores the OAuth credential as the default connection.
To store the OAuth result as a named connection, include connectionName:
curl -s -X POST http://localhost:3000/api/oauth/authorizations \
-H 'authorization: Bearer replace-with-an-admin-token' \
-H 'content-type: application/json' \
-d '{"service":"github","connectionName":"work"}'
Give tools to an agent
For MCP-capable clients, point the client at:
http://localhost:3000/mcp
The MCP server exposes discovery-oriented tools:
list_appssearch_actionsget_action_guideexecute_action
Preview MCP tool metadata:
curl -s http://localhost:3000/mcp/tools \
-H 'authorization: Bearer oct_...'
For HTTP clients, use the /v1 runtime API:
curl -s http://localhost:3000/v1/actions \
-H 'authorization: Bearer oct_...'
Each action has a local Markdown guide with the input schema, scopes, provider permissions, current connection identity, and request examples:
curl -s http://localhost:3000/api/actions/github.get_current_user/agent.md \
-H 'authorization: Bearer replace-with-an-admin-token'
The web console can also copy cURL, TypeScript, and agent prompt examples for each action.
Run from source
Use the source workflow when you are developing OOMOL OpenConnector or provider executors. Use Node.js 22 or newer.
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
npm install
npm run build:web
npm run dev
npm install and npm run dev create local generated files when they are missing or stale.
When running from source, runtime state is stored in:
./data/connect.sqlite
Use another data directory with:
OOMOL_CONNECT_DATA_DIR=/path/to/data npm run dev
Set the same admin, encryption, origin, runtime token, and action policy environment variables described above.
Deploy to Cloudflare Workers
Cloudflare Workers is supported as a metadata and runtime-state deployment target.
Clone the repository, create the Cloudflare resources, and deploy:
git clone https://github.com/oomol-lab/open-connector.git
cd open-connector
cp wrangler.example.jsonc wrangler.local.jsonc
npm run generate:catalog
npm run build:web
npx wrangler d1 create oomol-connect
npx wrangler r2 bucket create oomol-connect-transit-files
npx wrangler d1 migrations apply oomol-connect --remote
npm run deploy:cloudflare
Before deploying, update the ignored wrangler.local.jsonc file with the D1 database_id returned by Cloudflare.
Set secrets with Wrangler:
npx wrangler secret put OOMOL_CONNECT_ADMIN_TOKEN
npx wrangler secret put OOMOL_CONNECT_ENCRYPTION_KEY
Cloudflare uses the same environment variable names for origin, auth tokens, action policy, transit file limits, and credential encryption. PORT, HOST, and OOMOL_CONNECT_DATA_DIR are local Node-only settings.
The Worker runtime serves catalog metadata, /api and /v1 metadata endpoints, connections, runtime tokens, OAuth config and state, R2-backed transit files, and the generated provider action executor registry. Configure an R2 lifecycle rule for the transit bucket if you want unread expired transit files cleaned up automatically.
Operate the deployment
Keep these records available for support and recovery:
| Record | Where to find it |
|---|---|
| Runtime database | Docker volume, local OOMOL_CONNECT_DATA_DIR, or Cloudflare D1. |
| Temporary transit files | OOMOL_CONNECT_DATA_DIR/files for local runtime, or Cloudflare R2. |
| Admin token and encryption key | Your secret manager. OOMOL OpenConnector does not store the encryption key for you. |
| Runtime token prefix | Web console Access tab or /api/runtime-tokens. Full runtime tokens are shown only once. |
| Execution history | Web console recent runs or GET /api/runs. |
For file-upload actions, local transit files are stored under OOMOL_CONNECT_DATA_DIR/files and cleaned up by age. Tune the lifetime and upload size with OOMOL_CONNECT_TRANSIT_FILE_TTL_SECONDS and OOMOL_CONNECT_TRANSIT_FILE_MAX_BYTES.
Troubleshooting
| Symptom | What to check |
|---|---|
The web console or /api returns unauthorized. | Send Authorization: Bearer <admin-token> and confirm OOMOL_CONNECT_ADMIN_TOKEN matches the running environment. |
/v1 or /mcp returns unauthorized. | Use a runtime token created from the Access tab or POST /api/runtime-tokens. Admin tokens are for admin surfaces, not runtime clients. |
| OAuth redirects to the wrong host. | Set OOMOL_CONNECT_ORIGIN to the origin users open in the browser, restart the runtime, then copy the fresh expectedRedirectUri from /api/oauth/configs. |
| An action cannot find credentials. | Check /api/connections, the selected x-oo-connector-alias, and whether the connection is still available. |
| An action is blocked. | Check OOMOL_CONNECT_ALLOWED_ACTIONS and OOMOL_CONNECT_BLOCKED_ACTIONS. Blocked actions win over broader allowlists. |
| Provider credentials fail after working earlier. | Reconnect the provider if the token expired and no refresh token is available, or verify that the encryption key still matches the stored records. |