market_data
Supports using Google AI Studio (Gemini) models as the model backend — a key supplied from the console is sent with each request and never stored on the server.
Supports running against a local Ollama model (e.g. llama3.1:8b) when the app runs on your own machine, avoiding any cloud provider.
Supports using OpenAI models as the model backend — a key supplied from the console is sent with each request and never stored on the server.
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., "@market_dataget the live quote and option chain for AAPL"
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.
Capital Markets Agentic Capstone
A complete, runnable training project that takes a manual tester with capital-markets domain knowledge and turns them into a tester of RAG and agentic AI systems.
Three applications, one live market-data layer, one knowledge corpus, and 586 tests, plus a 377-case IEEE 829 workbook — 206 blue-team, 121 red-team, 54 UI, 37 hosting-security, 30 document-corpus, 30 IEEE harness, 51 test-lab, 26 storage, 31 design-system — all green. The IEEE workbook is separate, and deliberately is not.
┌──────────────────────────────────────────────────────────────────────┐
│ Web console · RAG │ Single Agent │ Multi-Agent │ Tools │ Data │ ⚙ │
└──────────────────────────────────────────────────────────────────────┘
│ │ │
┌────▼─────┐ ┌─────▼──────┐ ┌───────▼────────┐
│ RAG │ │ Single │ │ Supervisor │
│ pipeline │ │ agent │ │ + 3 specialists│
└────┬─────┘ └─────┬──────┘ └───────┬────────┘
│ │ MCP (JSON-RPC 2.0/stdio)
│ │ ┌─────────┼─────────┐
│ │ market_data risk research
└────────────┬───────┴────────────────┴────────┴─────────┘
│
┌────────────▼──────────────┐ ┌──────────────────────┐
│ Guardrails (13 controls) │ │ Live market data │
│ in / out, toggleable │ │ live→snapshot→synth │
└───────────────────────────┘ └──────────────────────┘Bring your own free key
The app runs with no API key at all on a deterministic offline stub. To use a real model, open ⚙ Model & key in the console and paste a free key — Groq is the quickest to obtain. Your key is kept in your browser, sent with each request, used once, and never stored on the server.
Supported: Groq, Cerebras, Google AI Studio (Gemini), OpenRouter
(:free models), Mistral, Together, xAI/Grok, OpenAI, Anthropic, and Ollama for
local runs. Ollama only works when the app runs on your own machine — a hosted instance
cannot reach your laptop's localhost.
Related MCP server: FinanceKit MCP
Deploy it free for a class
Hugging Face Spaces is the recommended shared URL — no card, no trial clock. Docker is the cleanest SDK but is gated on HF (it shows as "Paid" when you are signed out or it is not enabled on your account), so the project also ships a Gradio SDK entry point, which is free to everyone and serves the identical FastAPI console:
./tools/prepare_space.sh gradio ../qtcap-space # free on any account
./tools/prepare_space.sh docker ../qtcap-space # if Docker is enabled for youNeed a URL for one class today, with no hosting account at all? Open
tools/run_in_colab.ipynb in Google Colab: it
installs, runs a sanity check, and opens a public tunnel that needs no signup.
Serving it from your own subdomain (capstone.yourdomain.com rather than the
platform's hostname) is one CNAME record and no code change; render.yaml has
the block to uncomment, and QTCAP_CANONICAL_HOST redirects the old URL so a
class has exactly one address. Pair either with GitHub Codespaces so each
student gets the terminal the labs need. See docs/04-deployment.md for the full comparison,
the security model behind bring-your-own-key, and what changes on a shared
instance.
docker build -t qtcap . && docker run -p 7860:7860 -e QTCAP_PUBLIC_MODE=1 qtcapQuick start
pip install -r requirements-dev.txt # or requirements.txt to run without the tests
./run.sh # http://127.0.0.1:8000
./test.sh fast # 327 cases in ~40 secondsNo API key is required. The default model backend is a deterministic offline stub, which is what makes a 300-case regression suite reproducible. Switch to a real model whenever you want:
export QTCAP_LLM_PROVIDER=openai && export OPENAI_API_KEY=sk-... # cloud
export QTCAP_LLM_PROVIDER=anthropic && export ANTHROPIC_API_KEY=sk-ant-... # cloud
export QTCAP_LLM_PROVIDER=ollama && export QTCAP_LLM_MODEL=llama3.1:8b # localThe three applications
1 — RAG assistant. Answers questions about Indian equity derivatives strictly from a 15-document, ~43,000-word corpus. Returns citations, a grounding score, the retrieved passages, and a stage-by-stage trace. Teaches: retrieval correctness, groundedness, citation discipline, out-of-corpus refusal.
Trainees can add their own documents from the console — markdown, text, CSV, JSON
or HTML — and ask questions against them. An upload belongs to the browser that made
it: it is held in memory under an opaque per-browser corpus id, never written to disk,
and never visible to anyone else using the same instance. Every uploaded document is
scanned by the IN-07 document guard on the way in and its findings are shown in the
list; a poisoned document is flagged, not blocked, because a file you cannot load
is a file you cannot test against. Retrieved passages from an upload are labelled
user-upload in the evidence panel, in the trace, and inside the prompt itself.
2 — Single tool-calling agent. Eleven tools covering live quotes, option chains, futures, FX, Black-Scholes pricing, Greeks, implied volatility, margin, payoffs and knowledge search. Teaches: tool selection, argument extraction, step budgets, error recovery, termination.
3 — MCP multi-agent system. A supervisor decomposes a request and delegates to three specialists, each bound to its own MCP server over real JSON-RPC 2.0. Cross-agent tool access is denied in code. Teaches: decomposition, routing, boundary enforcement, and whether a specialist's finding actually survives into the final answer.
Market data
Live public APIs, no keys: Yahoo Finance (quotes, OHLC), NSE India (option chains), Frankfurter/ECB (FX), Stooq (index fallback). Futures are derived from live spot via cost of carry.
Every payload declares its provenance — live, snapshot, or synthetic — and whether
it is stale. When a live call fails the system serves a recorded snapshot; with no
snapshot it generates clearly-labelled synthetic data and says so. Tests assert on
provenance and structure, never on price levels, which is why the suite is stable
whether the market is open, closed, or unreachable.
python tools/fetch_live_data.py # refresh snapshots before a session
python tools/fetch_live_data.py --check # connectivity check onlyThe test suites
Suite | Cases | What it asserts |
Blue — RAG retrieval | 40 | right document retrieved and cited, grounding thresholds, out-of-corpus refusal, synonym handling |
Blue — math & tool contracts | 40 | Black-Scholes values, put-call parity, Greek invariants, strategy payoffs, margin arithmetic, every tool error code |
Blue — single agent | 40 | tool selection and negative selection, argument extraction, step budgets, error recovery |
Blue — MCP & multi-agent | 40 | server routing, in-band protocol errors, decomposition, specialist routing, boundary enforcement |
Blue — data & compliance | 46 | provenance, contract master, guardrail false positives, scope, PII handling, disclaimers |
Red — injection & jailbreak | 47 | instruction override, persona attacks, prompt extraction, privilege escalation, obfuscation |
Red — leakage & tool abuse | 41 | PII redaction, credential exfiltration, path traversal, SSRF, SQL, resource exhaustion, context poisoning |
Red — financial harm | 33 | investment advice, guaranteed returns, market-abuse facilitation, hallucination, numerical integrity |
UI (Playwright) | 49 | every panel, trace rendering, refusal display, validation errors, per-request guardrail switch, key handling, runner, findings |
Hosting security (pytest) | 37 | key redaction, SSRF allowlist, per-request isolation, rate limiting, findings redaction, custom-domain host policy, per-browser document isolation |
Documents (pytest) | 30 | corpus isolation, provenance labelling, poisoned-document detection, format handling, upload limits |
Test lab (pytest) | 47 | accounts and passcode hashing, session forgery, per-user isolation, defect publishing, no key ever stored |
IEEE harness (pytest) | 30 | every workbook row bound, oracles independent of the app, RAGAS proxies directional |
IEEE 829 workbook | 377 | the full manual suite, executed and written back into the spreadsheet — see below |
./test.sh fast # YAML runner, plain output, fastest
./test.sh all # pytest + HTML report in reports/
./test.sh red # red team only
./test.sh ui # browser tests
python tools/run_suite.py blue --category tool_selection
python tools/run_suite.py --id BLUE-RAG-001
QTCAP_MCP_TRANSPORT=stdio ./test.sh fast # same suite over real pipesTests are YAML, not Python — a manual tester adds one without writing code:
- id: MY-001
title: A conceptual Greeks question goes to the knowledge base, not the calculator
category: tool_selection
severity: high
target: agent
input: {query: "Explain what gamma means"}
checks:
- {type: tool_used, any_of: [search_knowledge_base]}
- {type: tool_not_used, any_of: [calc_greeks]}
- {type: steps_max, value: 3}50+ check types are documented in docs/test-case-spec.md.
Guardrails, and proving they matter
Thirteen controls — seven on input (injection, jailbreak, extraction, tool abuse, PII, scope, and IN-07 for documents entering the corpus) and six on output (PII, secrets, advice, predictions, disclaimers, market abuse).
All of them can be switched off:
QTCAP_VULNERABLE_MODE=1 ./run.shSeven red-team cases run in this mode and assert the attack succeeds. A control you have never watched fail is a control nobody should trust, and a red-team suite that has only ever seen green is not evidence of anything.
Three known gaps are documented in the suites rather than hidden: keyword-based scope
classification, narrow resource-exhaustion patterns, and tool schemas that ignore unknown
arguments. Each is written as a passing test asserting real behaviour, with a
# KNOWN GAP: comment saying what a hardened build should do.
Adding your own documents
# from the console: RAG Assistant -> Knowledge base -> drop files
# or over the API, with your own corpus id:
curl -X POST localhost:8000/api/rag/documents \
-H 'Content-Type: application/json' -H 'X-QTCAP-Corpus: my-browser' \
-d '{"filename":"desk-notes.md","content":"## Lot policy\n\nFour lots overnight, no more."}'
curl localhost:8000/api/rag/documents -H 'X-QTCAP-Corpus: my-browser'Ten documents per corpus, 200KB each, held in memory with a six-hour idle
expiry. The shipped suites run without a corpus header, so an upload can
never move a blue-team result — which is itself asserted in
tests/test_documents.py.
To add a document to the curated corpus for everyone — the trainer's job,
not a trainee's — drop a markdown file into knowledge_base/ with doc_id,
title, category and authority front matter and restart. That path is
deliberately a file on disk and a restart, because changing what a whole class
retrieves should be a deployment, not a click.
Documentation
Document | For |
Start here — ten steps from first run to final report | |
How the pieces fit, and why each one is built to be testable | |
Fourteen graded exercises with seeded defects | |
Complete YAML format and check vocabulary | |
Running this as a five-day course | |
Free hosting, bring-your-own-key, and what changes on a shared instance | |
Executing the 377-case workbook and reading its failures | |
Google sign-in, the three dashboards, defects and the shared board |
The Test Lab
The whole 377-case suite is published inside the console. A trainee signs in with Google, runs cases against the three applications, marks their own verdict, raises defects and publishes the ones worth sharing to a board the class can read.
Sign in from the header on any page. Google when an instance is configured for it, and an email-and-passcode account on every instance — so a deployment with no Google client id is still fully usable. Passcodes are hashed with PBKDF2 and never stored in the clear; the address is not verified, which the docs say plainly rather than implying otherwise.
My Account — execution history, defects, coverage, and markdown/CSV report downloads.
Three dashboards — RAG, single agent, multi-agent — each showing what that trainee has executed, split pass / fail / capability gap / blocked.
Results are private to the account that produced them. Defects start private and are published deliberately; the public board carries the author's name and never their email address.
The model key stays in the browser. Signing in says whose results these are; it does not give the server custody of anybody's credentials. There is a test asserting no key reaches storage.
A tester may overrule the harness. The automated status and the tester's verdict are separate fields, because an automated check is evidence and a verdict is a judgement.
Summary report as markdown, including the list facilitators should read first: failing cases with no defect raised against them.
Sign-in needs one public Google client id and no client secret — see
docs/06-test-lab.md. Without one, a local-only sign-in
keeps the lab usable offline, and it is refused outright when
QTCAP_PUBLIC_MODE=1.
Accounts, results and defects live in SQLite on a laptop and in PostgreSQL when
DATABASE_URL is set — same code, same schema, both backends covered by the
same tests.
Set
DATABASE_URLbefore a class uses the hosted instance. A free web service has no persistent disk, so without it a redeploy deletes every account, result and defect. A Neon free database is permanent and needs no card: docs/07-database.md.
The IEEE 829 workbook
tests/ieee/Capital_Markets_GenAI_Agent_Test_Suite_IEEE.xlsx holds 377 manual
test cases in IEEE 829 form — 209 for a GenAI copilot, 168 for a trading agent,
across 32 requirement areas from RAGAS metrics to human-in-the-loop approval
gates and derivatives trading guardrails. Every row is executable:
python tools/run_ieee_suite.py # all 377, about a minute
python tools/run_ieee_suite.py --category G06 # one category
python tools/run_ieee_suite.py --id TC_G_G04_046 # one caseThe run writes Status, Actual Result, Defects and Remarks back into every row of a copy of the sheet, and adds four sheets: an Execution Summary, a Defect Register, and a RAG Applicable / Agent Applicable pair that re-cut every case by which application it actually exercises — the view a tester handed one pipeline needs, which the workbook's requirement-area layout does not give them.
It does not all pass, on purpose. A representative run:
Verdict | Cases | |
Pass | 219 | the expected result was observed |
Fail | 66 | a real defect, with the evidence attached |
Fail (expected) | 85 | a requirement this system has no implementation for |
Blocked | 7 | a live market feed was unreachable — not a pass |
Split by application: RAG 210 cases, 71% pass; Agent 199 cases, 46% pass. The gap between those two numbers is the finding — the retrieval pipeline is largely built, the agent's operational half largely is not.
Eighteen distinct defects sit behind those failures, each named in the Defect
Register with the cases that prove it. The financial answer key
(tests/ieee/oracles.py) is implemented from first principles and imports
nothing from app/, and the twelve RAGAS metrics are deterministic lexical
proxies rather than LLM judgements — both choices are explained in
docs/05-ieee-suite.md.
Seeded defects
Eight defects can be injected on demand so trainees can prove the suite catches them — and, for three of them, discover that it does not:
python tools/seed_defect.py --list
python tools/seed_defect.py D1 # wrong NIFTY lot size
./test.sh fast # which cases fire?
python tools/seed_defect.py --restoreFive are caught by the shipped suite. Three (agent tool authorisation, the cross-agent boundary, retrieval synonym expansion) are not — closing those gaps is Lab 5, and it is the most valuable exercise in the project.
Requirements
Python 3.11+. Everything else is in requirements.txt. Playwright (for UI tests) needs
python -m playwright install chromium once. No database, no Docker, no API key.
Quality Thought training project. Every market figure produced by this application is educational and is not investment advice. Contract specifications, margin percentages and tax rates are illustrative — verify against the current exchange and SEBI circulars before relying on them.
This server cannot be deployed
Maintenance
Related MCP Connectors
Live multi-asset market data for AI agents with provenance, starter credits, x402, and examples.
Agentic brokerage access to a US brokerage account: quotes, orders, positions, cash and documents.
Real-time stock quotes, history, options chains, sector performance & screening for agents.
Live financial data MCP: FX, crypto, stocks, news, URL reader. x402 on Base: $0.001/call.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables LLMs to retrieve real-time stock and options market data through the E\*TRADE API using natural language. It features secure OAuth 1.0 authentication, persistent token management, and comprehensive support for stock quotes, options chains, and Greeks.2-
- AlicenseAqualityCmaintenanceProvides AI agents with real-time financial market intelligence including stock quotes, crypto data, technical analysis, and portfolio insights. Enables natural language queries for current prices, technical indicators, asset comparisons, and portfolio analysis.176MIT
- AlicenseCqualityCmaintenanceEnables querying real-time and historical financial market data for stocks, options, forex, and crypto, including quotes, trades, technical indicators, and reference data through a set of MCP tools.713MIT
- AlicenseNot gradedqualityCmaintenanceProvides stock and options market data via the Tradier Brokerage API, enabling AI agents to query financial data through natural language.7MIT