Model Context Protocol server that lets AI assistants interact with the FerrLabs ecosystem (FerrFlow, FerrVault, FerrTrack, FerrGrowth, FerrFleet, FerrLens) through the unified FerrLabs API. Runs locally via stdio transport.
Add to your MCP client configuration (Claude Code, Cursor, etc.):
{
"mcpServers": {
"ferrlabs": {
"command": "npx",
"args": ["-y", "@ferrlabs/mcp"]
}
}
}The first time you call a tool that needs auth, the MCP opens auth.ferrlabs.com in your default browser (OAuth 2.0 loopback PKCE). After you click Allow, the token is saved locally and reused for future sessions. No env var required.
Bypass the browser dance by injecting a token directly:
{
"mcpServers": {
"ferrlabs": {
"command": "npx",
"args": ["-y", "@ferrlabs/mcp"],
"env": { "FERRLABS_API_TOKEN": "fl_..." }
}
}
}Create the token from app.ferrlabs.com → Settings → API Tokens. It's forwarded as x-api-token to api.ferrlabs.com.
This repo ships six MCP servers as separate npm packages. @ferrlabs/mcp is the unified entrypoint (orgs, billing, profile, public stats, docs); the four sub-MCPs target a specific product API. Add only the servers you need to your client config.
| Package | npm | Targets | Base URL env |
|---|---|---|---|
@ferrlabs/mcp |
@ferrlabs/mcp |
api.ferrlabs.com (unified) |
API_URL |
@ferrlabs/mcp-vault |
@ferrlabs/mcp-vault |
FerrVault secrets | API_URL |
@ferrlabs/mcp-track |
@ferrlabs/mcp-track |
api.ferrtrack.com |
FERRTRACK_API_URL |
@ferrlabs/mcp-growth |
@ferrlabs/mcp-growth |
api.ferrgrowth.com |
FERRGROWTH_API_URL |
@ferrlabs/mcp-fleet |
@ferrlabs/mcp-fleet |
api.ferrfleet.com |
FERRFLEET_API_URL |
All servers share the same auth resolution (env token or OAuth loopback, see below). Register several at once:
{
"mcpServers": {
"ferrlabs": { "command": "npx", "args": ["-y", "@ferrlabs/mcp"] },
"ferrlabs-vault": { "command": "npx", "args": ["-y", "@ferrlabs/mcp-vault"] },
"ferrlabs-track": { "command": "npx", "args": ["-y", "@ferrlabs/mcp-track"] },
"ferrlabs-growth": { "command": "npx", "args": ["-y", "@ferrlabs/mcp-growth"] },
"ferrlabs-fleet": { "command": "npx", "args": ["-y", "@ferrlabs/mcp-fleet"] }
}
}Tools marked destructive below are irreversible or high-impact (spend quota, switch live serving, delete data). MCP clients should gate them behind a confirmation.
| Tool | Scope | Notes |
|---|---|---|
get_stats, health_check, fetch_docs |
public | No auth required |
get_me, update_me, export_my_account, list_my_sessions, revoke_my_session |
auth | Current user |
list_orgs, get_org, get_org_overview, get_org_usage, update_org, list_org_audit |
auth | Organizations |
list_org_members, invite_org_member, remove_org_member, update_org_member_role |
auth | remove_org_member is destructive |
list_teams, create_team, update_team, delete_team, add_team_member, remove_team_member |
auth | delete_team is destructive |
list_projects, list_vaults, list_issues |
auth | Cross-product lists |
list_subscriptions, activate_subscription, update_subscription, cancel_subscription |
auth | cancel_subscription is destructive |
list_tokens, create_token, revoke_token |
auth | create_token needs a session; revoke_token is destructive |
| Tool | Notes |
|---|---|
get_vault, list_secrets, get_secret, get_vault_audit_log |
read |
list_secret_requests, archive_secret_request |
secret-request workflow |
create_vault, update_vault, delete_vault |
delete_vault is destructive |
create_secret, update_secret, rotate_secret, delete_secret |
rotate_secret/delete_secret are destructive |
| Tool | Notes |
|---|---|
list_projects, get_project, create_project, update_project |
projects |
list_issues, get_issue, create_issue, update_issue, list_issue_links |
issues |
list_issue_comments, create_issue_comment, update_issue_comment, delete_issue_comment |
delete_issue_comment is destructive |
list_cycles, get_cycle, create_cycle, update_cycle, delete_cycle, list_cycle_issues, plan_next_cycle |
delete_cycle is destructive |
list_milestones, get_milestone, create_milestone, update_milestone, delete_milestone |
delete_milestone is destructive |
list_track_users, search_track |
read |
| Tool | Notes |
|---|---|
list_sites, get_site, create_site, update_site, archive_site |
archive_site is destructive |
attach_domain, detach_domain, verify_domain |
custom domains |
list_pages, get_page, create_page, update_page, publish_page, discover_pages, import_pages |
pages |
list_forms, get_form, create_form, update_form, delete_form, list_form_submissions |
delete_form is destructive |
list_releases, get_release, activate_release |
activate_release is destructive (switches live serving) |
get_analytics_summary, get_seo_overview, run_seo_audit |
read / audit |
| Tool | Notes |
|---|---|
list_agents, get_agent |
read |
list_runs, get_run, get_run_transcript |
read |
trigger_agent_run |
destructive — executes an agent and spends run quota |
FerrFlow CLI-specific tools (dry_run, validate_config, read_config, read_changelog, list_release_tags, record_event) were removed in v4.0.0 — they required either a local FerrFlow CLI install or HMAC signing the MCP doesn't do. Use the FerrFlow CLI directly or fetch docs via fetch_docs("ferrflow", "docs/...").
| Component | Technology |
|---|---|
| Runtime | Node.js 22+ |
| Language | TypeScript |
| MCP SDK | @modelcontextprotocol/sdk |
| Transport | stdio (default) or Streamable HTTP |
| Variable | Description | Default |
|---|---|---|
API_URL |
FerrLabs API base URL (no /v1 suffix — paths are prefixed in code) |
https://api.ferrlabs.com |
FERRLABS_AUTH_URL |
Auth SPA base URL (where the OAuth browser flow lands) | https://auth.ferrlabs.com |
FERRLABS_API_TOKEN |
Pre-provisioned token. Bypasses the OAuth flow. Use for CI / scripted environments. | — |
FERRFLOW_API_TOKEN |
Deprecated — accepted as a fallback for backward compatibility with v3.x. | — |
FERRLABS_MCP_NO_OAUTH |
Set to 1 to disable the OAuth fallback. Then FERRLABS_API_TOKEN becomes required. |
unset |
FERRLABS_MCP_TOKEN_PATH |
Override the path where the OAuth-acquired token is persisted. | %APPDATA%\ferrlabs\mcp\token.json / ~/.config/ferrlabs/mcp/token.json |
FERRLABS_MCP_NO_PERSIST |
Set to 1 to keep the token in memory only (re-auth on every cold start). |
unset |
FERRTRACK_API_URL |
Base URL for the FerrTrack API (@ferrlabs/mcp-track). |
https://api.ferrtrack.com |
FERRGROWTH_API_URL |
Base URL for the FerrGrowth API (@ferrlabs/mcp-growth). |
https://api.ferrgrowth.com |
FERRFLEET_API_URL |
Base URL for the FerrFleet API (@ferrlabs/mcp-fleet). |
https://api.ferrfleet.com |
FERRLABS_MCP_MODE |
Transport: stdio (default) or http (Streamable HTTP). --http also selects http. |
stdio |
PORT |
Port for the HTTP transport (FERRLABS_MCP_MODE=http). |
3000 |
HOST |
Bind address for the HTTP transport. | 0.0.0.0 |
By default the server runs over stdio. Set FERRLABS_MCP_MODE=http (or pass --http) to expose the MCP over Streamable HTTP on HOST:PORT (0.0.0.0:3000 by default) — this is the mode the Docker image runs. Requests carry the bearer token in the Authorization header. Run the HTTP transport behind a gateway (e.g. Traefik) that terminates TLS and applies rate limiting / request-size caps; do not expose it directly on an untrusted network.
On the first authenticated tool call, the MCP looks for a token in this order:
- In-memory cache (set during this MCP process's lifetime)
FERRLABS_API_TOKEN(orFERRFLOW_API_TOKEN) env var- Persisted token file (
FERRLABS_MCP_TOKEN_PATH) - OAuth 2.0 loopback PKCE flow — opens the user's browser at
FERRLABS_AUTH_URL(auth.ferrlabs.com, the login SPA), captures the callback onhttp://127.0.0.1:54321/cb, then exchanges the code for a session token viaPOST /v1/auth/exchangeonAPI_URL(api.ferrlabs.com). Token is persisted to step 3 for future sessions.
If you set FERRLABS_MCP_NO_OAUTH=1, step 4 is skipped — useful for CI where opening a browser would hang.
Auth host split.
auth.ferrlabs.comis the user-facing login SPA (where the browserauthorizestep lands);api.ferrlabs.comperforms the token exchange and serves the OAuth discovery metadata used by the HTTP transport. ConfigureFERRLABS_AUTH_URLfor the former andAPI_URLfor the latter — they are not interchangeable.
pnpm smoke builds the server, spawns it over stdio, runs the MCP initialize/tools/list handshake, then calls health_check and get_stats against the real api.ferrlabs.com. Useful to confirm the server boots, registers all tools, and the API is reachable. Exits non-zero on any failure.
[PASS] initialize handshake — serverInfo: ferrlabs@6.5.0
[PASS] tools/list — N tools registered
[PASS] tools/call health_check — {"status":"ready", ...}
[PASS] tools/call get_stats — total_releases=N
Smoke: 4/4 OK
v4.0.0 renames the package and points the MCP at the unified FerrLabs API. To migrate:
- Replace
@ferrflow/mcpwith@ferrlabs/mcpin your MCP client config. - Rename
FERRFLOW_API_TOKEN→FERRLABS_API_TOKEN(the old name still works for one release). - If you were overriding
API_URL=https://api.ferrflow.com, drop the override — the default is nowhttps://api.ferrlabs.com.
Tokens issued by the legacy FerrFlow-only API are not valid against the unified API. Create a fresh one from app.ferrlabs.com.
Mozilla Public License 2.0 — see LICENSE.