Automated outbound sourcing and investment opportunity analysis
This server exhibits severe quality gaps across naming, descriptions, schema completeness, and error handling. While 8 tools are explicitly defined in src/main.py as FastAPI endpoints, the tool definitions lack the rigor required for reliable agent invocation. Most tools have minimal descriptions (under 50 chars), many parameters lack type information or descriptions, output schemas are not documented, and error handling is generic HTTPException responses that provide no recovery guidance. The server is written as a standard REST API, not as an MCP-compliant tool interface. Tool names are verb-based (get_, crawl_, score_, generate_), which is positive, but descriptions are shallow and parameters frequently underdescribed.
Crawl portfolio data for a specific incubator
Generate an investment committee memo
Get comprehensive insights for a specific company
Process and return daily deal flow from emails
Get list of all incubators from the database
Get market insights and trends
Get portfolio data for a specific incubator
Most tool descriptions are under 50 characters and lack context. 'Process and return daily deal flow from emails' and 'Get market insights and trends' do not explain WHEN to use the tool vs alternatives, what data it requires, or what structure it returns. LLMs cannot reliably select tools based on these descriptions.
Output schemas are not documented. The code returns dictionaries (e.g., {'deals': deals}, {'incubators': df.to_dict('records')}) but the agent has no advance knowledge of what fields to expect. This violates the 'documented return types' baseline (100% of A+ tools have documented return types) and forces the LLM to guess at response structure.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 39 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 28 | - | v1 |
Score a company based on investment criteria and thesis
Parameters lack descriptions. 'company_name' and 'incubator_name' are self-documenting, but many parameter descriptions are missing. The score_company tool accepts a 'company' object with nested properties but provides no guidance on which fields are required, what values are acceptable, or how missing fields are handled. The 'thesis' parameter in score_company is optional but its purpose and structure are not explained.
Error handling is generic and unhelpful. All endpoints raise HTTPException(status_code=500, detail=str(e)) on failure. The agent sees only a raw exception message (e.g., 'string index out of range') with no guidance on cause, retryability, or recovery steps. This violates the 'recovery-guide' pattern, errors must tell the LLM what to do next.
No pagination support. Tools that return lists (get_incubators, get_portfolio, get_daily_dealflow) do not accept limit, offset, or page parameters. If the incubators list grows to hundreds of records, the entire dataset is dumped to the agent, wasting tokens and risking context window exhaustion.
No input validation or constraints. Parameters like 'company_name' and 'incubator_name' are free-form strings with no length limits, format validation, or enum constraints. An LLM can pass arbitrary text, causing silent failures or inconsistent behavior (e.g., database lookup on a misspelled name returns no results without guidance).
score_company parameter 'thesis' is poorly defined. The input shows thesis as an optional object with a single property 'thesis_text', but the description does not explain: (a) what happens if thesis is omitted, (b) what format thesis_text should take (plain text? markdown?), (c) how it affects scoring. The complex nested structure of 'company' parameter is also not documented.
crawl_portfolio is marked WRITE but returns immediately with 'processing' status and executes asynchronously in the background. The agent has no way to check crawl status, verify completion, or handle partial failures. This violates the 'idempotent-operation' and 'confirmation-request' patterns, destructive/side-effect operations should provide feedback or require confirmation.
Tool names are generic but not granular. 'get_company_insights' and 'score_company' both accept or return company data, but it is unclear how they differ or when to use each. 'get_company_insights' calls market_intelligence.get_company_insights, while 'score_company' calls company_scorer.score_company, these have overlapping purposes and could confuse the LLM.
generate_investment_memo calls multiple internal services (affinity_client, market_intelligence, company_scorer) and returns a complex nested structure, but does not document the output schema. The agent does not know what fields to expect or how to extract actionable data from the memo.