ContextCraft has significant structural and quality gaps. While tool names follow verb conventions (trade, get_holdings, search, etc.), descriptions are inconsistent and often lack depth. Most critically, the server mixes two fundamentally different domains (stock trading + math) with no coherent justification. Parameter descriptions exist but lack constraints (enums, ranges, formats). Error handling is minimal, most tools return raw API responses or generic errors without recovery guidance. The 'add' tool (adding two numbers) in a separate module signals conceptual confusion about the server's purpose. No tool annotations (destructiveHint for 'trade', readOnlyHint for read tools), no output schema documentation, no pagination despite tools returning lists. Security concern: API keys are injected via .env but no mention of least-privilege scope declaration.
Output schemas undocumented. Tools return raw dict/list without specifying field structure, types, or chaining IDs. LLMs cannot plan downstream calls or extract required fields reliably.
Parameter descriptions lack constraints. 'period' in get_historical_data says '(e.g., "1m", default "1m")', no enum of valid periods, no format spec. LLMs cannot validate and will guess or reuse examples literally.
No tool annotations (destructiveHint, readOnlyHint). 'trade' is destructive (places real orders) but unmarked, agents cannot reason about side effects. All read tools lack readOnlyHint.
Recommendations
Add output schema documentation for every tool. Specify return type (e.g., 'Returns a dict with keys: symbol (str), change_percentage (float), recommendation (str)') or use OpenAPI-style response objects.
Convert parameter descriptions to include constraints. Replace 'period (e.g., "1m", default "1m")' with 'period (string, enum: 1m|5m|15m|1h|1d|1w; default "1m")'. Replace 'threshold (float)' with 'threshold (float, range 0-100, unit: percent change per day)'.
Add tool annotations: mark 'trade' with destructiveHint=true; mark all read tools with readOnlyHint=true. Use idempotentHint for tools like 'get_holdings'.
Implement confirm-before-execute for 'trade'. Add a dry_run parameter that returns proposed order without placing it. Document the two-step workflow: 1. call trade with dry_run=true; 2. if LLM/user approves, call with dry_run=false.
Improve error handling. Each error should include: (1) what went wrong, (2) recovery action, (3) error type (retryable/user-fixable/fatal). E.g., 'Stock "XYZ" not found on NSE. Try with a different symbol (e.g., "TCS" for Tata Consultancy Services). Retryable: false, reason: invalid symbol.'
Remove 'add' tool from this server. It has nothing to do with stock trading. Create a separate math/utility server if needed, or remove entirely.
Standardize parameter names across tools. Use 'stock_symbol' consistently instead of mixing 'symbol', 'stock_id', 'stock_name'. Document accepted formats: e.g., 'stock_symbol (string, e.g., "INFY" for Infosys, "TCS" for Tata Consultancy Services)'.
Error handling is minimal and non-actionable. 'No matching stock for X' and 'Failed to parse response' offer no recovery path. Missing error classification (retryable vs user-fixable vs fatal).
Composition failure: 'add' tool (math) mixed with 'trade' tools (stock trading). Server has no coherent domain, confuses LLM tool selection and signals poor design. Should be in separate servers.
No pagination for list-returning tools. get_holdings, get_positions, get_order_history, get_trending_stocks, etc. return unbounded lists. Large portfolios or search results blow context window.
Incomplete parameter descriptions. Many tools have bare minimal descriptions (5-10 chars). E.g., 'get_commodities' has no parameters, so no way to filter results. 'get_bse_most_active' has no parameters, no way to sort or limit.
Add pagination support. get_holdings, get_trending_stocks, etc. should accept 'limit' (max 50, default 20) and 'offset' (default 0) or 'cursor'. Return total_count and next_cursor if available.
Document scope requirements. Add to tool descriptions: 'Requires scope: write:portfolio' for trade, 'Requires scope: read:market' for all query tools. Update server metadata with available scopes.
Add parameter constraints for numeric inputs. 'quantity' in trade: 'integer, minimum 1, maximum 100000'. 'threshold' in auto_trade_signal: 'float, range 0-100 (percent)'.
For tools calling external APIs (RapidAPI), document rate limits and timeouts in descriptions. E.g., 'Note: RapidAPI endpoint may be rate-limited (100 calls/day). If request times out, retry after 5 minutes.'
Add a 'list_stocks' or 'search_stocks' discovery tool. Many tools require a stock_symbol but don't explain how to find valid symbols. A lookup tool reduces agent friction.
Document parameter dependencies. E.g., in get_stock_forecasts, 'measure_code (string, enum: EPS|Revenue|NetIncome; must match available forecasts for the stock)'. If a combination is invalid, error message should explain why.
Return filtered/limited responses. If RapidAPI returns 500 trending stocks, cap at 50 and add 'total_count: 500, showing first 50, call with offset=50 for more' guidance.
Add natural-identifier support. 'trade' accepts 'symbol' as a substring match (good), but explain this clearly: 'symbol (string, case-insensitive partial match, e.g., "INF" matches "INFY" and "INFY-BE"). Returns first match.'
Validate Kite API responses. If kite.holdings() returns empty, error message should be: 'No holdings found. Your portfolio is empty. Try placing a trade first.' instead of returning [].
Document what 'filter_type' and 'stats' parameters mean. Replace generic defaults with examples: 'filter_type (string, enum: price|volume|returns; default: price). Use price for price trends, volume for trading activity.'
Add a 'confirm_order' tool separate from 'trade', or implement idempotency key for multi-step order workflows. Document retry behavior: 'If trade returns error, retry with same parameters is safe (idempotent via Kite API).'
Remove or document the 'explain_stock' tool. It calls multiple tools internally (get_stock_forecasts, get_historical_stats, get_52_week_high_low) but doesn't show the composition clearly. If it's a convenience wrapper, document that. If it's redundant, remove it.