Most agent integration tooling locks you into a single context. You wire up MCP servers for your LLM, then rebuild the same OAuth flows and API adapters when your backend cron job needs Slack or when your customer dashboard needs Google Calendar. Corsair (10,937 stars, trending #2 on GitHub TypeScript) takes a different path: a REST-first integration platform that serves agents, backend services, and user-facing dashboards from the same adapter layer.
This matters because production agent systems rarely live in isolation. The same integration that powers an agent’s tool call also needs to run in a scheduled job, appear in a multi-tenant admin panel, or handle webhook callbacks when a third-party service pushes updates. MCP-only tools force you to maintain parallel plumbing for each context.
The MCP-Only Trap
MCP (Model Context Protocol) is excellent for agent-to-tool communication. It defines a standard way for LLMs to discover and invoke functions. But MCP servers are stateless, session-scoped, and designed for synchronous request-response cycles. They don’t handle:
- OAuth token refresh across long-running sessions
- Webhook ingestion from third-party services
- Multi-tenant credential storage
- Backend job scheduling that needs the same API access
- User-facing dashboards where customers connect their own accounts
If you build MCP-only, you end up writing separate OAuth handlers, separate API clients, and separate credential stores for every non-agent context. Corsair solves this by putting a REST API in front of the integration layer. The same unified syntax works whether the caller is an LLM, a cron job, or a React component.
Architecture: REST API as the Integration Substrate
Corsair’s core is a REST API that normalizes third-party integrations. Each integration (Slack, Google Calendar, GitHub, etc.) exposes a consistent interface:
- Authentication: OAuth flows, token refresh, and credential storage handled by the platform
- Unified syntax: Same request shape across providers, regardless of underlying API quirks
- Webhook handling: Inbound events from third-party services routed to your application
- Multi-tenant support: User-scoped credentials, not global service accounts
The flow looks like this:
- User connects account: OAuth dance happens once, credentials stored in Corsair
- Agent makes tool call: LLM invokes a Corsair REST endpoint with user context
- Corsair translates: Platform maps the request to the provider’s API, handles auth, returns normalized response
- Same endpoint for backend: Your cron job hits the same REST endpoint with the same syntax
- Same endpoint for dashboard: Your frontend calls the same endpoint to display user data
This eliminates the adapter duplication problem. You write integration logic once, and it works in every context.
Deployment Shapes: Self-Hosted vs. Managed Hub
Corsair offers two deployment models:
| Deployment | OAuth Refresh | Webhook Handling | Data Ownership | Ops Burden |
|---|---|---|---|---|
| Self-hosted | You manage token refresh loops | You expose webhook endpoints | Full control, your infrastructure | High (credential storage, rotation, monitoring) |
| Managed Hub | Corsair handles refresh | Corsair receives webhooks, forwards to you | Data remains yours, processed on Corsair infra | Low (Corsair manages OAuth state) |
Self-hosting gives you complete control but requires running a credential store, managing token refresh timers, and exposing webhook endpoints with proper security. The managed Hub option offloads OAuth state management while keeping your user data in your application. Webhooks arrive at Corsair’s infrastructure, get validated, then forward to your callback URLs.
For production agent systems, the managed Hub reduces the surface area for OAuth token expiration bugs. Self-hosting makes sense if you need air-gapped deployments or have strict data residency requirements.
State Management: Markdown + Git for Knowledge Layer
Corsair uses markdown files in a git repository for its knowledge layer instead of a vector database or graph store. This is an opinionated choice with specific trade-offs:
Why markdown + git:
- Diffable: Every integration schema change is a commit
- Auditable: Full history of who changed what and when
- Portable: No database migration when you move environments
- Developer-friendly: Engineers can PR integration updates like code
Trade-offs:
- No semantic search: You can’t query “find all integrations that support calendar events” without grep
- No real-time indexing: Changes require a git pull, not a database query
- Scale limits: Works well for hundreds of integrations, gets awkward at thousands
- No fine-grained permissions: Git-level access control, not row-level
This works well for teams that treat integrations as infrastructure-as-code. It breaks down if you need dynamic, user-generated integration schemas or real-time search across integration metadata.
Tool Call Flow: Agent to Third-Party API
Here’s how an agent tool call flows through Corsair:
// Agent invokes a Corsair integration
const response = await fetch('https://api.corsair.dev/v1/integrations/slack/send-message', {
method: 'POST',
headers: {
'Authorization': `Bearer ${corsairApiKey}`,
'X-User-Context': userId // Multi-tenant credential lookup
},
body: JSON.stringify({
channel: '#general',
text: 'Agent-generated message'
})
});
// Corsair handles:
// 1. User credential lookup (OAuth token for this userId + Slack)
// 2. Token refresh if expired
// 3. Translation to Slack API format
// 4. Rate limit handling
// 5. Error normalization
// 6. Response mapping back to unified schema
The same endpoint works in a backend job:
// Cron job, same syntax
const response = await fetch('https://api.corsair.dev/v1/integrations/slack/send-message', {
method: 'POST',
headers: {
'Authorization': `Bearer ${corsairApiKey}`,
'X-User-Context': userId
},
body: JSON.stringify({
channel: '#alerts',
text: 'Scheduled report ready'
})
});
And in a user dashboard:
// React component, same syntax
const sendMessage = async (channel: string, text: string) => {
return fetch('https://api.corsair.dev/v1/integrations/slack/send-message', {
method: 'POST',
headers: {
'Authorization': `Bearer ${corsairApiKey}`,
'X-User-Context': currentUser.id
},
body: JSON.stringify({ channel, text })
});
};
The key is the X-User-Context header. Corsair looks up the OAuth credentials for that user and integration, handles token refresh, and proxies the request. The caller doesn’t need to know Slack’s API shape or manage OAuth state.
Security Boundaries: Credential Isolation and Scope
Corsair’s multi-tenant design creates clear security boundaries:
- User-scoped credentials: Each user’s OAuth tokens are isolated, not shared across tenants
- API key authentication: Your application authenticates to Corsair with a service-level API key
- User context header: You pass the user ID in
X-User-Context, Corsair enforces credential ownership - Scope validation: Corsair checks that the requested action matches the OAuth scopes granted by the user
The risk: if your API key leaks, an attacker can impersonate any user by setting X-User-Context. Mitigation options:
- Use short-lived API keys with rotation
- Add IP allowlisting if your backend has stable egress IPs
- Implement request signing (HMAC) for high-security contexts
- Run self-hosted Corsair behind your own auth layer
For agent systems, this means your LLM can’t accidentally access another user’s integrations. The user context must be explicitly passed, and Corsair enforces the boundary.
Observability: What You Need to Instrument
Corsair abstracts the integration layer, which creates observability gaps if you don’t instrument carefully:
What to log:
- User context on every request (which user’s credentials were used)
- Integration provider and action (e.g.,
slack.send-message) - Token refresh events (when OAuth tokens were renewed)
- Rate limit hits (which provider throttled you)
- Error codes from Corsair (distinguish auth failures from API errors)
What to trace:
- End-to-end latency from agent tool call to third-party API response
- Time spent in Corsair’s translation layer vs. provider API
- Retry attempts (Corsair may retry transient failures)
What to alert on:
- OAuth token refresh failures (user needs to re-authenticate)
- Sustained rate limit errors (you’re hitting provider quotas)
- Credential lookup failures (user disconnected the integration)
Without this instrumentation, you’ll see “integration failed” errors without knowing if the problem is Corsair’s translation layer, the provider’s API, or expired credentials.
Failure Modes and Mitigation
| Failure Mode | Symptom | Mitigation |
|---|---|---|
| OAuth token expired | 401 errors from Corsair | Corsair auto-refreshes, but if refresh token is invalid, user must re-auth. Implement re-auth flow in your UI. |
| Provider API rate limit | 429 errors | Corsair doesn’t queue requests. Implement exponential backoff in your agent orchestration layer. |
| Webhook delivery failure | Missed events from third-party | Corsair retries webhooks, but if your endpoint is down, events are lost. Use a message queue to buffer inbound webhooks. |
| Credential lookup latency | Slow tool calls | Corsair caches credentials, but cold starts are slow. Pre-warm cache for high-frequency integrations. |
| Provider API schema change | Malformed responses | Corsair maintains adapters, but new fields may not map. Pin integration versions in production. |
The biggest operational risk is OAuth token expiration. If a user’s refresh token becomes invalid (they revoked access, changed password, etc.), Corsair can’t auto-refresh. Your application needs a re-authentication flow that prompts the user to reconnect.
When to Use Corsair
Good fit:
- You’re building agents that need to access user-connected SaaS tools (Slack, Google Workspace, GitHub)
- You also need backend services or user dashboards to use the same integrations
- You want to avoid maintaining separate OAuth flows and API clients for each context
- You’re okay with the markdown + git knowledge layer trade-offs
- You need multi-tenant credential isolation
Poor fit:
- You only need agent-to-tool communication (MCP is simpler)
- You need real-time semantic search over integration metadata
- You require air-gapped deployments and can’t use the managed Hub (self-hosting adds ops burden)
- You need sub-100ms tool call latency (Corsair’s REST layer adds overhead)
- You’re integrating with APIs that don’t fit the REST model (gRPC, GraphQL subscriptions, etc.)
Technical Verdict
Corsair solves a real problem: the duplication of integration plumbing across agent, backend, and user-facing contexts. By putting a REST API in front of OAuth flows and third-party APIs, it lets you write integration logic once and use it everywhere. The markdown + git knowledge layer is a reasonable choice for teams that treat integrations as code, but it won’t scale to thousands of dynamically generated schemas.
The managed Hub option is the right default for most teams. Self-hosting only makes sense if you have strict data residency requirements or need to run air-gapped. Either way, you’ll need to instrument OAuth token refresh failures and provider rate limits carefully, because Corsair abstracts away the details that help you debug integration failures.
If you’re building a multi-tenant agent system that needs to access user-connected SaaS tools, Corsair eliminates a lot of repetitive adapter code. If you only need agent-to-tool communication, stick with MCP. The REST layer is overhead you don’t need.