AI-native Robinhood trading interface — single npm package with MCP server + TypeScript client.
src/client/— Robinhood API client (~50 async methods)src/server/— MCP server with 18 toolsbin/— CLI entry point (robinhood-for-agents)skills/— Claude Code skills for interactive usedocs/— Architecture, access controls, use cases, contributing
- Runtime: Bun
- Language: TypeScript (strict mode, ESM-only)
- MCP SDK:
@modelcontextprotocol/sdkv1.12+ (McpServer + StdioServerTransport) - Validation: Zod v3.24 (API responses + MCP tool schemas)
- Testing: Vitest (not
bun test— module isolation matters) - Linting: Biome v2
- Browser Auth: playwright-core (drives system Chrome, no bundled browser)
bun install
bun bin/robinhood-for-agents.tsbun run typecheck # tsc --noEmit
bun run check # biome lint + format
npx vitest run # all tests (use vitest, NOT bun test)Canonical skill source is skills/. Local .claude/skills/ contains symlinks for development.
Install MCP server + skills: bun bin/robinhood-for-agents.ts install
Skills use three-layer progressive disclosure:
- SKILL.md — MCP tool orchestration (default)
- reference.md — MCP tool API details (loaded on demand)
- client-api.md — TypeScript client library patterns (advanced, loaded on demand)
Available skills:
robinhood-for-agents- Unified skill: auth, portfolio, research, trading, options (dual-mode: MCP + client API)
import { RobinhoodClient, getClient } from "robinhood-for-agents";
// Class-based
const client = new RobinhoodClient();
await client.restoreSession();
const quotes = await client.getQuotes("AAPL");
// Singleton
const rh = getClient();
await rh.restoreSession();- All methods are
async(nativefetchunder the hood) - Multi-account is first-class: every account-scoped method accepts
accountNumber - Session cached in OS keychain via
Bun.secrets(macOS Keychain Services) — no plaintext fallback, no tokens on disk - Token refresh via
refresh_token+device_tokenwhen access token expires - Proper exceptions:
AuthenticationError,APIError - Do NOT use
phoenix.robinhood.com— it rejects TLS. Useapi.robinhood.comendpoints only.
- Browser login (
robinhood_browser_login) opens a Chromium-based browser via playwright-core. On macOS, Brave and Chrome are auto-detected; otherwise useBROWSER_PATHorrobinhood-for-agents login --chrome /path/to/browser. - Purely passive — Playwright intercepts
/oauth2/tokennetwork traffic, never interacts with the DOM - Request body (JSON) → captures
device_token; Response → capturesaccess_token+refresh_token - Tokens stored directly in OS keychain via
Bun.secrets(never on disk) restoreSession()validates cached token, falls back to refresh, then directs to browser login
- NEVER place bulk cancel operations
- NEVER call fund transfer functions
- ALWAYS confirm with user before placing any order
- Order tools require explicit parameters - no defaults that could cause accidental trades
- NEVER use real PII in code, docs, examples, or commit messages — this includes account numbers, tokens, device IDs, email addresses, and any other user-identifying data. Use placeholders like
"ACCOUNT_ID","xxx-token", etc.
npx vitest runTests use vi.mock() to mock HTTP layer — no real API calls. Use vitest (not bun test) for correct module isolation.