A capstone project implementing 4 autonomous trading agents using 6 MCP servers (accounts, market, push notifications, fetch, Brave Search, memory). Agents execute trades via FastMCP-based tools connected to Polygon API for market data and Gradio UI for portfolio visualization.
This MCP server exhibits significant definition quality gaps. While all 7 tools have explicit registrations with names and descriptions, the descriptions are often vague or incomplete, parameter documentation is minimal, output schemas are undocumented, and error handling guidance is absent. The server lacks specificity in describing what each tool does, when to use it, and what to expect from the result. Naming is acceptable (verb-noun pattern mostly followed), but descriptions fall short of the 50-200 character LLM-optimized range. No parameter constraints (enums, ranges, formats) are visible. Output is returned as raw Python types (float, dict, str) without documentation of structure or fields. This is typical of community MCP servers and lands squarely in the 'Fair to Poor' range.
Buy shares of a stock.
At your discretion, if you choose to, call this to change your investment strategy for the future.
Get the cash balance of the given account name.
Get the holdings of the given account name.
This tool provides the current price of the given stock symbol.
Send a push notification with this brief message
Sell shares of a stock.
No output schemas documented. Tools return raw Python types (float, dict, str) with no description of structure, fields, or interpretation. LLMs cannot plan downstream tool calls or extract data reliably.
Parameter descriptions are minimal or generic. 'The name of the account holder' appears verbatim in three tools without additional context. No validation rules, constraints, or dependency hints are provided.
Tool descriptions are too brief (under 50 characters for most). 'Get the cash balance of the given account name' lacks context: What is cash balance vs portfolio value? When should this be called? Is it real-time or cached?
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 59 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 39 | - | v1 |
No error handling or recovery guidance. Tools do not document failure modes (e.g., 'Account not found', 'Insufficient funds', 'Invalid symbol'). LLMs cannot self-correct or retry intelligently.
No parameter constraints visible. 'quantity' is an integer with no min/max bounds. 'symbol' is a free-form string with no format or enum. LLMs can pass invalid values (quantity=-5, symbol='INVALID') with no guidance.
get_holdings returns dict[str, int] with no documentation of structure. Is it {'AAPL': 100, 'MSFT': 50}? What if empty? No guidance for LLM on parsing or iteration.
buy_shares and sell_shares both require 'rationale' parameter but do not constrain or validate it. No guidance on format, length, or required content. Vague parameters invite hallucinated or nonsensical inputs from LLMs.
change_strategy has vague description: 'At your discretion, if you choose to, call this to change your investment strategy for the future.' This is not actionable. When should this be called? What does 'strategy' expect as input? Format? Examples?
No idempotency hints or confirmation mechanisms for destructive operations. buy_shares and sell_shares modify state but provide no dry-run, confirmation, or rollback capability. If an agent retries a failed call, shares could be bought/sold twice.