Connect your AI agent to ftInvstr
ftInvstr speaks the Model Context Protocol — Anthropic's open standard for letting AI agents discover and call tools on remote servers. Connect Claude, Cursor, Claude Code, Windsurf, VS Code, ChatGPT, or any Python agent — they all consume the same endpoint and the same 11 tools. Once connected, your AI can browse 60+ Indian equity strategies, fetch full stats, design and run real backtests end-to-end, and cancel jobs mid-flight.
01 Get your API key
- Log in at ftinvstr.in (or sign up if you haven't).
- Go to Profile → API Keys.
- Click Generate Key, label it (e.g. "Claude Desktop · MacBook").
- Copy the plaintext key shown. Keys look like
fti_aB3cD4eF5gH6iJ7…
02 Configure your AI client
Pick your client below — same endpoint, same Bearer header, format varies. After pasting the snippet, replace YOUR_KEY_HERE with the key from step 1.
The easiest setup — no API key, no JSON config, no Node.js. claude.ai handles the auth handshake automatically via OAuth.
- Open claude.ai. Click your profile icon (top-right) → Settings.
- In the left sidebar, click Connectors (or Custom Integrations, depending on your account's UI version).
- Click Add custom connector.
- Fill in:
- Name:
ftInvstr - Remote MCP server URL:
https://ftinvstr.in/mcp/
- Name:
- Leave the OAuth Client ID and OAuth Client Secret fields empty under Advanced settings — our server uses Dynamic Client Registration, no manual provisioning.
- Click Add, then click Connect on the new entry.
- You'll be redirected to ftinvstr.in. Sign in if prompted, then click Allow access on the consent screen.
- claude.ai redirects you back. Open a new chat and click the 🔧 tools icon — you should see ftinvstr · 11 tools listed.
Test prompt:
To revoke access later: in claude.ai → Settings → Connectors → remove the ftInvstr entry. That deletes the connector locally; the matching token on our side will simply expire (or you can also email us to force-revoke).
Edit your Claude Desktop config file (create it if missing):
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Claude Desktop only speaks stdio. Use the mcp-remote bridge to reach our HTTPS endpoint. Requires Node.js (brew install node or nodejs.org).
Fully quit Claude Desktop (Cmd+Q / right-click tray → Quit, not just close the window) and reopen. The 🔧 tools icon should now list ftinvstr with 11 tools.
Open Settings → MCP, or edit ~/.cursor/mcp.json directly:
Cursor speaks HTTP natively for remote MCP servers, so no Node bridge needed. Restart Cursor; the tool appears in the agent's tool list.
One-shot CLI command from any terminal:
Confirm with claude mcp list. The tool becomes available immediately in the next claude session — no restart needed.
Edit ~/.codeium/windsurf/mcp_config.json:
Restart Windsurf. The Cascade panel will list ftinvstr alongside other configured servers.
VS Code's GitHub Copilot Chat (1.96+) supports MCP via settings.json. Open Command Palette → "Preferences: Open User Settings (JSON)":
Reload window (Cmd+Shift+P → "Developer: Reload Window"). Copilot Chat agent mode will show ftinvstr tools.
ChatGPT supports remote MCP servers via the Connectors UI (ChatGPT Pro / Enterprise).
- Open Settings → Connectors → Add custom connector.
- Set Server URL to
https://ftinvstr.in/mcp/ - Under Authentication, choose "Bearer token" and paste your
fti_…key. - Save and enable the connector for the conversations where you want it.
The official mcp Python SDK works with any HTTP MCP server. Compatible with OpenAI Agents SDK, LangChain MCP adapter, and custom agents.
For OpenAI Agents SDK: pass the same headers when creating the MCP server connection (see openai-agents-python).
For LangChain: use langchain-mcp-adapters with the same URL + Bearer header.
Any HTTP client speaks JSON-RPC 2.0 directly. Useful for debugging or custom integrations.
Required protocol: MCP spec 2024-11-05, Streamable HTTP transport, JSON-RPC 2.0 framing. Initial initialize handshake is required before tools/call.
03 Verify the connection
In a new chat with your AI client, ask it to list its tools or run this prompt:
The agent should make two tool calls (search_strategies then get_strategy_stats) and return a structured answer in seconds.
04 Designing & running a backtest via your agent
Backtest submissions use an async pattern — your agent submits a job, polls for status, and fetches the result when done. Typical flow:
job_id so your agent knows what to poll (or cancel via stop_backtest).
get_expression_help are listed (with descriptions, examples, and field categories) at /function-docs/. Useful while you're sketching an expression before letting the agent run with it.
05 The 11 tools your agent can call
Read-only catalog (Phase 1)
| Tool | What it returns |
|---|---|
| list_strategies | Catalog overview — name, badges, factor family, rebalance frequency, full stats per strategy. |
| get_strategy_stats | One strategy's full stats — CAGR, Sharpe, Sortino, Calmar, max DD, year-by-year + equity / drawdown curves + monthly returns. |
| get_holdings | Actual current portfolio — ticker, company name, shares held, latest price, market value, weight %. |
| search_strategies | Filter the catalog by min CAGR, min Sharpe, max DD, universe. |
| get_rebalance_history | Aggregate rebalance activity — date + buy/sell counts per rebalance, no specific tickers. |
Writable backtests (Phase 2)
| Tool | What it does |
|---|---|
| get_expression_help | DSL reference — overview / fields (276 fields) / functions (36 operators) / functions:<name> (one-op detail) / examples. Same content humans browse at /function-docs/. |
| validate_expression | Syntax + field check before submit. Fast, no queue burn. Returns {ok: true} or specific error. |
| submit_backtest | Queues a real full-fidelity backtest. Args: expression, universe (NIFTY50 / 100 / 200 / 500 / 1000 / 2000 / ALL), start, end, max_positions, investment_mode (7 modes), rebalance_frequency (daily/weekly/monthly), name. Returns {job_id, status, universe, stocks_count, eta_seconds}. |
| get_backtest_status | Poll: queued / running / done / failed. Surfaces a progress dict (description + percent) during runs. |
| get_backtest_result | Fetch full stats when status is done. Same shape as get_strategy_stats. |
| stop_backtest | Cancel an in-flight backtest you submitted. Revokes the Celery task, drops the partial DB, removes the temp CONFIG. Idempotent. |
Investment modes (passed to submit_backtest)
| Mode | Behaviour |
|---|---|
| max_position_legacy | Default. Long-only, equal-weight slot-based top-N with score-driven swaps. Matches what most platform strategies use. |
| equal_weight_top_n | Long-only, strict equal weights across top-N each rebalance. |
| score_weighted_top_n | Long-only, weights proportional to score within top-N. |
| daily_top_n_long_short | 50/50 long top-N vs short bottom-N. |
| beta_neutral_top_n | Long-short scaled to net-zero beta vs NIFTY. |
| sector_neutral_top_n | Paired long-short within each sector. |
| regime_switching_dynamic | Regime-aware: long-only in bull/sideways, neutral or short in bear. |
06 Limits & safety
- 10 submit_backtest calls per day, per user. Resets at midnight UTC. Counter is per-user, shared across all your API keys.
- One concurrent backtest per user. A second
submit_backtestwhile one is in flight is rejected with the existingjob_id. Callstop_backtestto free the slot or wait it out. - Expression length cap: 5000 characters.
- Universes: seven friendly index labels —
NIFTY50,NIFTY100(default),NIFTY200,NIFTY500,NIFTY1000,NIFTY2000,NIFTYALL. Each = top-N of the broad listed pool ranked by market cap. Same expression across NIFTY50 vs NIFTY500 vs NIFTYALL gives you small-cap vs mid-cap vs full-market behaviour. - Date range:
start_date ≥ 2018-01-01. This floor exists because fundamentals data (qr, pl, bl, cf, rto and ML predictions derived from them) is sparse before 2018. Technical / price-only strategies (Close, Volume, momentum operators, beta) work back to 2015 — let us know if you need an earlier start for a pure-technical expression. - Read tools are unlimited (list / get / search / help / validate / status / result). Only
submit_backtestconsumes the daily quota.
07 Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
| 401 Unauthorized | Missing or invalid Bearer header. Re-copy from /profile/api-keys/. Header is case-sensitive: Authorization: Bearer fti_.... |
| Tools don't appear in Claude Desktop | Forgot to fully quit + reopen (Cmd+Q, not just close the window). Check ~/Library/Logs/Claude/mcp*.log on macOS. |
| command not found: npx | Node.js not installed locally. Install from nodejs.org or brew install node on macOS. |
| "You already have a backtest in flight" | Serialize gate — one job per user at a time. Poll get_backtest_status on the returned existing_job_id until done, or call stop_backtest. |
| "daily submit limit reached" | Hit the 10/day cap. Resets at midnight UTC. Read tools still work. |
| Backtest finished with 0 trades | Most common cause: a hard binary filter inside multiply(score, gt(...)) or multiply(score, lt(...)) zeroes out every stock because the gated field is sparse. Use the field as a weighted factor (multiply(rank('field'), 0.3)) inside an add(...) instead of as a hard gate. |
| "unknown or expired job_id" | Job records have a 7-day TTL in Redis. After that, results are only fetchable via list_strategies if the strategy was kept. |
| validate_expression rejects a field | Field name must match the catalog exactly. Call get_expression_help(topic="fields") or browse /function-docs/ for the full list. Field names are case-sensitive and use single quotes. |
| Tool returns empty list | Filters too strict. Try list_strategies() with no arguments first to confirm connectivity. |
| "Cannot reach server" | Corporate firewall blocks ftinvstr.in. Try a different network or whitelist the host. |
08 Security & disclaimers
- Treat keys like passwords. Anyone with the key can submit backtests as you and read your account.
- Use one key per AI client / device so you can revoke selectively. The "Last used" timestamp helps you spot stale or compromised keys.
- If a key leaks, delete it immediately from /profile/api-keys/.
- Expressions you submit and the resulting CONFIG / strategy_name labels are tied to your
user_idin Redis. Other users cannot see, status, result, or stop your jobs. - ftInvstr is a quantitative research tool — not investment advice. We are not SEBI-registered investment advisers.
- All results are historical backtests on Indian equity data. Past performance does not predict future returns. The bias-safe fundamentals layer (lagged by reporting filings) is always enforced — you can't accidentally peek into the future.