Add an OAuth or CLI Provider
Implement a cross-stack managed provider with scoped consent, a pinned runtime, deterministic effect classification, and action safety.
OAuth and trusted CLI providers are cross-stack features. A catalog entry alone is insufficient. Google Workspace is the reference CLI implementation. Meta Ads is the reference hybrid: a standard OAuth connection feeds a backend-owned MCP SDK server for direct Graph operations, while a trusted companion handles capabilities that need private local files. Organic X and X Ads use the same backend-owned provider pattern, but remain separate connectors: X uses OAuth 2.0 with PKCE and X Ads uses three-legged OAuth 1.0a.
For a hosted MCP server that advertises standard OAuth discovery, use the shared managed-MCP OAuth path in Add a Managed MCP. Keep this guide for providers that need service-specific consent behavior or a trusted CLI gateway.
First Decide Whether CLI Is Safe
Proceed only if the vendor CLI can:
- expose deterministic schema or dry-run information;
- distinguish reads from effects without executing the effect;
- run with a temporary isolated home;
- accept bounded files and output;
- avoid interactive persistent login state; and
- be pinned and verified in the image.
If classification is uncertain, fail closed. Prefer a managed MCP or defer the provider when these conditions cannot be met.
For a hybrid provider, keep the companion smaller than the managed tool surface. Reuse the OAuth credential in the backend, never the agent, and add companion operations only where structured MCP inputs cannot safely or efficiently carry private bytes.
1. Extend Shared Contracts
In packages/types/src/index.ts:
- add the managed runtime key;
- extend the OAuth provider union if this is a new provider;
- add the smallest provider capability shape;
- define selected service/tool names as bounded values; and
- add the trusted runtime definition.
Update catalog validation so kind, authentication, and policy remain identical across the catalog and trusted registry.
2. Add Catalog Presentation and Grants
Add a strict kind: "cli" catalog entry with provider resources, setup instructions, OAuth
authentication, service allowlist, categories, departments, and explicit profile grants. Do not put
commands, paths, downloads, or secrets in the catalog.
3. Model Durable Connection State
Use the existing integration row when the provider fits its typed configuration and credential envelope. Add a migration only when new durable provider state is genuinely required.
Store:
- encrypted refresh credential or API secret;
- selected services;
- access mode;
- redacted account identity;
- readiness and status; and
- authorization epoch effects.
Never expose the plaintext credential in a response.
4. Implement OAuth
The backend owns:
- authorization initiation;
- organization- and integration-bound state;
- PKCE where supported;
- callback validation;
- code exchange;
- incremental service-to-scope mapping;
- encrypted refresh credential storage;
- redacted account metadata;
- short-lived access-token refresh;
- same-account reauthorization policy;
- disconnect and revocation behavior; and
- frontend return redirects.
Add connect, callback, status, and disconnect OpenAPI documentation. Test replay, expired state, state mismatch, provider errors, wrong account, missing scopes, disconnect, and redaction.
Do not force every provider into OAuth 2.0. Keep the shared organization-bound state store and encrypted credential envelope, but model provider callback fields and reusable credentials accurately. For OAuth 1.0a, persist the request-token secret only in one-use state, match the callback token before exchange, and keep the consumer secret in deployment configuration.
5. Pin the Vendor Binary
- Download a fixed version during the backend image build.
- Verify per-architecture checksums.
- Install below
/opt/oblive/integrations/<provider>/<version>. - Keep the vendor binary off the global shell
PATH. - Verify the binary in the built image.
Never download or install the vendor tool during an agent run.
6. Build the Backend Gateway
Add a narrow provider adapter that:
- validates the integration capability;
- rejects auth, setup, and configuration commands;
- bounds pagination, time, input, and output;
- classifies the operation before execution;
- routes reads directly;
- routes effects through
integration-action.service.ts; - materializes short-lived credentials in a mode-
0600temporary home; - cleans up on success, error, cancellation, and stale recovery; and
- never returns provider credentials.
Large hybrid files should upload directly from the worker to an exact-key object-store grant. Verify ownership, declared size and type, file signature, and a server-calculated digest before proposal and again before execution. Stream or range-read the private object into the provider API; do not require the provider to fetch an Oblive URL.
Backend-owned MCP SDK providers
When a vendor API is usable but its hosted MCP is missing required tools or gated by account rollout, implement a managed tool provider behind the same integration gateway:
- Register fixed Zod schemas with the official MCP SDK on an in-memory server.
- Discover and call those tools through an SDK client so schema generation, validation, and hashes use the same contract.
- Keep endpoints, API version, paths, methods, fields, pagination, and retries allowlisted.
- Read the encrypted integration credential only inside the backend provider.
- Route every write through the existing durable action lifecycle.
- Keep the agent registry unchanged; managed integrations are injected dynamically through their backend gateway endpoints.
Do not register a credentialed managed provider as a static agent MCP server. That bypasses organization tool selection, Chat filtering, credential isolation, and action enforcement.
Keep provider mechanics in workspace packages when more than one backend or agent surface may need
them. @oblive/meta-ads, @oblive/x, and @oblive/x-ads own fixed API clients, tool schemas, and
upload primitives. Backend services own organization credentials, authorization, actions, private
object storage, and runtime policy. Prefer a small provider adapter over copying API logic into the
backend.
7. Add the Agent Launcher
Add a checked-in launcher under apps/agents/src/cli/<provider> and register only its
integration-owned directory in apps/agents/src/cli/registry.ts.
Copy the launcher and any login-shell environment file into that image-owned directory with
explicit modes. Do not symlink them back into /workspace/apps, because development bind mounts
replace image-time source files and their executable modes. Verify the exact launcher path in the
image and keep it off the global PATH.
The active run may receive:
- gateway URL;
- an environment-variable reference for its execution capability;
- enabled services; and
- the launcher directory prepended to its scoped login shell.
The vendor credential must not be inherited by the agent shell.
8. Add Provider-specific UI
Ordinary API-key integrations remain catalog-driven. OAuth providers need UI for service selection, access mode, connection initiation, callback results, redacted account state, reauthorization, and disconnect.
9. Add the Skill
Create a deterministic provider skill describing schema inspection, bounded reads, required idempotency and summary flags, file rules, approval/reconciliation exits, and provider-specific verification. The skill carries workflow—not credentials or executable configuration.
10. Verify Release
Test:
- ungranted shell cannot find the launcher;
- granted run can resolve only the launcher;
- read classification;
- write approval;
- stale authorization rejection;
- idempotency;
- unknown transport outcomes;
- file boundaries;
- credential cleanup;
- cross-organization isolation;
- image pin and checksum; and
- both backend and agent images after a launcher or binary change.