Open Agent Connector
An open-source, self-hosted integration gateway for AI agents. Connect accounts to app APIs, keep credentials in your own runtime, and let agents discover and run actions through the Model Context Protocol (MCP) or a REST API.
This project is for developers who want to inspect, run, and extend their own agent integration layer. It is an open-source option to evaluate alongside Composio, Nango, Merge.dev, and Arcade.dev. Those platforms offer broader catalogs and managed capabilities; Open Agent Connector currently prioritizes a compact self-hosted implementation that you can modify.
Project description
Open Agent Connector gives an agent a consistent way to discover connected services, find an action, read its input schema, and execute it. A FastAPI backend manages provider definitions, connections, outbound requests, and run records. A Next.js console provides screens for browsing providers and actions, managing connections and runtime tokens, and reviewing activity. SQLite stores application data locally by default, with PostgreSQL supported via SQLAlchemy async and Alembic migrations.
The catalog currently registers 263 providers with 8,472 actions (counted from server/app/providers/registry.py and actions_catalog.json) spanning Developer tools, Project Management & CRM, Communication, Storage, AI/ML, E-Commerce, Social Media, Financial, and Utilities. For a complete list of all 263 providers, auth types, action counts, and category classifications, see PROVIDER_GUIDE.md. Registered does not mean battle-tested: not every provider action or OAuth flow has been verified against a live account, so confirm the ones you depend on.
Features
- MCP gateway: Model Context Protocol (MCP) JSON-RPC 2.0 endpoint over
POST /mcpand tool discovery overGET /mcp/tools. Every remote MCP call fails closed and requires an admin or runtime token with granular scope enforcement. - Scoped runtime tokens: hashed, revocable tokens with deny-by-default action grants plus optional connection and proxy restrictions.
- OAuth: authorization URL, state and code exchange, encrypted token storage, and refresh for providers that support OAuth.
- Action discovery: agents can list providers, search actions, inspect action guides and schemas, and execute actions.
- Direct MCP actions: provider actions are exposed as individual MCP tools (scoped to caller token grants), alongside discovery and execution meta-tools.
- REST API: list providers and actions, execute an action, or use a provider proxy where supported.
- Connections & credentials: save named provider connections; credential values are encrypted at rest with AES-256-GCM.
- Local web console: browse the 263-provider catalog, configure connections, execute test runs, and manage runtime tokens and audit logs.
- Outbound HTTP safeguards: SSRF protection with hop-by-hop redirect verification, cross-origin secret stripping, response size caps, and socket-level IP address pinning to eliminate DNS-rebinding attacks.
- Idempotent execution: action requests can use an
Idempotency-Key; matching completed requests return saved responses and detect payload conflicts. - Run records: action executions record duration, HTTP status, and bounded, secret-redacted input/output summaries.
- Unified catalog: 8,472 action schemas maintained in
server/app/providers/actions_catalog.jsonand registered through extensible Python providers.
How it compares
These products overlap in connecting apps to software and AI agents, but they have different scopes. Composio centers on a large app toolkit and agent execution platform. Nango focuses on building and operating product integrations, including auth and sync. Merge.dev provides unified APIs and common models across product integration categories. Arcade.dev focuses on agent-ready tools, authentication, and runtime controls. Open Agent Connector is a self-hosted integration gateway for teams who want to inspect, own, and customize their agent runtime.
Architecture
Agent or application
│
├── MCP JSON-RPC: POST /mcp (authenticated)
└── REST: /v1/* (authenticated execution)
│
FastAPI action runtime
├── provider and action registry (263 providers / 8,472 actions)
├── principal resolution & deny-by-default policy enforcement
├── connection & AES-256-GCM credential encryption
├── DNS-pinned guarded outbound HTTP client (SSRF & rebinding guard)
└── audit run logs and idempotency records
│
SQLite / PostgreSQL database + external provider APIs
│
Next.js web console ────────┘
Stack
Provider catalog overview
The registry includes 263 providers across 10 functional domains. Below is a representative cross-section:
For the complete 263-provider matrix and action schemas, consult PROVIDER_GUIDE.md. Provider definitions and action schemas can also be queried programmatically via GET /v1/providers and GET /v1/actions.
Quick start
Requirements
- Python 3.11 or newer
- Node.js and npm
1. Run the API
cd server
python -m venv venv
source venv/bin/activate
python -m pip install -r requirements.txt
uvicorn main:app --host 127.0.0.1 --port 8000 --reload
On Windows PowerShell, activate the environment with:
venv\Scripts\Activate.ps1
The API creates its SQLite database and a local encryption key on first startup if they do not exist. For a durable deployment, configure and back up a stable key before saving credentials; losing the key makes previously encrypted credentials unreadable.
2. Run the web console
Open another terminal from the repository root:
cd client
npm install
npm run dev
Open http://localhost:3000. The console uses http://localhost:8000 for the API by default. Set NEXT_PUBLIC_API_URL before starting or building the frontend to use a different API URL.
Local service URLs
- Web console:
http://localhost:3000 - Health check:
http://localhost:8000/health - Interactive API docs:
http://localhost:8000/docs - MCP endpoint:
http://localhost:8000/mcp - MCP tool preview:
http://localhost:8000/mcp/tools
Configuration
Backend settings use the CONNECTOR_ environment prefix. A .env file in the server/ directory is loaded when you launch Uvicorn from that directory.
Set CONNECTOR_ENCRYPTION_KEY to a strong, stable secret before creating connections in an environment you need to preserve. Back up the key separately from the database and restrict access to both. Do not commit .env files or secret values.
Connect an account
- Start both the API and web console.
- Open the Connections screen and select any of the 236 providers.
- Add the required token, API key, or OAuth credentials and choose a connection alias, such as
default. - Browse the Actions screen to inspect available operations, required scopes, and JSON input schemas.
- Generate a scoped runtime token on the Tokens screen granting access to selected actions and connection aliases.
- Use MCP or the REST API to execute actions securely under that token.
GitHub and Slack credentials are validated against their provider APIs when saved. Hacker News does not require credentials. Custom HTTP can use no auth or a saved API key.
MCP usage
Configure an MCP client (such as Claude Desktop, Cursor, or Antigravity) that supports remote HTTP MCP with the local endpoint:
{
"mcpServers": {
"open-agent-connector": {
"url": "http://localhost:8000/mcp",
"headers": {
"Authorization": "Bearer <runtime-or-admin-token>"
}
}
}
}
A token is required. Unauthenticated, invalid, or revoked tokens receive 401. Tool discovery and execution are filtered by the token's action and connection grants.
The MCP gateway provides five discovery and execution meta-tools:
list_apps: list providers with display names, categories, and authentication requirements.list_connections: list configured accounts with safe identities (filtered by token grants).search_actions: search 8,024 catalog actions by keywords or provider service ID (scoped to token grants).get_action_guide: retrieve full Markdown parameter documentation and JSON Schema for an action.execute_action: execute an authorized action with input arguments and target connection alias.
Individual provider actions are also exposed as direct MCP tools (e.g. github_get_current_user), dynamically filtered by the caller's authorized action permissions. An action call may include a connectionName argument; it defaults to default.
REST API examples
List providers (catalog browsing is public):
curl http://localhost:8000/v1/providers
Search actions across catalog:
curl 'http://localhost:8000/v1/actions?service=github&query=issue'
Execute an action with a runtime token:
curl -X POST http://localhost:8000/v1/actions/github.get_current_user \
-H 'Authorization: Bearer <runtime-or-admin-token>' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: example-request-001' \
-d '{"input": {}, "connectionName": "default"}'
Main routes
Action execution accepts an input object and optional connectionName. You can also select a connection with the x-connector-alias header. The Idempotency-Key header is supported on action execution.
Extending the catalog
Providers are registered in server/app/providers/registry.py. Built-in implementations live in server/app/providers/builtins/ and share the base classes in server/app/providers/base.py.
To add a new provider action:
- Define its stable action ID, display name, description, input JSON schema, and required scopes.
- Implement its asynchronous
executemethod using the shared HTTP client and the provider credential passed to it. - Register it from the provider implementation and register the provider in the registry.
- Add or update credential validation if the provider requires authentication.
- Confirm the action schema works through both the REST API and MCP clients.
Provider actions are maintained in a unified catalog at server/app/providers/actions_catalog.json, partitioned by provider service ID for scalable expansion.
Data and security notes
-
The default database and generated local key are stored under
server/data/; keep this directory out of source control and protect it in backups. -
Connection credentials and OAuth tokens are encrypted at rest with AES-256-GCM. The database alone is not sufficient to recover them; the encryption key must also be preserved securely.
-
Outbound requests check resolved IP addresses and block private or internal destinations by default. The
CONNECTOR_ALLOW_PRIVATE_NETWORKoption relaxes some private-address blocking and should be used only in a controlled environment. Loopback, link-local, and metadata addresses remain blocked. -
Run logs keep bounded summaries of action inputs and outputs with sensitive credentials automatically redacted.
-
Authentication is enforced per route:
-
Outbound HTTP / SSRF Defense: All outbound provider calls execute through
GuardedTransport, which validates target IP addresses and pins TCP connections directly to the vetted IP, preventing DNS rebinding (TOCTOU) attacks while preserving TLS SNI and certificate validation. Private subnets, loopback, link-local, and cloud metadata (e.g. AWS/GCP169.254.169.254) are strictly blocked. -
Behind a reverse proxy, set
CONNECTOR_EXPOSE_LOCAL_TOKEN=false, bind the API to loopback or a private network, terminate TLS at the proxy, and rate-limit/api/auth/verify. Seedocker-compose.prod.ymlfor a loopback-only overlay. -
Database Portability & Deployment: Backed by SQLite async by default with auto-migration, with PostgreSQL supported via SQLAlchemy async and versioned Alembic migrations (
alembic upgrade head). A single-instance deployment is recommended until distributed locking and replication coordination are configured across multiple instances.
Tenancy
Every tenant-owned row (connections, OAuth state, runtime tokens, run logs, idempotency records) carries a
tenant_id. A self-hosted install uses a single default tenant, so nothing changes for you. The core
enforces the boundary on every query: services take tenant_id as a required argument, and a tenant id
only ever comes from the authenticated principal or from server-side state created for it (for example the
OAuth state record), never from request input.
- Connection names are unique per tenant, so two tenants can each have a
github/defaultconnection. - OAuth client credentials a tenant supplies are stored per tenant. Credentials from the server
environment belong to the operator and are used only by the
defaulttenant. - Unauthenticated visitors (only when
CONNECTOR_ALLOW_PUBLIC_ACCESSis turned on; it is off by default) live in a separatepublictenant and never see the operator's data. - A multi-user or hosted layer plugs in through two hooks in
app.core.tenancy:register_principal_resolver(...)maps its own credentials (API keys, sessions) to aPrincipalwith atenant_id(kindtenant_adminfor the management API,runtimefor agents), andregister_token_extractor(...)lets it read a credential from somewhere other than the standard headers (for example a session cookie). A resolver can raise a 401 for a credential it recognises but finds invalid, so that request never falls back to the public sandbox. Platform-wide hosted OAuth credentials remain operator-only. The open core itself has no user accounts: it is meant for your own agents, with the admin token and scoped runtime tokens.
server/tests/test_tenant_isolation.py is the contract: two tenants, the operator, and anonymous visitors
try to reach each other's data through every route.
Production deployment
# .env.prod: PUBLIC_ORIGIN=https://connector.example.com
# ADMIN_TOKEN=<long random value> ENCRYPTION_KEY=<long random value>
docker compose -f docker-compose.yml -f docker-compose.prod.yml --env-file .env.prod up -d --build
This publishes the API on 127.0.0.1:8100 and the console on 127.0.0.1:3100. Put nginx or another TLS-terminating proxy in front: route /api, /v1, /mcp, /health, and /docs to the API and everything else to the console. Back up .env.prod and the connector_data volume together; without the encryption key, saved credentials cannot be decrypted. Run one instance only.
Backups
deploy/backup/connector-backup.sh takes a consistent snapshot of the SQLite database while the service is
running (SQLite's online backup API), verifies it, keeps 14 days of history, and saves the env file (which holds
ENCRYPTION_KEY) whenever it changes. Run it daily from root's cron:
15 3 * * * COMPOSE_DIR=/home/ubuntu/open-agent-connector /home/ubuntu/open-agent-connector/deploy/backup/connector-backup.sh >> /var/log/connector-backup.log 2>&1
Snapshots land in /var/backups/connector (override with BACKUP_DIR). They protect against corruption and bad
migrations but not against losing the machine, so copy that directory off the host as well. The database holds
credentials encrypted with the key, so store the key backup separately from the database backup when you copy
them off the host.
To restore: stop the server, replace the database file in the data volume with a snapshot
(gunzip -k connector-<time>.db.gz), and start the server again. Check with PRAGMA integrity_check first.
Development
Backend dependencies are listed in server/requirements.txt. Frontend scripts are defined in client/package.json:
cd client
npm run lint
npm run build
For API changes, run the backend locally with Uvicorn's reload option and use /docs to inspect the generated OpenAPI schema.
Run the in-process MCP authentication regression tests from server/:
pip install pytest pytest-asyncio
CONNECTOR_ADMIN_TOKEN=test-admin python -m pytest tests/test_mcp_auth_regression.py tests/test_mcp_security.py
Project status
Open Agent Connector provides 236 registered providers and 8,024 catalog actions with fail-closed MCP authentication, runtime token authorization, AES-256-GCM encryption, SSRF protection with DNS rebinding defenses, and versioned Alembic database migrations. Contributions that improve provider coverage, documentation, and agent workflows are welcome.
License
Open Agent Connector is licensed under the Apache License 2.0. Unless you state otherwise, any contribution you submit for inclusion is licensed under the same terms (section 5 of the license).