Skip to main content

AI agents (MCP & research)

TradeFlow has an opt-in automation layer that lets an AI help tune scanners and strategies and do market analysis — without ever putting a model in the live order path. Two entry points share the same deterministic core:

  • mcp — serve TradeFlow's capabilities to any MCP client (Claude Code, Claude Desktop) as tools. A human (or another agent) drives.
  • research — a bounded, self-pacing research loop that proposes hypotheses, validates them out-of-sample, and hands you a shortlist.

Both work on the research clock (offline, exploratory). The live order path (python main.py live) stays deterministic and LLM-free. Neither can place an order — that capability is simply not wired in.

MCP server

uv sync --extra mcp
uv run python main.py mcp # serves over stdio

Register it with an MCP client:

{ "mcpServers": { "tradeflow": {
"command": "uv",
"args": ["run", "--extra", "mcp", "python", "main.py", "mcp"],
"cwd": "/path/to/tradeflow" } } }

The agent gets tools for discovery (list_strategies, list_scanners, get_param_ranges), analysis (run_scan, run_backtest, run_optimization, run_walk_forward, summarize_bars, get_metrics_glossary), and config persistence (save_config, load_config, list_configs). Every call is logged to logs/mcp_audit.jsonl. There is no order, live-trading, or PAPER_TRADE-toggling tool — that absence is the safety model.

Research agent

uv sync --extra ai
uv run python main.py research \
--strategy volume_spike --symbols NVDA,AAPL,MSFT \
--start 2024-01-01 --end 2025-12-31 \
--goal "improve OOS Sharpe without raising max drawdown" \
--holdout-days 60 --max-trials 10

The loop proposes a hypothesis → validates it with walk-forward (never on the holdout) → keeps it only if it's promotable and beats the incumbent out-of-sample → repeats until its trial/token budget or a "no improvement" stop → scores the survivors once on the sacred holdout → writes a shortlist of provenance-stamped configs to configs/ for you to review. Nothing is promoted to live automatically.

Choosing an LLM provider

The research agent is provider-agnostic — pick with --provider:

ProviderExtraDefault modelCredential
anthropic (default)uv sync --extra aiclaude-opus-4-8ANTHROPIC_API_KEY
openaiuv sync --extra openaigpt-4oOPENAI_API_KEY
ollama (local)nonellama3.1none (local server)
# Local model, no API key, no cloud calls:
uv run python main.py research --provider ollama --model llama3.1 ...

# OpenAI:
uv run python main.py research --provider openai --model gpt-4o ...

Setting credentials

You can provide a key either in config.py or as the standard environment variable. The agent checks config.py first, then the environment — so the SDK defaults keep working and you don't have to duplicate keys.

config.py (alongside your Alpaca keys — see config_example.py):

ANTHROPIC_API_KEY = "sk-ant-..." # for --provider anthropic
OPENAI_API_KEY = "sk-..." # for --provider openai
OLLAMA_BASE_URL = "http://localhost:11434" # optional, for --provider ollama

…or the environment:

export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-...
export OLLAMA_BASE_URL=http://localhost:11434 # optional

Ollama needs no key — just run a model locally (ollama run llama3.1) and the agent talks to its HTTP API at OLLAMA_BASE_URL (default http://localhost:11434).

See the engineering wiki's MCP server and Research agent pages for the architecture and guardrails.