Skip to main content

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.
  1. Product intent — how will this project use Corsair?
  2. Instance — find or create
  3. Plugins — install what the project needs
  4. Tenant — find or create
  5. 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?”
IntentWhat 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();
SituationAction
No instancesCreate one: await corsair.instances.create({ name: "…" }) — use a sensible name from the project or ask the user
One instanceUse it unless the user said otherwise
Multiple instancesAsk the user which to use — show name and id from the list
User named an instanceMatch by display name, then use its id
CORSAIR_INSTANCE_ID already in envVerify 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();
SituationAction
User named integrations (e.g. GitHub, Slack)await inst.plugins.upsert("github", { mode: "cautious" }) — see catalog for plugin ids
Unclear which pluginsAsk the user which services this project needs
Already installedSkip 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();
SituationAction
No tenantsCreate 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 tenantAsk the user to confirm, unless they already specified it
Multiple tenantsAsk the user which to use — show tenant ids from the list
CORSAIR_TENANT_ID already in envVerify 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

  1. npm install @corsair-dev/app if not already present
  2. Persist env (never commit secrets): CORSAIR_DEV_KEY, CORSAIR_INSTANCE_ID, CORSAIR_TENANT_ID
  3. 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);
}
  1. 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:
  1. https://api.corsair.dev/md/integrations — plugin ids
  2. https://api.corsair.dev/md/integrations/github — all paths for a plugin (*.api.*, *.db.*, webhooks)
  3. 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

TopicDoc
Integrations catalog (paths + schemas)api.corsair.dev/md/integrations
Instances, plugins, permissionsInstances and plugins
Tenants, connect links, OAuthTenants and auth
Types and errorsTypes 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).