API vs DB paths
Corsair plugins expose two families of operations:| Path pattern | What it does | When to use |
|---|---|---|
<plugin>.api.* | Live call to the third-party API (GitHub, Slack, …) | Writes, one-off reads, refreshing the synced cache |
<plugin>.db.* | Read/search Corsair’s synced database for that instance | UI feeds, lists, search, detail pages — avoids rate limits |
tenant.run("github.db.issues.search", …) (or the relevant entity). Corsair populates the DB when *.api.* endpoints run (e.g. during an explicit Resync). Design the UI to read from .db on every render and call .api only when the user asks to refresh or when performing a write.
/md/integrations/github for all GitHub paths, /md/integrations/github.api.issues.list for that endpoint’s schema. Then call tenant.run(path, input).
Run an operation
plugin.section.operation (e.g. github.api.repositories.star, github.db.pullRequests.search).
Connect the user
After provisioning, mint a connect link proactively and send it to the user:plugins, ttlMs).
Handle missing auth
run() returns a result object instead of throwing when the tenant still needs to connect a plugin:
connectLink.create() when you know the user still needs to connect accounts. Use signInLink when you discover missing auth at call time.
Permissions
Direct execution respects the same instance policies as MCP. Denied operations returnCorsairApiError with status 403.
MCP vs direct
| Use case | Use |
|---|---|
| Agent picks tools at runtime | Coding agents or Agent SDKs — MCP meta tools only; no operation hints in the system prompt |
| UI feeds / lists / search | tenant.run("<plugin>.db.*") |
| User-triggered refresh into cache | tenant.run("<plugin>.api.*") list/read endpoints |
| Backend knows the exact write | tenant.run("<plugin>.api.*") |