Skip to main content
Glama
YugMakhecha17

Finance MCP Aggregator

Finance MCP Aggregator

A Scoped Aggregator pattern MCP server: 43 real finance tools, but the model only ever sees the 4–7 that matter for the current turn.

Built to solve a real, measured problem: MCP servers that statically register every tool up front degrade as the tool count grows past ~15. This project implements the fix — dynamic, intent-routed tool exposure — for a domain (personal finance / investing analytics) where 40+ tools is the realistic end state, not a contrived example.


1. The problem, with numbers

Give an LLM 40+ tool schemas in its system prompt on every single turn and four failure modes compound:

Failure mode

Mechanism

Effect

Attention dilution

Tool definitions in the middle of a long prompt get less attention ("lost in the middle")

Wrong tool picked, or the right tool picked with the wrong arguments

Name/description collisions

get_stock_price vs get_after_hours_price, calculate_var vs calculate_volatility — semantic overlap is inevitable at 40+ tools

Coin-flip tool selection

Parameter hallucination

Model has 40+ schemas competing for context; it blends fields from one schema into a call to another

Invalid API calls, retries, silent wrong answers

Context/cost bloat

Every tool schema is JSON sent on every turn, whether used or not

Fewer tokens left for actual conversation, higher per-call cost

This project measures — not just claims — the first and last of those for its own tool catalog. Run benchmarks/benchmark_routing.py yourself; here's what it produced on this repo's 43-tool registry:

TOKEN COST: static merge (43 tools) vs scoped aggregator
Architecture                Tokens/turn    Tokens/10 turns
Static merge (all 43)       1754           17540
Scoped aggregator           338            3380
Reduction in tool-schema tokens per turn: 80.7%

ROUTING ACCURACY: expected tool in top-6 results
Top-6 accuracy: 25/26 (96.2%) on a 26-query evaluation set spanning all 6 domains

(Token counts are a ~4-chars/token estimate, order-of-magnitude accurate — swap in tiktoken or Anthropic's tokenizer for exact figures. The methodology is transparent in the script, not a black box.)

What this means in practice: at $3/M input tokens and 500 tool-augmented turns/day, the static-merge architecture spends roughly $0.79/day on tool schemas alone that never get called; the scoped aggregator spends about $0.15/day for the same volume — and, more importantly, the accuracy numbers above are what actually protects you from a misrouted execute_trade-style call in a finance context, where a wrong tool call isn't just an annoyance.


Related MCP server: mcp-compressor

2. Why finance, specifically

Personal finance / investing assistants are one of the few domains where 40+ distinct tools is the honest requirement, not an artificially inflated demo:

  • Market data (quotes, history, news, earnings dates, dividends, splits)

  • Portfolio analytics (value, returns, Sharpe ratio, diversification, rebalancing, CAGR, drawdown, benchmarking)

  • Risk analytics (VaR, beta, volatility, stress testing, correlation, Monte Carlo simulation)

  • Technical analysis (SMA, EMA, RSI, MACD, Bollinger Bands, support/resistance, ATR, Fibonacci)

  • Fundamental analysis (P/E, EPS, balance sheet, income statement, cash flow, DCF valuation)

  • Currency & crypto (FX conversion, live rates, crypto pricing, gas fees)

A real product covering all six domains genuinely needs on the order of 40+ tools. Trying to force that into a single flat MCP tool list is exactly the scenario the Scoped Aggregator pattern is meant for — this repo is that pattern applied to a domain where it's load-bearing, not decorative.


3. Architecture

                          ┌─────────────────────────┐
                          │   LLM / MCP Client       │
                          │ (Claude Desktop, etc.)   │
                          └────────────┬─────────────┘
                                       │  sees only 4 meta-tools,
                                       │  not all 43
                   ┌───────────────────▼────────────────────┐
                   │        finance_mcp/server.py            │
                   │  list_finance_categories()               │
                   │  search_finance_tools(query, top_k)  ────┼──┐
                   │  get_tool_schema(tool_name)              │  │ 1. TF-IDF cosine
                   │  execute_finance_tool(tool_name, params) │  │    similarity ranks
                   └───────────────────┬────────────────────┘  │    query against all
                                       │                        │    43 tool docs
                          ┌────────────▼────────────┐  ◄────────┘
                          │   router.py (IntentRouter)│
                          │   ranks registry.py's      │
                          │   43 ToolSpecs by relevance │
                          └────────────┬────────────┘
                                       │  2. top-k names resolved
                          ┌────────────▼────────────┐
                          │   executor.py             │
                          │   lazily imports + calls   │
                          │   the winning tool          │
                          └────────────┬────────────┘
                                       │
                   ┌───────────────────▼────────────────────┐
                   │  tools/market_data.py                    │
                   │  tools/portfolio_analysis.py             │
                   │  tools/risk_analysis.py                  │  ← 43 tools total,
                   │  tools/technical_analysis.py             │    only imported when
                   │  tools/fundamental_analysis.py           │    actually called
                   │  tools/currency_crypto.py                │
                   └──────────────────────────────────────────┘

The flow an LLM actually follows:

  1. search_finance_tools("what's my portfolio's Sharpe ratio") → returns the 5–6 relevant tools (not all 43), each with its exact parameter schema.

  2. execute_finance_tool("calculate_sharpe_ratio", {...}) → runs it.

No dependence on MCP clients supporting tools/list_changed notifications (many don't, reliably) — the narrowing happens inside a normal tool call, which every MCP client already supports. This is the same "search then act" shape you'll recognize from how large codebases expose tool search to coding agents, applied here to a finance tool catalog.

Why TF-IDF instead of an LLM router or embeddings model

  • No extra LLM call — a router that itself needs GPT-4 to pick a tool defeats the purpose (latency + cost on every turn).

  • No heavyweight downloadscikit-learn installs in seconds on a plain Windows Python 3.12 environment; no torch, no model weights.

  • Deterministic and debuggable — you can inspect exactly which words matched.

  • Swappablerouter.py includes an EmbeddingRouter with the same interface for when a catalog grows past a few hundred tools and paraphrase-level matching starts to matter more than raw token overlap. See Scaling further below.


4. Project structure

finance-mcp-aggregator/
├── README.md
├── requirements.txt
├── pyproject.toml
├── .env.example
├── .gitignore
├── LICENSE
├── src/finance_mcp/
│   ├── server.py                 # MCP server: 4 meta-tools only
│   ├── router.py                 # IntentRouter (TF-IDF) + EmbeddingRouter
│   ├── registry.py               # Metadata for all 43 tools (no imports of impls)
│   ├── executor.py                # Lazy resolve + call by dotted path
│   └── tools/
│       ├── _data_source.py       # yfinance wrapper w/ offline synthetic fallback
│       ├── market_data.py        # 8 tools
│       ├── portfolio_analysis.py # 8 tools
│       ├── risk_analysis.py      # 7 tools
│       ├── technical_analysis.py # 8 tools
│       ├── fundamental_analysis.py # 6 tools
│       └── currency_crypto.py    # 6 tools
├── benchmarks/
│   └── benchmark_routing.py      # Token-cost + routing-accuracy measurements
├── tests/
│   └── test_router.py
└── examples/
    └── demo_client.py            # Runs the search→execute flow with no LLM/API key

5. Setup (Windows, Python 3.12.4)

git clone https://github.com/<you>/finance-mcp-aggregator.git
cd finance-mcp-aggregator

python -m venv .venv
.venv\Scripts\activate

pip install -r requirements.txt
copy .env.example .env

Run the demo (no MCP client, no API key needed)

python examples\demo_client.py "what's my portfolio's value at risk"

Run the benchmark yourself

python benchmarks\benchmark_routing.py

Run tests

pytest tests\ -v

Run the actual MCP server

Built on the standalone fastmcp package (not the trimmed-down mcp.server.fastmcp bundled inside the official mcp SDK) — it tracks the MCP spec closer to real-time and adds a dev inspector, auth providers, and an HTTP transport out of the box.

# stdio (default) -- what Claude Desktop and most MCP clients expect
python -m finance_mcp.server

# or run it as a standalone HTTP server instead
$env:MCP_TRANSPORT="http"; $env:MCP_PORT="8000"; python -m finance_mcp.server

To use it from Claude Desktop, add to your MCP config (%APPDATA%\Claude\claude_desktop_config.json):

{
  "mcpServers": {
    "finance-aggregator": {
      "command": "C:\\path\\to\\finance-mcp-aggregator\\.venv\\Scripts\\python.exe",
      "args": ["-m", "finance_mcp.server"]
    }
  }
}

You can also inspect it live with FastMCP's built-in dev tool before wiring it into any client:

fastmcp dev src\finance_mcp\server.py

Note on live data: every tool falls back to deterministic synthetic data when yfinance has no network access, so the whole test/benchmark suite runs fully offline. With network access, get_stock_price, get_historical_prices, get_pe_ratio, etc. pull real data via yfinance (no API key required).


6. Scaling further than this repo

This repo's registry (43 tools, TF-IDF router) is sized to be genuinely runnable end-to-end without any paid API or heavy install. If you fork this for a catalog of hundreds of tools across many MCP servers, the pattern extends cleanly:

  • Categorization → Intent routing → Dynamic ingestion, exactly as described in the architecture above, generalizes past one server: put an aggregator server in front of multiple downstream MCP servers (each exposing its native tools), and have the aggregator's search_tools fan out across all of them.

  • Swap IntentRouter for the included EmbeddingRouter (pip install sentence-transformers) once paraphrase matching ("how risky is my portfolio" ≈ "what's my VaR") starts mattering more than keyword overlap — this repo's benchmark script is the harness to validate that swap actually improves top-k accuracy before you ship it.

  • For MCP clients that do support notifications/tools/list_changed, you can go further and only ever expose the narrowed tool list itself (not meta-tools) — trading universal compatibility for a marginally smaller prompt.


7. What this is not

  • Not investment advice, and not wired to a brokerage — every calculation tool is a standalone analytics function you'd still validate before acting on.

  • The offline synthetic price fallback exists so tests/CI/demos don't require network or an API key; it is clearly labeled "source": "synthetic-offline" in every response so it's never confused with real market data.

  • The DCF, Monte Carlo, and VaR implementations are standard textbook formulations for demonstration; a production system would want a reviewed quant library and real-world backtesting before being trusted with real allocation decisions.


Repository health and contribution model

This repository is structured so it can be pushed and maintained as a clean, open-source Python package:

  • Source code lives under src/finance_mcp/ and is buildable through pyproject.toml.

  • Tool metadata lives in a registry rather than scattered implementation details.

  • The public API is exposed through the server entry point and a stable set of search/execute tools.

  • Contribution docs are available in CONTRIBUTING.md, SECURITY.md, and CHANGELOG.md.

  • CI automation, issue templates, and pull request templates are available under .github/.

If you are preparing a public repository push, keep the branch history small and the release artifacts explicit.


License

MIT — see LICENSE.

Available Tools

4 tools
execute_finance_toolA

Execute a specific finance tool by name with the given parameters. Always call search_finance_tools or get_tool_schema first to confirm the correct tool name and parameter shape -- this avoids parameter hallucination from guessing at an unseen schema.

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsYes
tool_nameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description must carry the full burden of behavioral disclosure. It fails to state whether execution is read-only or mutating, what side effects may occur, or how results are returned. The only non-obvious context is the warning about hallucination, which is more usage guidance than behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the core purpose, and includes a highly relevant usage directive. Every sentence adds value, with no redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity as a dynamic dispatcher, the description adequately covers the key context: how to invoke it and the prerequisite discovery steps. The presence of an output schema means return values need not be explained. However, it does not address error handling or invalid inputs, which would make it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, and the description provides minimal added meaning. It implicitly acknowledges tool_name and params ('by name with the given parameters') but does not elaborate on their formats, constraints, or the expected structure of the params object. The description does not compensate for the lack of schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action: 'Execute a specific finance tool by name with the given parameters.' This distinguishes the tool from its siblings (list_finance_categories, search_finance_tools, get_tool_schema) by identifying it as the executor, not a discovery or schema tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit directive: 'Always call search_finance_tools or get_tool_schema first to confirm the correct tool name and parameter shape.' This clearly indicates when and how to use the tool (only after confirmation) and explains the rationale for avoiding parameter hallucination, thereby differentiating it from the discovery tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_tool_schemaA

Get the exact parameter schema for a single named finance tool (use after search_finance_tools has told you the tool name).

ParametersJSON Schema
NameRequiredDescriptionDefault
tool_nameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It suggests a read-only operation via 'Get' and adds the prerequisite that the tool name comes from search_finance_tools. However, it does not explicitly state error behavior or confirm non-mutating status, leaving some opacity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that front-loads the main action and integrates the usage guidance efficiently. Every word contributes to understanding the tool's purpose and workflow.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter tool with an output schema, the description adequately covers purpose, usage, and parameter meaning. It lacks explicit error-handling details, but the simplicity and output schema mitigate the gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description adds meaning by explaining that tool_name is the name of a finance tool and should be the value returned by search_finance_tools. This provides essential context beyond the bare 'string' type.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Get') and the specific resource ('exact parameter schema') for a single named finance tool. It also differentiates from siblings by indicating it follows search_finance_tools, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it: 'use after search_finance_tools has told you the tool name'. This provides clear sequencing and implies it is for schema retrieval rather than execution, which distinguishes it from execute_finance_tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_finance_categoriesA

List the domains of finance tools available (market data, portfolio analysis, risk analysis, technical analysis, fundamental analysis, currency/crypto) along with how many tools live in each.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral disclosure burden. It clearly states that the tool lists domains and provides tool counts, and implies a read-only, non-destructive action. For a simple listing tool, this is sufficient transparency; no hidden side effects or additional requirements are relevant.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that states the verb, resource, and key output aspects. It lists examples efficiently without redundancy and earns its place with high information density.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with an output schema present, the description is complete. It covers what the tool does (lists domains) and what it returns (domain names and counts), and the sibling context makes the tool's role clear. No further detail is required.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, which gives a baseline of 4. The description adds meaningful context beyond the empty schema by naming example categories and explaining the output includes tool counts. However, since there are no parameters to describe, the contribution is minimal but acceptable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and names a clear resource ('domains of finance tools'), enumerates example categories, and notes the counts per domain. This distinguishes it from siblings like search_finance_tools, get_tool_schema, and execute_finance_tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The context in which to use this tool is implied (exploration/discovery of available finance domains), but there is no explicit statement of when to prefer it over alternatives or any exclusion criteria. The sibling tools are not referenced in the description, so no when-not-to-use guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_finance_toolsA

Find the finance tools most relevant to a natural-language request.

Call this FIRST before execute_finance_tool. It searches across all 43 registered finance tools (market data, portfolio analysis, risk, technical analysis, fundamentals, currency/crypto) and returns only the ones relevant to your query, each with its name, description and the parameters it expects -- so you never need the full tool catalog in context at once.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes
top_kNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of disclosure. It discloses that this is a read-only search operation across all 43 tools, returns only relevant tools, and includes name, description, and expected parameters. It does not discuss exact matching semantics or edge cases, but it provides substantial behavioral context for a discovery tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no wasted words. It is front-loaded with the core purpose, then provides usage ordering, and finishes with a rationale for why the tool avoids loading the full catalog. Every sentence contributes unique value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 2-parameter search tool with an output schema, the description covers purpose, tool categories, return content, and usage order. It does not explicitly explain both parameters in prose, but the output schema and simple schema reduce that burden, making it mostly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description only implicitly clarifies the 'query' parameter as a natural-language request. It does not mention 'top_k', its default, or how it affects the result set. The parameters are simple enough to infer, but the description adds minimal value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('find') and resource ('finance tools most relevant to a natural-language request'), clearly distinguishing this discovery tool from the execution sibling. It explicitly contrasts with execute_finance_tool by stating it returns tool metadata rather than executing, making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit sequencing by saying 'Call this FIRST before execute_finance_tool,' which gives clear usage context. It also describes the broad coverage across all 43 finance tools, but it does not explicitly state when to use list_finance_categories or get_tool_schema instead, so it lacks a full alternatives exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.4/5.0
Disambiguation5/5

Each tool has a distinct role: listing categories, searching for tools, fetching schemas, and executing. There is no functional overlap between any two tools.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (list_finance_categories, search_finance_tools, get_tool_schema, execute_finance_tool), making the API predictable and easy to navigate.

Tool Count5/5

With only 4 tools, the server is well-scoped for its aggregator purpose. Instead of exposing 43 tools directly, it provides a lean meta-layer that is easy to learn and use.

Completeness5/5

The tool set covers the full discovery-to-execution workflow: list categories, search, get schema, and execute. There are no obvious missing operations for an aggregator that intentionally hides the underlying tool catalog.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A meta-server that aggregates multiple MCP servers into a single interface, reducing token usage by 98%+ through progressive tool discovery and direct code execution that processes data between tools without consuming context window space.
    16
    10
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    A proxy server that wraps existing MCP servers to significantly reduce token consumption by compressing tool descriptions into a two-step interface. It enables users to integrate extensive toolsets without exceeding context limits or incurring high API costs.
    116
    Apache 2.0
  • A
    license
    A
    quality
    A
    maintenance
    An MCP orchestration layer that aggregates multiple MCP servers while exposing only 8 meta-tools, dramatically reducing context window usage, and provides SLOP scripting, event monitoring, and tool customization.
    10
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enterprise-grade dynamic MCP proxy that eliminates token bloat by lazy-loading tool schemas based on semantic intent, enabling efficient orchestration of multiple backend tools from a single endpoint.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/YugMakhecha17/MCP_Aggregator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server