agent-router
Can be added as a catalog peer via 'Add Peer from Template' (written to ~/.agent-router/peers.json), with call_cli enforcing an allowlist so agents can run approved Docker commands.
Runs allowlisted gh CLI commands through call_cli, e.g. listing pull requests, giving agents GitHub access without a separate GitHub MCP server.
Integrates Linear via CLI/API (preferably the existing Cursor MCP tools if present) for issue and project operations.
Dispatches work to the official Codex / ChatGPT extension, using the chatgpt.addToThread and chatgpt.addFileToThread commands to open the conversation or push an editor/explorer selection into the thread as context.
Allowlisted Railway CLI commands through call_cli for service status and deployment operations.
Uses the public Slack CLI (~/.slack/bin/slack) to run Slack API methods (e.g. chat.postMessage) and search Slack documentation, so an agent can post results to channels or look up Slack docs without a custom bot.
Allowlisted Stripe CLI/API access for querying and managing Stripe resources.
Allowlisted Supabase CLI/API access for checking status and managing Supabase projects and services.
Allowlisted Vercel CLI commands for checking and managing Vercel deployments and services.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent-routerroute this bug fix to Claude"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
One Cursor agent. Official Claude, Codex, and Slack. No scraped UIs.
A Cursor (or VS Code) extension that routes work. The agent in this window — any model — calls small MCP tools. For Claude / Codex / ChatGPT, the router opens the official extension (vscode://splitin.agent-router/launch). It does not run claude -p, codex exec, or those vendors’ HTTP APIs. GitHub / Railway / Slack CLI stay as tools. Cursor Cloud API is available only when you pass runtime=cloud.
Built internally at SplitIn as the tech side of a product, then packaged so others can install the same dispatcher. A tool specialist owns this folder end to end. It can stay MIT and later also power a hosted SplitIn service. Every contributor would have % equity in that hosted service.
Compose, do not rebuild: Slack CLI, Claude Code / Codex / ChatGPT extensions, Cursor Cloud Agents API (opt-in),
@modelcontextprotocol/sdk,tsup, vitest,@vscode/vsce.Indie-cheap: no extra daemon, no extra cloud, no extra seat. Secrets in env /
~/.agent-router, never in git.Out of the box: Marketplace / Open VSX install, F5, or a VSIX. Sidebar Peers + Jobs, Command Palette, editor/explorer handoff menus, URI handler.
Version by version: catalog JSON adds peers without a new adapter class.
This does not merge Composer, Claude’s sidebar, and Codex into one transcript. It is a dispatcher, the same way ideation-loop-system routes Slack threads instead of inventing a new bot per vendor.
Cursor agent (any model)
→ MCP tools (list_peers, route, call_cli, slack_api, list_jobs)
→ AgentRouter
→ Claude: vscode://splitin.agent-router/launch → Claude Code URI (prefills, does not auto-submit)
→ Codex / ChatGPT: same URI → chatgpt.addToThread (openai.chatgpt)
→ Cursor: Composer command if present; otherwise you already are the agent
→ Slack: ~/.slack/bin/slack api | SLACK_BOT_TOKEN
→ GitHub / Railway / Vercel / Supabase / Stripe / Linear: allowlisted CLI or API
→ ideation-hq: POST /hooks/jobs (failed jobs stay on the Slack thread)Table of contents
Related MCP server: agentforge
How this folder is built
open-internal-tools is a program repo: each folder is the tech of one product, MIT, install from that folder, one specialist owns it. Stack is chosen per job, not one language for the hub.
Folder | Language / runtime | How it is built |
zsh on macOS | LaunchAgent + | |
TypeScript on Node 20+ | Slack Bolt + Slack CLI + YAML integrations. Official | |
TypeScript |
| |
TypeScript + React | Package-only primitives, vitest, tsup. | |
vscode-agent-router (this folder) | TypeScript on Node 20+ | Cursor/VS Code extension + MCP stdio. Catalog JSON + adapters. Same compose rule: official CLIs and APIs. |
Shared defaults across those folders, followed here:
Internal, then package — ship a VSIX /
dist/others can load.Right tool for the job — extension host for
executeCommand/ URI handoff; stdio MCP for any model;catalog/peers.jsonfor generic CLIs.Pick existing OSS — do not scrape Claude or Codex UIs; do not persist API keys in
settings.json.One folder, one PR surface — keep Agent Router work inside
vscode-agent-router/.People and agents in sync — the product is that sync: Cursor agents call Claude/Codex/Slack instead of working in silos.
Getting started
git clone https://github.com/splitintech/vscode-agent-router.git
cd vscode-agent-router
npm install
npm test
npm run buildThen F5 (Run Agent Router Extension) or install the VSIX (see Install). Work in sync with other contributors and agents. PRs stay in vscode-agent-router/.
Use cases
Ten ways developers integrate Agent Router:
Consult Claude from Cursor — a Composer agent calls
route peer=claude action=consult runtime=ide(default). Agent Router opens Claude Code with a prefilled prompt. It does not auto-submit and does not runclaude -p.Fan-out a fix — same prompt,
runtime=ideonclaude,codex, andchatgpt; Jobs sidebar holds ids; poller canPOSTideation HQ/hooks/jobs.Handoff a selection to Claude Code — editor context menu prefills
vscode://anthropic.claude-code/open?prompt=…(does not auto-submit).Add the current file to Codex — explorer or editor title uses
chatgpt.addFileToThreadwhenopenai.chatgptis installed.Post a cloud result to Slack —
slack_api method=chat.postMessageor Agent Router: Post to Slack, using the public Slack CLI (~/.slack/bin/slack).Search Slack docs from the agent —
route peer=slack action=consultrunsslack docs search.List GitHub PRs without a GitHub MCP —
call_cli peer=github argv=["pr","list","--limit","5"](ghallowlist).Add Docker as a peer — Add Peer from Template writes
~/.agent-router/peers.json;call_clienforcesallow.Probe the laptop — Probe Transports / sidebar dots for which of
claude,codex,gh,railway, Slack CLI, and API keys are actually present.Status a Railway or Vercel service — catalog CLI rows, still one
call_clitool, no per-vendor MCP explosion.
Install
VS Code Marketplace — search SplitIn Agent Router, or:
code --install-extension splitin.agent-routerhttps://marketplace.visualstudio.com/items?itemName=splitin.agent-router
Cursor (Open VSX) — Extensions panel → search SplitIn Agent Router (splitin.agent-router), or:
cursor --install-extension splitin.agent-routerhttps://open-vsx.org/extension/splitin/agent-router
From this folder (VSIX / F5)
npm run packageIn Cursor: Extensions: Install from VSIX… → agent-router-0.1.0.vsix. Reload. Or F5 Run Agent Router Extension (.vscode/launch.json).
Publish a release (needs VSCE_PAT + OVSX_PAT in the environment):
npm run publish:marketplacesOn activate the extension registers MCP via Cursor cursor.mcp.registerServer when that API exists, otherwise it spawns dist/mcp.js. After install, a Cursor agent of any model can call the tools without a project mcp.json.
Keep the stdio binary for Claude Code or Codex MCP configs (and for the hub’s “reply as a peer” path):
{
"mcpServers": {
"agent-router": {
"command": "node",
"args": ["dist/mcp.js"]
}
}
}Claude Code and Codex extensions are not hard dependencies. If they are missing, handoff commands prompt you to install them.
MCP tools
Transport preference is MCP → CLI → API. If Railway/Supabase/Linear is already on Cursor MCP, the agent should call those tools directly. route with transport=mcp tells you the same instead of proxying MCP inside MCP.
Tool | What it does |
| Catalog ids, kinds, runtimes, transports |
| CLIs on PATH, API env vars, |
| Opens the VS Code/Cursor extension for |
| Allowlisted argv for a catalog CLI |
| HTTP to that peer’s |
|
|
| Cloud launches recorded by the router |
| Get or |
route peer=claude action=consult runtime=ide prompt="Summarize src/auth.ts"
route peer=chatgpt action=handoff params.promptId=chatgpt.plan params.memoryPacket="…"
route peer=codex action=consult runtime=ide prompt="Fix tests"
route peer=cursor action=consult runtime=ide prompt="Continue in Composer"
route peer=cursor action=launch runtime=cloud prompt="Add a README"
route peer=slack action=launch params.channel=C0123 text="Cloud job finished"
slack_api method=chat.postMessage channel=C0123 text="done"
call_cli peer=github argv=["pr","list","--limit","5"]
list_jobs
job_status jobId=ar-… refresh=trueruntime=local / cloud on claude, codex, and chatgpt is rejected (claude -p / codex exec / vendor HTTP). Default is runtime=ide. Local Cursor opens Composer if this build exposes a handoff command; otherwise you already are the agent. Cursor Cloud remains runtime=cloud.
Peers
Shipped in catalog/peers.json. User overlay: ~/.agent-router/peers.json.
Peer | MCP | CLI | API | Cloud / IDE |
cursor | — | — |
| default ide: Composer / you are the agent |
claude | — | refused | refused |
|
codex | — | refused | refused | same URI → |
chatgpt | — | refused | refused | same URI → |
ideation-hq | — | — |
| link jobs into the Slack thread |
slack | optional |
|
| — |
github | optional |
| api.github.com | — |
railway | optional |
| GraphQL | — |
vercel | optional |
| api.vercel.com | — |
supabase | optional |
| api.supabase.com | — |
stripe | optional |
| api.stripe.com | — |
linear | optional | — | GraphQL | — |
Slack
Same rule as mac-unlock-notify and slack-agent-hq: use Slack’s own surface, not a homemade bot.
Binary:
~/.slack/bin/slack(public CLI). Fingerprintd41d8cd98f00b204e9800998ecf8427e.Install:
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bashFallback:
SLACK_BOT_TOKEN→https://slack.com/apiCommands: Slack Auth Status, Post to Slack, selection → Handoff Selection to Slack
Settings:
agentRouter.slackTeamId,agentRouter.slackChannel(channel id, not a token)
slack api chat.postMessage channel=C0123456789 text="Hello from Agent Router"Cloud jobs
Launches (action=launch) write a JobStore row. The extension polls every agentRouter.pollIntervalMs (default 15s) and POSTs ideation HQ POST {hqUrl}/hooks/jobs with x-agent-router-secret (AGENT_ROUTER_JOBS_SECRET) so failed jobs stay on the Slack thread.
Cursor Cloud: GET https://api.cursor.com/v1/agents/{id} (CURSOR_API_KEY) when you explicitly pass runtime=cloud.
Set agentRouter.hqUrl / AGENT_ROUTER_HQ_URL and optional agentRouter.projectId. Set agentRouter.notifySlackOnJobComplete and a channel to post when a job hits succeeded/failed.
Unpushed local files are not on the cloud clone. Push (or pass a remote SHA) first.
IDE handoff
MCP route (including the node dist/mcp.js child) cannot call vscode.commands.executeCommand. It opens vscode://splitin.agent-router/launch?peer=&prompt=. The extension host then:
Claude:
vscode://anthropic.claude-code/open?prompt=— prefills a new tab, does not auto-submit, does not return a result.Codex / ChatGPT:
chatgpt.addToThreadafterensureExtension("openai.chatgpt").Cursor local/ide: Composer command from
probeCursorHandoffif present; otherwise “you are already the agent”.
Add a peer
Agent Router: Add Peer from Template, or edit ~/.agent-router/peers.json. Example:
{
"version": 1,
"transportPreference": ["mcp", "cli", "api"],
"peers": [
{
"id": "docker",
"title": "Docker",
"kind": "platform",
"runtimes": ["local"],
"capabilities": ["api"],
"transports": {
"cli": { "bin": "docker", "allow": ["ps", "compose"] }
}
}
]
}call_cli rejects argv that is not on allow. No new TypeScript adapter required.
Commands
Command | What it does |
Agent Router: Probe Transports | Refresh Peers tree + Output JSON |
Agent Router: List Peers | Catalog dump |
Agent Router: Handoff to Claude Code | Prefill Claude tab |
Agent Router: Handoff to Codex |
|
Agent Router: Add File to Codex |
|
Agent Router: Slack Auth Status |
|
Agent Router: Post to Slack |
|
Agent Router: Add Peer from Template | Write |
Agent Router: Open Job | Open job URL |
Editor context (selection): Claude, Codex, Slack. Explorer file: Codex add-file.
Settings and secrets
Do not put tokens in settings.json or this repo.
Setting / env | Purpose |
| Cursor Cloud Agents ( |
| HTTP fallback if Slack CLI is missing |
| Ideation HQ base URL for |
| Shared secret header |
| Default HQ |
| Prompt catalog (default: sibling |
| Git remote for Cursor cloud |
| Slack |
| Slack on terminal job status |
| Job poll interval |
| CLI/API timeout |
| Extra catalog file; user file still merges |
Layout
catalog/peers.json shipped peers (MCP / CLI / API / cloud / ide)
src/core/ vscode-free: router, registry, jobs, poll, probe
src/adapters/ cursor, claude, codex, slack, generic
src/transports/ spawn (no shell), Slack CLI resolve, HTTP
src/mcp/ createMcpServer + stdio bootstrap
src/ext/ VS Code: MCP host, trees, handoff, poller
src/extension.ts activate
tests/ vitest, no vscodeCore stays vscode-free so npm test and node dist/mcp.js never load the extension host.
Confirm it works
npm test
npm run buildThen in Cursor:
Probe Transports — sidebar Peers dots match CLIs on the machine
Handoff a selection to Claude and Codex (those extensions installed)
Slack Auth Status (or docs search if the CLI is present)
call_cligithub withargv=["config"]→ allowlist errorCloud launch (if keys exist) shows a row under Jobs
Careers
Own this dispatcher end to end — or explore SplitIn tech careers — at https://www.splitin.net/careers-requests.
License
MIT. See LICENSE. Program rules live with the hub: CONTRIBUTING.md.
Standalone repository
This product is maintained at vscode-agent-router. Clone this repository and run the documented setup from its root. The npm/package and API identities are preserved. See migration provenance and contributing. See release setup; publishing starts disabled pending external configuration.
Standalone prompt catalog
The extension and MCP builds include a pinned Ideation prompt catalog, so an adjacent checkout is not required. Explicit agentRouter.promptsDir or AGENT_ROUTER_PROMPTS_DIR configuration takes precedence; existing sibling and personal catalogs remain supported. The bundled snapshot is a generated consumer of Ideation Loop System, with per-file provenance in prompt-catalog.json. Update prompts/ and run npm run sync:prompts to regenerate src/core/bundledPrompts.ts when deliberately upgrading the catalog.
Run npm ci, npm run typecheck, npm test, and npm run package. The VSIX retains extension ID splitin.agent-router. Publishing to either marketplace remains a separate, credentialed release action.
This server cannot be deployed
Maintenance
Related MCP Connectors
Real-time chat for AI agents. Claude Code, Cursor, Cline and Codex join channels over MCP.
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
Real-time chat hub for AI agents — Claude Code, Cursor, Cline, Codex over MCP or REST.
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables multiple coding agents (Claude Code, Codex, Cursor) to discover each other's sessions, search transcripts, ask questions, and handoff tasks through a shared MCP server.54 npmMIT
- AlicenseNot gradedqualityBmaintenanceProvides 300+ MCP tools for orchestrating AI agents — including swarm coordination, self-learning memory, and task management — enabling MCP clients like Claude Code and Cursor to spawn, coordinate, and learn from specialist agents across sessions.21,333 npm1MIT
- AlicenseNot gradedqualityAmaintenanceExposes specialized agents as MCP tools so users can manage and triage Jira tasks, analyze repositories for health and conventions, generate commit/PR/DevOps patterns, assemble reports, produce slides and infographics, and run semantic search over a knowledge base. Everything is invokable directly from inside a coding session in Claude Code, Cursor, or Claude Desktop.1MIT
- AlicenseNot gradedqualityAmaintenanceExposes a governed suite of 38 OAuth-gated tools over one MCP endpoint, letting web-based AI chat clients read and edit files, run whitelisted shell commands, search, and use Git, SQLite, browser automation, DevTools, background tasks, ports, clipboard, notifications, and localhost services on the user's own machine. It also allows local IDEs and automation tools to connect directly over localhost for offline, low-latency access.MIT