A Model Context Protocol server for the Questrade personal trading API. Query your portfolio, look up symbols, check balances, and review orders through any MCP-compatible AI assistant.
Designed with outcome-oriented tools that serve user intent — not a 1:1 REST endpoint mirror. Each tool orchestrates multiple API calls internally to return complete answers, minimizing agent round-trips and context window usage.
curl -fsSL https://deno.land/install.sh | shOr see deno.com for other install methods.
- Log in to the Questrade API Hub
- Register a personal app (or use an existing one)
- Generate a refresh token — copy it for the next step
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"questrade": {
"command": "deno",
"args": ["run", "-A", "jsr:@mathuran/questrade-mcp"],
"env": {
"QUESTRADE_REFRESH_TOKEN": "<your-token>"
}
}
}
}Claude Code (.mcp.json in your project root, or ~/.claude/mcp.json globally):
{
"mcpServers": {
"questrade": {
"command": "deno",
"args": ["run", "-A", "jsr:@mathuran/questrade-mcp"],
"env": {
"QUESTRADE_REFRESH_TOKEN": "<your-token>"
}
}
}
}Cursor (Settings > MCP Servers > Add):
{
"mcpServers": {
"questrade": {
"command": "deno",
"args": ["run", "-A", "jsr:@mathuran/questrade-mcp"],
"env": {
"QUESTRADE_REFRESH_TOKEN": "<your-token>"
}
}
}
}Restart your MCP client and ask it to "show my portfolio" to verify the connection.
| Tool | Description |
|---|---|
get_portfolio |
Full portfolio overview — accounts, positions, and balances in one call |
get_positions |
Positions held in a specific account |
get_balances |
Cash balances and buying power for an account |
lookup_symbol |
Search by name/ticker, returns symbol details + live quote |
get_quotes |
Batch live quotes by symbol IDs |
get_price_history |
Historical OHLCV candle data |
get_option_chain |
Options chain with optional live quotes |
get_orders |
Order history with status/date filters |
get_account_activity |
Combined activities + executions timeline |
Trading tools (place_order, cancel_order) are implemented but disabled —
the server is read-only for now.
On startup the server:
- Validates
QUESTRADE_REFRESH_TOKENis set (from env var or.envfile) - Authenticates with Questrade's OAuth2 API
- Runs a smoke test to verify connectivity
- Starts listening on stdio for MCP requests
Tokens are single-use — each refresh produces a new token pair. The server persists tokens to a platform-appropriate config directory and auto-refreshes before expiry or on 401 responses.
| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/questrade-mcp/token.json |
| Linux | ~/.config/questrade-mcp/token.json |
| Windows | %APPDATA%/questrade-mcp/token.json |
If a token.json exists in the current working directory, it takes priority
(for backward compatibility with run-from-source setups).
git clone https://github.com/mathuransadagopan/questrade-mcp.git cd questrade-mcp cp .env.example .env # Edit .env with your refresh token deno task start
deno task dev
npx @modelcontextprotocol/inspector deno run -A src/main.ts
src/
├── main.ts # Entry point — .env loading + dispatch
├── main-stdio.ts # Stdio transport setup + smoke test
├── env.ts # Environment validation
├── auth.ts # OAuth token lifecycle (refresh, persist, auto-renew)
├── client-factory.ts # Questrade HTTP client (auto-auth, retry on 401)
├── server.ts # MCP server factory + tool registration
├── log.ts # Stderr logger
└── tools/
├── portfolio.ts # get_portfolio, get_positions, get_balances
├── market.ts # lookup_symbol, get_quotes, get_price_history, get_option_chain
└── trading.ts # get_orders, get_account_activity