loading…
Search for a command to run...
loading…
A unified API provisioning layer that provides AI agents with access to multiple services like weather, stocks, health data, maps, and LLMs through a single MCP
A unified API provisioning layer that provides AI agents with access to multiple services like weather, stocks, health data, maps, and LLMs through a single MCP endpoint. It handles account creation, key management, quota enforcement, and failover so developers never need to interact with individual provider portals.
The agentic API provisioning layer. Your AI agent gets weather, stocks, health data, maps, and frontier LLMs from a single endpoint. invariant creates the accounts, manages the keys, enforces the quotas, and falls back when something breaks. You never touch a developer portal.
One key in. Every API out.
A useful AI agent needs to call ten different services. An LLM, a weather API, a stock ticker, a geocoder, a health database, a charity lookup. Building that today means:
invariant collapses all of it into one managed layer. You connect once over MCP or REST, and the provisioning, routing, quota accounting, and failover happen above your agent.
| Provider | Category | Rate Limit | Key needed? |
|---|---|---|---|
| OpenFDA | Physical Health | 240 req/min | No |
| Mental Health Resources | Mental Health | unlimited | No |
| CoinGecko | Finance | ~50 req/min | No |
| Finnhub | Finance | 60 req/min | Free signup |
| Every.org | Social Impact | generous | Free signup |
| OpenWeatherMap | Environment | 60 req/min | Free signup |
| Anthropic Claude | AI | . | Paid |
| Google Gemini | AI | 1,500 req/day | Free (AI Studio) |
| HuggingFace | AI | generous | Free signup |
| Geoapify | Maps | 3,000 req/day | Free, no card |
On the hosted instance invariant handles every "Free signup" row for you. You never see those portals. Self-hosted instances can bring their own keys via environment variables.
┌─────────────────────┐
│ Your AI Agent │
│ (Claude, Cursor, │
│ Codex, custom) │
└──────────┬──────────┘
│ MCP (JSON-RPC) or REST
│ single key: x-pl-key
▼
┌─────────────────────────────────┐
│ invariant │
│ ┌───────────────────────────┐ │
│ │ auth + quota │ │
│ │ (Supabase + Upstash) │ │
│ ├───────────────────────────┤ │
│ │ reasoning layer │ │
│ │ (recommend / compare) │ │
│ ├───────────────────────────┤ │
│ │ provider router + fall- │ │
│ │ back + usage logging │ │
│ └───────────────────────────┘ │
└──────────┬──────────────────────┘
│ managed upstream credentials
▼
OpenFDA . Mental Health . CoinGecko . Finnhub . Every.org
OpenWeatherMap . Anthropic . Gemini . HuggingFace . Geoapify
invariant exposes the same engine through two interfaces.
1. MCP (recommended for AI clients). JSON-RPC over HTTP at POST /api/mcp. Works with Claude Desktop, Cursor, Claude Code, Windsurf, Cline, Continue.dev, Codex CLI, Goose, and the OpenAI Responses API.
2. REST (for custom code). Plain HTTP endpoints if you are building your own integration:
| Endpoint | Method | Purpose |
|---|---|---|
/api/providers |
GET | List every provider and its status |
/api/query |
POST | Execute an action on a provider |
/api/recommend |
POST | Ask invariant to pick the best provider for a goal |
/api/usage |
GET | Your current quota, tier, and per-provider breakdown |
/api/mcp |
POST | MCP JSON-RPC endpoint (same tools, agent-friendly shape) |
Every endpoint requires an x-pl-key: pl_... header.
Sign up at the hosted instance. You get one pl_... key. That is the only credential you ever see. Behind it, invariant is already holding every upstream account for you.
All clients connect to the same remote endpoint. No cloning, no building, no Node.js required.
URL: https://pclabs.dev/api/mcp
Header: x-pl-key: pl_your_key_here
claude mcp add invariant --transport http https://pclabs.dev/api/mcp --header "x-pl-key: pl_your_key_here"
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (Mac) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"invariant": {
"type": "http",
"url": "https://pclabs.dev/api/mcp",
"headers": {
"x-pl-key": "pl_your_key_here"
}
}
}
}
Restart Claude Desktop after saving.
Settings → Integrations → Add custom integration. Paste the URL and set the x-pl-key header in the form. No file editing.
Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json (per project):
{
"mcpServers": {
"invariant": {
"url": "https://pclabs.dev/api/mcp",
"headers": {
"x-pl-key": "pl_your_key_here"
}
}
}
}
Or via UI: Settings → Tools & Integrations → MCP → Add Server.
Edit ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"invariant": {
"url": "https://pclabs.dev/api/mcp",
"headers": {
"x-pl-key": "pl_your_key_here"
}
}
}
}
Or via UI: Cascade panel → MCP Servers → Configure.
https://pclabs.dev/api/mcp as the URLx-pl-key: pl_your_key_hereEdit ~/.continue/config.json:
{
"mcpServers": [
{
"name": "invariant",
"transport": {
"type": "http",
"url": "https://pclabs.dev/api/mcp",
"headers": {
"x-pl-key": "pl_your_key_here"
}
}
}
]
}
Edit ~/.codex/config.toml:
[mcp_servers.invariant]
type = "http"
url = "https://pclabs.dev/api/mcp"
[mcp_servers.invariant.headers]
x-pl-key = "pl_your_key_here"
Pass the MCP server directly as a tool:
response = client.responses.create(
model="codex-mini-latest",
tools=[{
"type": "mcp",
"server_url": "https://pclabs.dev/api/mcp",
"headers": { "x-pl-key": "pl_your_key_here" }
}],
input="What crypto prices are available?"
)
Edit ~/.config/goose/config.yaml:
extensions:
invariant:
type: mcp
enabled: true
transport: http
url: https://pclabs.dev/api/mcp
headers:
x-pl-key: pl_your_key_here
The MCP endpoint exposes four tools.
recommendDescribe what you need. invariant returns ranked providers with scores, reasoning, pricing, and availability. This is the agentic entry point. Agents should start here, not with query.
{
"need": "real-time crypto prices with no signup",
"priorities": ["no-auth", "cost"],
"budget": "free"
}
compareSide-by-side comparison of two or more providers on pricing, rate limits, strengths, and weaknesses.
{ "provider_ids": ["claude", "gemini"] }
list_providersBrowse the catalog, optionally filtered by category: physical_health, mental_health, financial, social_impact, environment, ai, maps.
queryExecute a specific action against a specific provider. The low-level primitive that recommend ultimately calls into.
{
"provider_id": "coingecko",
"action": "price",
"params": { "ids": "bitcoin", "vs_currencies": "usd" }
}
You can run your own invariant instance if you want to bring your own upstream credentials or host on your own infrastructure.
invariant runs as a single Node HTTP server defined in dev-server.ts, which mounts the route handlers in api/ plus the admin, signup, and waitlist routes. Railway auto-detects the start script, so no railway.toml or Procfile is required.
npm install
npm run build
npm start # runs dist/dev-server.js on $PORT
Point Railway at this repo and set the environment variables below in the Railway dashboard.
Platform (required):
| Variable | Description |
|---|---|
SUPABASE_URL |
Supabase project URL |
SUPABASE_SERVICE_KEY |
Supabase service role key (server-side only) |
UPSTASH_REDIS_REST_URL |
Upstash Redis REST URL |
UPSTASH_REDIS_REST_TOKEN |
Upstash Redis REST token |
ADMIN_PASSWORD |
Password gate for the admin API endpoints |
Upstream providers (optional). Omit a variable to disable that provider:
| Variable | Provider |
|---|---|
ANTHROPIC_API_KEY |
Anthropic Claude (console.anthropic.com) |
GOOGLE_GEMINI_API_KEY |
Google Gemini (aistudio.google.com) |
HUGGINGFACE_API_KEY |
HuggingFace (huggingface.co/settings/tokens) |
FINNHUB_API_KEY |
Finnhub (finnhub.io) |
COINGECKO_API_KEY |
CoinGecko. Optional, boosts rate limit. |
EVERY_ORG_API_KEY |
Every.org (partners.every.org) |
OPENWEATHER_API_KEY |
OpenWeatherMap (openweathermap.org/api) |
GEOAPIFY_API_KEY |
Geoapify (myprojects.geoapify.com) |
OPENFDA_API_KEY |
OpenFDA. Optional, boosts rate limit. |
Providers without a configured key show Status: Not configured in list_providers and return a 503 when queried. OpenFDA and Mental Health Resources work with no key at all.
Keys live in Supabase, not in an env var. Apply migration.sql to your project to create the accounts and usage tables, then create accounts through the admin endpoints (gated by ADMIN_PASSWORD) or by inserting rows directly. Each account row holds a pl_... key, a tier, a monthly quota, and a per-minute rate.
cp .env.example .env # fill in your values
npm install
npx tsx dev-server.ts # HTTP server with hot-restart via tsx
The server listens on $PORT (defaults to 3000). Hit http://localhost:3000/api/providers with your x-pl-key header to sanity check.
To run the stdio MCP fallback instead (see below), use npm run dev.
For MCP clients that cannot speak HTTP, the repo also ships a thin stdio proxy in src/ that forwards to a remote invariant backend:
npm install
npm run build
{
"mcpServers": {
"invariant": {
"command": "node",
"args": ["/absolute/path/to/invariant/dist/index.js"],
"env": {
"PL_API_KEY": "pl_your_key_here",
"PL_BACKEND_URL": "https://pclabs.dev/api/mcp"
}
}
}
}
MCP client env vars for the stdio path:
| Variable | Required | Description |
|---|---|---|
PL_API_KEY |
Yes | Your pl_ key |
PL_BACKEND_URL |
No | Override backend URL. Default: https://pclabs.dev/api/mcp |
lib/providers/my-provider.ts implementing the Provider interface from lib/providers/types.tsrecommend tool can surface itnpm run dev # stdio MCP server via tsx, no build
npm run build # compile TypeScript → dist/
npm start # run compiled standalone server (dist/dev-server.js)
npm test # run test.ts against local backend
Built on MCP, Hono, Supabase, and Upstash Redis.
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"invariant": {
"command": "npx",
"args": []
}
}
}Web content fetching and conversion for efficient LLM usage.
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also