The local Node runtime stores connections, OAuth client configuration, pending OAuth states, runtime tokens, recent run logs, and HTTP Action idempotency claims and responses in SQLite. The Cloudflare Workers runtime stores the same runtime records in D1 and temporary transit files in R2.
By default the database lives at:
./data/connect.sqlite
Set OOMOL_CONNECT_DATA_DIR to use another directory. The Docker image defaults this to
/app/data, which is intended to be mounted as a volume.
no_authproviders are available as virtual connections and do not store secrets.api_keyandcustom_credentialproviders store their local secrets in SQLite.oauth2providers use user-provided OAuth client configuration and a localhost callback URL.
Set OOMOL_CONNECT_ENCRYPTION_KEY to encrypt stored credentials, OAuth client configuration, and
completed idempotent Action response payloads:
OOMOL_CONNECT_ENCRYPTION_KEY="replace-with-a-long-random-secret" npm run devThe runtime uses AES-256-GCM for provider credential records, OAuth client configuration, and the
completed response payload retained for an idempotent HTTP Action retry. The raw Idempotency-Key
is never stored; the database contains its hash and a request fingerprint. Claim identifiers,
state, timestamps, and expiry are also stored as unencrypted metadata. The encryption key is not
stored by OpenConnector; if it is lost, encrypted records cannot be recovered.
Without OOMOL_CONNECT_ENCRYPTION_KEY, the runtime stays usable for local development and prints a
startup warning. In that mode, credentials, OAuth client configuration, and completed idempotent
Action responses are stored as plaintext. Action responses may contain sensitive provider data, so
treat connect.sqlite or D1 as a sensitive data store even after a response is no longer eligible
for replay.
Completed idempotent Action responses remain eligible for replay for 24 hours. Expired idempotency records are deleted opportunistically when a later idempotent Action request claims a key; the 24-hour replay window is not a guarantee of physical deletion by that deadline.
Credential fields are declared by each provider's catalog auth metadata. The runtime treats that
metadata as the contract for local API requests:
api_keyconnections always requirevalues.apiKey.api_keyconnections may declare additionalextraFields.custom_credentialconnections require exactly the provider-declaredfields.oauth2client config may declare additionalclientConfigFields.
All submitted string values are trimmed. Empty strings are treated as missing. Unknown submitted fields are rejected instead of being silently stored, because credential forms, scripts, and provider definitions should fail fast when they drift.
Inspect a provider before writing setup scripts:
curl -s http://localhost:3000/api/providers/githubWhen a provider can cheaply validate credentials against a current-user or current-account endpoint, its validator stores a stable connection profile:
accountId: provider-side user, workspace, bot, account, or token identifier.displayName: human-readable account label.grantedScopes: provider-native scopes granted to the credential, when known.
The runtime exposes this profile in /api/connections, MCP action discovery, action agent guides,
and recent run logs. Agents should use it to understand which account an action will run as; raw
provider tokens are never exposed.
Check current connections:
curl -s http://localhost:3000/api/connectionsCreate or replace the default API key connection:
curl -s -X PUT http://localhost:3000/api/connections/github \
-H 'content-type: application/json' \
-d '{"authType":"api_key","values":{"apiKey":"github_pat_..."}}'Create or replace a named API key connection:
curl -s -X PUT http://localhost:3000/api/connections/github \
-H 'content-type: application/json' \
-d '{"authType":"api_key","connectionName":"work","values":{"apiKey":"github_pat_..."}}'The accepted keys are apiKey plus the provider's auth[].extraFields.
Execute an action with the default connection:
curl -s -X POST http://localhost:3000/v1/actions/github.get_current_user \
-H 'content-type: application/json' \
-d '{"input":{}}'Create or replace the default custom credential connection:
curl -s -X PUT http://localhost:3000/api/connections/example \
-H 'content-type: application/json' \
-d '{"authType":"custom_credential","values":{"host":"localhost","password":"..."}}'The accepted keys come from the provider's auth[].fields.
OAuth2 providers require your own provider OAuth app. List OAuth-capable providers and copy the
expectedRedirectUri for the service:
curl -s http://localhost:3000/api/oauth/configsPaste that exact callback URL into the provider OAuth app. With the default port, GitHub uses:
http://localhost:3000/oauth/callback
If the browser reaches the runtime through another origin, set OOMOL_CONNECT_ORIGIN before
starting the runtime:
OOMOL_CONNECT_ORIGIN="https://your-tunnel.example" npm run devThen use the new expectedRedirectUri returned by /api/oauth/configs.
Store the local client configuration:
curl -s -X PUT http://localhost:3000/api/oauth/configs/github \
-H 'content-type: application/json' \
-d '{"clientId":"...","clientSecret":"..."}'Some providers declare additional OAuth client fields in auth[].clientConfigFields; send those as
extra.
Start authorization:
curl -s -X POST http://localhost:3000/api/oauth/authorizations \
-H 'content-type: application/json' \
-d '{"service":"github"}'Open the returned authorizationUrl in a browser. After the provider redirects to the local
callback URL, the runtime stores the OAuth credential as the default connection.
To store the OAuth credential as a named connection, include connectionName when starting
authorization:
curl -s -X POST http://localhost:3000/api/oauth/authorizations \
-H 'content-type: application/json' \
-d '{"service":"github","connectionName":"work"}'Protect the local SQLite database like any other file containing API keys or OAuth tokens.
The default connection is used when no alias is provided:
curl -s -X POST http://localhost:3000/v1/actions/github.get_current_user \
-H 'content-type: application/json' \
-d '{"input":{}}'If a named connection already exists, select it with x-oo-connector-alias:
curl -s -X POST http://localhost:3000/v1/actions/github.get_current_user \
-H 'x-oo-connector-alias: work' \
-H 'content-type: application/json' \
-d '{"input":{}}'The alias query parameter is also accepted:
curl -s -X POST "http://localhost:3000/v1/actions/github.get_current_user?alias=work" \
-H 'content-type: application/json' \
-d '{"input":{}}'Reset local runtime data:
npm run runtime:data -- reset --yesRotate the local SQLite data-encryption key:
OOMOL_CONNECT_ENCRYPTION_KEY="old-secret" \
OOMOL_CONNECT_NEW_ENCRYPTION_KEY="new-secret" \
npm run runtime:data -- rotate-keyRemove local SQLite data encryption only when you intentionally want plaintext local storage:
OOMOL_CONNECT_ENCRYPTION_KEY="old-secret" \
npm run runtime:data -- rotate-key --plainBoth commands re-encode stored credentials, OAuth client configuration, and completed idempotent Action response payloads. Idempotency key hashes, request fingerprints, claim state, and timestamps remain unencrypted metadata.
runtime:data is for the local SQLite runtime only. For Cloudflare, back up and restore D1/R2
directly with Cloudflare tooling.
OAuth access tokens are refreshed automatically when they are expired and the provider issued a
refresh token. Refreshed credentials are written back to the local SQLite store, using encryption
when OOMOL_CONNECT_ENCRYPTION_KEY is configured.
If a token is expired and no refresh token is available, reconnect the provider from the local runtime. Providers such as Google may require authorization parameters that request offline access; provider definitions should include those parameters when refresh tokens are expected.
The server binds to 127.0.0.1 by default. Set HOST=0.0.0.0 only when the runtime must be
reachable from outside the local machine or container.
Set an admin bearer token when the admin API or web console is reachable outside your own shell:
OOMOL_CONNECT_ADMIN_TOKEN="replace-with-an-admin-token" npm run devAdmin clients calling /api, /docs, or the web console should send:
Authorization: Bearer replace-with-an-admin-token
Create runtime tokens for /v1 and /mcp callers from the web console Access tab or
POST /api/runtime-tokens. The token is shown once when created; only a hash is stored in SQLite.
Runtime clients should send Authorization: Bearer oct_.... Persistent tokens configure Action
rules and provider proxy grants independently. Their allowedProxies list is empty by default,
which denies /v1/proxy/:service; add a provider service or * only when that client needs proxy
access.
OOMOL_CONNECT_RUNTIME_TOKEN is still accepted for bootstrap scripts and backward compatibility.
The bundled web console receives a same-site local cookie from the runtime so it can keep working when API-token authentication is enabled.
Use OOMOL_CONNECT_ALLOWED_ACTIONS to expose only selected actions to HTTP and MCP execution:
OOMOL_CONNECT_ALLOWED_ACTIONS="hackernews.*,github.get_current_user" npm run devUse OOMOL_CONNECT_BLOCKED_ACTIONS to deny specific actions even when a broader allowlist includes
them:
OOMOL_CONNECT_ALLOWED_ACTIONS="github.*" \
OOMOL_CONNECT_BLOCKED_ACTIONS="github.delete_repository" \
npm run devProvider proxy requests use separate service-level policy variables because /v1/proxy/:service
can reach provider API endpoints beyond the curated action catalog. Action policy and proxy policy
are independent: the action variables never restrict proxies, and the proxy variables never restrict
actions. At the deployment and runtime layers, every provider proxy is allowed until you restrict it:
OOMOL_CONNECT_ALLOWED_PROXIES="github" npm run devPersistent runtime tokens must also grant the requested provider through their independent
allowedProxies list. Token grants intersect with the deployment and runtime proxy policy and
cannot widen it. An empty token proxy grant denies every provider proxy.
Set OOMOL_CONNECT_BLOCKED_PROXIES="*" to disable /v1/proxy/:service entirely. Restrict both
surfaces when you want both restricted:
OOMOL_CONNECT_ALLOWED_ACTIONS="github.get_current_user" \
OOMOL_CONNECT_ALLOWED_PROXIES="github" \
npm run devUse OOMOL_CONNECT_BLOCKED_PROXIES to deny provider proxies even when OOMOL_CONNECT_ALLOWED_PROXIES
contains *:
OOMOL_CONNECT_ALLOWED_PROXIES="*" \
OOMOL_CONNECT_BLOCKED_PROXIES="github" \
npm run devAction policy entries are comma-separated action ids. A provider-wide wildcard such as gmail.*
matches all actions for that provider, and a bare * matches every action. Proxy policy entries are
comma-separated provider service names, or * for all provider proxies.