Corsair
Getting Started

Quick Start

Go from zero to a working GitHub integration in five minutes

Setup

Install

npm install corsair

Generate your encryption key

Corsair encrypts every stored credential with a Key Encryption Key (KEK). Click to generate one and copy it into your .env:

.env
CORSAIR_KEK=""

Keep this key safe

If you lose it, you lose access to all stored credentials. Treat it like a root password.

Migrate the database

Corsair needs five tables. Run this once, then you're done.

Install the driver, then run the migration:

npm install better-sqlite3
npm install --save-dev @types/better-sqlite3

sqlite3 corsair.db < migration.sql

Install GitHub plugin and create corsair.ts

npm install @corsair-dev/github

This is the one file that wires everything together. Create it at src/server/corsair.ts:

src/server/corsair.ts
import 'dotenv/config';
import Database from 'better-sqlite3';
import { createCorsair } from 'corsair';
import { github } from '@corsair-dev/github';

const db = new Database('corsair.db');

export const corsair = createCorsair({
    plugins: [github()],
    database: db,
    kek: process.env.CORSAIR_KEK!,
});

You'll add more plugins here later — slack(), linear(), gmail() — same pattern, just append to the array.

Optional: Add your GitHub token and run setup

Use Corsair with any integration. Here's an example of how to get started with Github.

  1. Go to GitHub → Settings → Developer settings → Personal access tokens (classic)
  2. Click Generate new token (classic)
  3. Select scopes: repo, read:org, read:user
  4. Copy the token — it starts with ghp_
export GITHUB_TOKEN=ghp_...

Run setup once with the Corsair CLI:

npm install @corsair-dev/cli
npx corsair setup --github api_key=$GITHUB_TOKEN --backfill

Corsair stores your token, creates the database rows, and fetches your GitHub data locally. Your agent can now query it instantly — no API call needed every time.

Interact with Corsair

There's multiple ways to use Corsair. Here's two easy ways:

Let the agent discover and call endpoints on its own. You prompt in plain English — Corsair handles the rest.

Install the MCP adapter alongside your preferred framework:

npm install @corsair-dev/mcp @anthropic-ai/sdk
agent.ts
import Anthropic from '@anthropic-ai/sdk';
import { AnthropicProvider } from '@corsair-dev/mcp';
import { corsair } from './src/server/corsair';

async function main() {
    const provider = new AnthropicProvider();
    const tools = provider.build({ corsair });
    const client = new Anthropic();

    const message = await client.beta.messages.toolRunner({
        model: 'claude-sonnet-4-6',
        max_tokens: 4096,
        tools,
        messages: [{
            role: 'user',
            content: 'Use Corsair to list my GitHub repos with the most open issues.',
        }],
    });

    for (const block of message.content) {
        if (block.type === 'text') console.log(block.text);
    }
}

main().catch(console.error);

Your agent gets four tools automatically — regardless of which framework you use:

ToolWhat it does
corsair_setupCheck auth and get credential instructions
list_operationsDiscover every available API endpoint
get_schemaInspect parameters for a specific endpoint
run_scriptExecute a JS snippet with corsair in scope

See MCP Adapters for Vercel AI SDK, Mastra, and more.

Call any endpoint from plain TypeScript — no agent, no framework required.

The pattern is always: corsair.[plugin].[api | db].[group].[method]()

API — live calls to GitHub:

// Get a specific repo
const repo = await corsair.github.api.repositories.get({
    owner: 'octocat',
    repo: 'hello-world',
});

console.log(repo.name); // "hello-world"

DB — query what's already cached locally:

After backfill runs (or after any API call), data lives in your database. Query it without touching the GitHub API:

// Every repo you've fetched — instant, no network
const repos = await corsair.github.db.repositories.search({});

// Filter in JS using camelCase data fields
const withIssues = repos.filter((r) => Number(r.data?.openIssuesCount ?? 0) > 0);

for (const repo of withIssues) {
    console.log(`${repo.data?.name} — ${repo.data?.openIssuesCount} open issues`);
}

What's next