Finanal
БесплатноНе проверенA minimal, token-efficient MCP server that combines stock prices and fundamentals with the macro and micro narrative around them — so an AI agent can reason abo
Описание
A minimal, token-efficient MCP server that combines stock prices and fundamentals with the macro and micro narrative around them — so an AI agent can reason about why a stock moved, what people are thinking about it, and what probable scenarios lie ahead.
README
A minimal, token-efficient MCP server that combines stock prices and fundamentals with the macro and micro narrative around them — so an AI agent can reason about why a stock moved, what people are thinking about it, and what probable scenarios lie ahead.
Why this project exists
Knowing a stock's PE ratio or current price is not enough. The interesting questions are: why did this stock dip today? What does the market narrative say about it? What are the macro tailwinds or headwinds? What could happen next?
Answering those questions requires combining three things simultaneously:
- Fundamentals and price data — earnings, ratios, revenue growth, institutional flows
- Real-time news and macro context — what analysts, media, and macro events are saying
- The narrative — sentiment, concall tone, sector rotation, management guidance
The tools chosen — FMP, Tapetide, and Tavily — are the best available for each of those jobs. FMP is the gold standard for US stock fundamentals. Tapetide is purpose-built for Indian NSE/BSE data with native MCP support. Tavily is a research-grade search engine that retrieves and synthesises real-time financial news.
Why not use the existing MCP servers for these tools directly?
All three providers publish their own MCP servers, but each exposes 50–100+ individual tools. Every tool description gets embedded into the system prompt of every LLM call. With three servers active that's potentially 150–300 tool descriptions injected into every single prompt — input tokens explode, costs spike, and the LLM gets confused by the noise.
This project is the solution: one MCP server, 6 tools maximum. The LLM talks to a single router that knows which underlying API to call, how to call it, and what parameters to use. The input token footprint stays flat no matter how many endpoints exist in the index.
finanal-mcp in one sentence: ask any financial question in plain English — the server finds the right API, calls it, and caches the answer for instant reuse.
Why it is built this way
| Decision | Rationale |
|---|---|
| 6 tools maximum | Each tool description is injected into every LLM prompt. Keeping the count to 6 keeps the input token footprint minimal and constant (~159 tokens total), regardless of how many underlying endpoints are indexed. |
Slim search_apis responses |
search_apis returns only id, source, path, summary, score (~310 tokens for 10 results). Full schema is deferred to get_api_details, only called when the right endpoint is identified. Before this, full rows cost ~1,232 tokens per search call. |
Response field trimming in call_api |
Known-verbose fields (description, cik, cusip, isin, address, phone, image) are stripped from FMP responses. Cuts a typical /profile response from ~360 to ~149 tokens — the LLM never needed the 3-paragraph company bio. |
| SQLite + FTS5 BM25 instead of vector embeddings | The endpoint index is ~300 rows. BM25 + finance synonyms hits ~90% accuracy with zero extra dependencies and zero latency. Vector search adds complexity and a model inference call for no measurable gain at this scale. |
Finance synonym expansion baked into db.py |
"PE ratio", "price to earnings", "valuation multiple" are the same query. Expanding tokens before FTS search avoids the most common failure modes without needing an LLM call. |
| Tapetide as a proxied MCP server instead of a direct REST client | Tapetide exposes a native MCP server at https://mcp.tapetide.com/mcp. Proxying it over JSON-RPC means we never need to maintain an OpenAPI spec for 49+ Indian market tools — they stay current automatically. |
| Tavily for news instead of FMP news endpoints | FMP's news APIs require a paid plan (return HTTP 402 on free tier). Tavily's search engine covers US/global news, macro events, and earnings headlines on the free tier with far richer synthesis. |
| Recipe cache as the first tool call | BM25 is fast but not perfect. Recipes are exact-match quality. Any question answered once correctly is answered instantly forever after, with zero redundant API discovery. A recipe hit skips both search_apis and get_api_details — the two most expensive steps. |
| uv for all Python | Reproducible builds, fast installs, no system Python pollution. All commands use uv run. |
Source routing rules
These rules are enforced both in the search_apis tool description and in seeded recipes,
so any LLM using this server learns them from the first call.
| Source | Use for | Never use for |
|---|---|---|
| tapetide | Indian NSE/BSE: quotes, news, fundamentals, shareholding, FII/DII, screener, concalls | US or global stocks |
| fmp | US and global stocks: price, financials, earnings, analyst estimates, SEC filings | News (paywalled, returns 402) |
| tavily | All news and macro: US stock news, Fed/RBI decisions, earnings headlines, any web search | N/A — use as fallback for anything news-shaped |
Why not just use prompt caching?
A fair question: FMP, Tapetide, and Tavily each publish their own MCP servers. If you registered all three directly, the LLM would have the full tool list in its context. And since modern LLMs (Claude, GPT-4o) cache the system prompt, subsequent calls would hit the cache at ~90% discount — so it would barely cost anything after the first call, right?
Prompt caching fixes the wallet problem. This architecture fixes the brain problem. Even with perfect cache hits, monolithic tool registrations still fail in three ways:
1. Cache eviction tax (TTL ~5–10 minutes)
Prompt caches are ephemeral. Most providers evict after 5–10 minutes of inactivity. If a user pauses to read, grabs a coffee, or writes a long reply — the cache evicts. The very next turn re-indexes all 150–300 tool schemas at 1.25× the base rate (cache-write premium), and the full cost resets. With 6 tools and ~159 tokens of descriptions, a cache eviction costs fractions of a cent. The TTL problem simply disappears.
2. Model attention tax ("lost in the middle")
Even if holding 200,000 tokens of tool schemas in context is cheap, it is not free for the
model's reasoning. When an LLM has to parse 500 tool schemas simultaneously its retrieval
accuracy degrades measurably — it hallucinates optional parameters, confuses endpoints with
similar names, and dilutes attention on the actual task. By routing through search_apis
first, the model only sees the 3–4 tools it actually needs for that specific turn.
Attention stays sharp.
3. Context window starvation
Every model has a hard context limit. If 200,000 tokens are permanently occupied by monolithic tool schemas, that is 200,000 fewer tokens available for conversation history, API response payloads, and deep reasoning. For a tool-heavy financial workflow where API responses can be large, this matters.
The compounding win: recipes
The deeper lever is the recipe cache. A recipe hit means the model calls exactly one
tool (search_recipes) instead of the usual three (search_recipes → search_apis →
get_api_details → call_api). Every question answered correctly makes the next identical
question instant and near-zero cost. The system gets cheaper and more accurate over time.
Measured token budget
| Component | Tokens |
|---|---|
| All 6 tool descriptions combined | ~159 |
search_apis response, 10 results (slim) |
~310 |
search_apis response, 10 results (old, full rows) |
~1,232 |
FMP /profile response, trimmed |
~149 |
FMP /profile response, untrimmed |
~360 |
| A typical recipe hit (skips search entirely) | ~80 |
Architecture
Copilot / LLM agent
│
▼
finanal-mcp (stdio)
┌─────────────────────────────────────────────┐
│ search_recipes ← check cache first │
│ search_apis ← BM25 + synonym index │
│ get_api_details ← full schema for endpoint │
│ search_docs ← BM25 doc search │
│ call_api ← live API call │
│ save_recipe ← cache successful answer │
└──────────────┬──────────────────────────────┘
│ routes by source field
┌─────────┼──────────┐
▼ ▼ ▼
FMP REST Tavily REST Tapetide MCP
(US/global) (news) (India NSE/BSE)
Prerequisites
- Python ≥ 3.14
- uv —
brew install uvorpip install uv - API keys for FMP, Tavily, and Tapetide (free tiers available for all three)
Setup
git clone <repo>
cd finanal
uv sync
cp .env.example .env
# Edit .env and fill in your three API keys
Get your keys:
- FMP: https://site.financialmodelingprep.com/developer/docs — free tier, 250 req/day
- Tavily: https://app.tavily.com — free tier, 1,000 credits/month
- Tapetide: https://tapetide.com/mcp — free token from settings
Seed the endpoint index
Run once after cloning (or after pulling updates):
uv run scripts/seed_fmp_scrape.py # 236 FMP endpoints from official docs
uv run scripts/seed_tavily.py # 7 Tavily endpoints
uv run scripts/seed_tapetide.py # 49 Tapetide tool schemas
uv run scripts/enrich_docs.py # 348 synthetic BM25 docs
Verify with smoke tests
uv run scripts/test_search.py
# Expected: 15/15 ✓ all rank-1
Run the MCP server
uv run python main.py
The server communicates over stdio and is consumed by VS Code / Copilot via the MCP protocol. You do not interact with it directly.
Register in VS Code (user-level — works in all workspaces)
Add to ~/Library/Application Support/Code/User/mcp.json (macOS) or the equivalent
user-level mcp.json on your OS:
{
"servers": {
"finanal-mcp": {
"type": "stdio",
"command": "uv",
"args": ["run", "python", "main.py"],
"cwd": "/absolute/path/to/finanal"
},
"tapetide-mcp": {
"type": "http",
"url": "https://mcp.tapetide.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_TAPETIDE_TOKEN",
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream"
}
}
}
}
Note:
tapetide-mcpis registered separately as an HTTP server so Copilot can call its tools directly (faster path).finanal-mcpproxies through to it as well, but direct registration gives Copilot access to all 49 Tapetide tools without going through the router.
How to use it from Copilot Chat
finanal-mcp is a tool router, not a chat assistant. An LLM agent (Copilot, Claude,
etc.) calls its tools to discover and invoke the right financial API. The mandatory workflow:
Step-by-step tool call order
1. search_recipes(query)
└─ If score < -1.0 → use that recipe directly, skip to call_api. Done.
2. search_apis(query, source="fmp"|"tapetide"|"tavily")
└─ Returns ranked endpoint list with id, summary, source, parameters.
3. get_api_details(endpoint_id)
└─ Returns full parameter schema so call_api gets the right args.
4. call_api(endpoint_id, params={...})
└─ Executes the live API call and returns the data.
5. save_recipe(question, summary, endpoint_ids=[...])
└─ Always save after a good answer — next identical query is instant.
Example queries and what happens
| Query | Route | Tool sequence |
|---|---|---|
| "Polycab current price" | tapetide | search_recipes → call_api(tapetide get_stock_quote) |
| "VRT Vertiv stock price" | fmp | search_recipes → call_api(fmp /profile) |
| "Polycab latest news" | tapetide | search_recipes → call_api(tapetide get_stock_news) |
| "Vertiv news 2026" | tavily | search_recipes → call_api(tavily /search, topic=finance) |
| "RELIANCE PE ratio" | fmp | search_recipes → search_apis → call_api(fmp /ratios) |
| "India FII DII flows today" | tapetide | search_recipes → call_api(tapetide get_fii_dii_flows) |
| "US Fed rate decision news" | tavily | search_recipes → call_api(tavily /search, topic=news) |
Teaching the server new routing rules
Seed recipes directly:
import db
conn = db.get_conn()
db.upsert_recipe(
conn,
question="Get quarterly earnings for an Indian company",
summary="Use tapetide get_financials (source=tapetide), section='profit_loss'.",
endpoint_ids=[22],
)
conn.commit()
Or use the save_recipe tool from within a Copilot chat session after a successful answer.
DB state (after full seed)
| Source | Endpoints | Notes |
|---|---|---|
| fmp | 236 | Scraped from official FMP docs + community OpenAPI YAML |
| tapetide | 49 | Tapetide native MCP tool schemas |
| tavily | 7 | Hand-crafted from Tavily OpenAPI spec |
| Total | 292 | |
| Docs (BM25) | 348 | Synthetic per-endpoint + per-tag-group docs |
| Recipes | 6+ | Seeded routing rules; grows with use |
Key files
main.py ← FastMCP server — 6 tools, source-aware call_api routing
db.py ← SQLite schema, FTS5 tables, BM25 search, synonym expansion
scripts/seed_fmp_scrape.py ← Primary FMP seed (236 endpoints from scraped docs)
scripts/seed_fmp.py ← Secondary FMP seed (community OpenAPI YAML, 181 endpoints)
scripts/seed_tavily.py ← Tavily endpoint seed
scripts/seed_tapetide.py ← Tapetide tool schema seed
scripts/enrich_docs.py ← Synthetic BM25 doc generation (348 docs)
scripts/test_search.py ← Smoke tests (15/15 expected)
specs/tavily.yaml ← Hand-crafted Tavily OpenAPI spec
data/finanal.db ← SQLite database (gitignored)
.env.example ← API key template
.github/copilot-instructions.md ← Copilot tool workflow instructions
Установка Finanal
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/Sekharz/finanalFAQ
Finanal MCP бесплатный?
Да, Finanal MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Finanal?
Нет, Finanal работает без API-ключей и переменных окружения.
Finanal — hosted или self-hosted?
Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.
Как установить Finanal в Claude Desktop, Claude Code или Cursor?
Открой Finanal на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
автор: modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
автор: xuzexin-hzCompare Finanal with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории ai
