Documentation Index
Fetch the complete documentation index at: https://docs.corsair.dev/llms.txt
Use this file to discover all available pages before exploring further.
This is the single source of truth for setting up Corsair App in a user’s project. Humans: read Introduction first. Agents: follow this page end-to-end; fetch linked docs for path-specific details rather than guessing.
Package: @corsair-dev/app · Doc index: llms.txt · Integrations: catalog
Prerequisites
The user adds a developer API key to .env as CORSAIR_DEV_KEY (create one). Scope it to the relevant instance(s). Secrets are shown once — never log or commit them.
npm install @corsair-dev/app
import { createClient } from "@corsair-dev/app";
const corsair = createClient({ apiKey: process.env.CORSAIR_DEV_KEY! });
Use instance id (opaque), not display name, in API calls and env (CORSAIR_INSTANCE_ID).
Goal
Use the SDK to provision and wire Corsair into the user’s project. Ask the user when something is ambiguous — do not guess instance names, tenant ids, or plugins from the repo folder name.
Prefer minimum project changes: env vars, a thin server helper if needed, and only the client config (MCP, etc.) the user asked for. Do not add committed setup scripts unless the user wants repeatable/CI provisioning.
The user connects OAuth / API keys via a connect link you mint in code (t.connectLink.create()), or in the dashboard for debugging.
Flow overview
Work through these in order. Ask the user at any step when you cannot infer the answer from their message or discovery results.
- Product intent — how will this project use Corsair?
- Instance — find or create
- Plugins — install what the project needs
- Tenant — find or create
- Wire the project — env, code, connect link, optional MCP/SDK config
1. Product intent
Before writing project code, understand what this product does with Corsair. If unclear, ask — e.g. “What should this project do with Corsair — integrate a coding agent via MCP, add in-app chat, or call specific integrations from your backend/UI?”
| Intent | What to set up |
|---|
| UI feeds, lists, dashboards (read-heavy) | tenant.run() with *.db.* paths — read Corsair’s synced cache; use *.api.* only on explicit refresh/write |
| Backend buttons, workflows, known API calls (writes or one-offs) | tenant.run() with *.api.* paths — no agent loop |
| Cursor, Claude Code, Codex, etc. | Coding agent MCP + client config |
| In-app AI chat (Vercel AI, OpenAI, Claude SDK) | Agent SDKs — wire MCP tools; do not put Corsair operation names in the system prompt |
Do not configure Cursor MCP (or any coding-agent client) just because you are running inside Cursor. Only set up MCP when the user wants that.
2. Instance
const { instances } = await corsair.instances.list();
| Situation | Action |
|---|
| No instances | Create one: await corsair.instances.create({ name: "…" }) — use a sensible name from the project or ask the user |
| One instance | Use it unless the user said otherwise |
| Multiple instances | Ask the user which to use — show name and id from the list |
| User named an instance | Match by display name, then use its id |
CORSAIR_INSTANCE_ID already in env | Verify it exists; confirm with the user if discovery shows others |
const inst = corsair.instance(instanceId);
See Instances and plugins.
3. Plugins
const { plugins } = await inst.plugins.list();
| Situation | Action |
|---|
| User named integrations (e.g. GitHub, Slack) | await inst.plugins.upsert("github", { mode: "cautious" }) — see catalog for plugin ids |
| Unclear which plugins | Ask the user which services this project needs |
| Already installed | Skip unless the user wants config changes |
Use useManaged: true for managed OAuth when appropriate. Fetch Instances and plugins for auth types and permissions.
4. Tenant
const { tenants } = await inst.tenants.list();
| Situation | Action |
|---|
| No tenants | Create one: await inst.tenants.create("your-id") or await inst.tenants.create() for a generated id — ask the user for a tenant id if this maps to their users/workspaces |
| One tenant | Ask the user to confirm, unless they already specified it |
| Multiple tenants | Ask the user which to use — show tenant ids from the list |
CORSAIR_TENANT_ID already in env | Verify it exists on the instance |
Never invent tenant ids from the repo or folder name. List tenants and ask, or use an id the user provides.
const t = inst.tenant(tenantId);
See Tenants and auth.
5. Wire the project
npm install @corsair-dev/app if not already present
- Persist env (never commit secrets):
CORSAIR_DEV_KEY, CORSAIR_INSTANCE_ID, CORSAIR_TENANT_ID
- Add a thin server helper if the app will call Corsair — e.g.
src/lib/corsair.ts:
import { createClient } from "@corsair-dev/app";
export const corsair = createClient({ apiKey: process.env.CORSAIR_DEV_KEY! });
export function corsairTenant(tenantId = process.env.CORSAIR_TENANT_ID!) {
return corsair.instance(process.env.CORSAIR_INSTANCE_ID!).tenant(tenantId);
}
- Connect accounts — if the tenant still needs OAuth or API keys:
const { url } = await t.connectLink.create(); // optional: { plugins: ["github"] }
// Send url to the user to open in a browser
Pick operations from the catalog
Fetch the integrations catalog — same data as MCP list_operations / get_schema, as markdown:
https://api.corsair.dev/md/integrations — plugin ids
https://api.corsair.dev/md/integrations/github — all paths for a plugin (*.api.*, *.db.*, webhooks)
https://api.corsair.dev/md/integrations/github.api.issues.list — input/output schema for one path
Use those paths in tenant.run(). No separate probe step — read the catalog, then call the endpoint.
Direct execution (backend / UI)
See Direct execution.
Read-heavy UI (feeds, search, detail pages): prefer github.db.* (or <plugin>.db.*) so the app reads Corsair’s synced database instead of calling the third-party API on every page load. Add a user-triggered Resync (or similar) that calls *.api.* list endpoints to refresh the cache, then re-read from *.db.*.
Writes and one-off actions: use *.api.* via tenant.run() when the backend already knows the exact operation.
// Read open issues from the synced cache (good for a feed)
const { data: rows } = await t.run("github.db.issues.search", {
data: { url: { contains: "corsairdev/corsair" } },
limit: 100,
offset: 0,
});
// Refresh cache from GitHub (good for a Resync button)
await t.run("github.api.issues.list", {
owner: "corsairdev",
repo: "corsair",
state: "open",
perPage: 100,
});
// Write when the user clicks a button
const result = await t.run("github.api.issues.createComment", {
owner: "corsairdev",
repo: "corsair",
issueNumber: 42,
body: "Thanks for the report!",
});
if (!result.success) {
// redirect user to result.signInLink
}
Coding agent MCP (only when requested)
See Coding agents and the client page (e.g. Cursor).
const conn = await t.mcpKeys.connection();
const key = await t.mcpKeys.create("cursor"); // secret shown once → CORSAIR_MCP_SECRET
// Wire only the client the user asked for (e.g. .cursor/mcp.json)
Agent SDK (only when requested)
See Agent SDKs. Prefer tenant.mcp.createVercelClient() when the server holds CORSAIR_DEV_KEY.
Wire the MCP client and pass await mcpClient.tools() to your harness. Do not add Corsair operation names, run_script usage, or plugin paths to the system prompt — the hosted MCP server exposes list_operations, get_schema, and run_script so the agent discovers and invokes operations itself. Keep the system prompt to product context only (e.g. which repo or tenant the app serves).
Reference
| Topic | Doc |
|---|
| Integrations catalog (paths + schemas) | api.corsair.dev/md/integrations |
| Instances, plugins, permissions | Instances and plugins |
| Tenants, connect links, OAuth | Tenants and auth |
| Types and errors | Types and errors |
| Installation (API overview) | Installation |
Safety rules
- Never log or expose tenant API key secrets, OAuth tokens, or plugin credentials
- Permission requests must be approved in Corsair; agents cannot bypass them
- Ask the user when instance, tenant, or plugin choice is ambiguous — do not hardcode or guess from repo metadata
- Avoid extra setup scripts, env keys, and MCP config the user did not ask for
Self-hosted SDK
Use only when the user explicitly wants Corsair in their own process: SDK introduction, quick start, MCP adapters (stdio MCP, not hosted App).