EVE Online OSINT MCP Server using EveWho API for intelligence gathering
The EVE Online OSINT server demonstrates basic tool structure with names following verb_noun conventions and input schemas present. However, there are critical gaps in parameter documentation, output schema clarity, and error handling guidance. Tool descriptions are present but relatively generic (average ~80 chars, below the 194-char baseline for A-grade tools). No parameter descriptions visible in the schemas, all 9 tools list parameters with types but lack the explanatory text that helps LLMs understand constraints and purpose. Output schemas are not explicitly documented in the code, forcing LLMs to infer response structure. Error handling provides raw HTTP status codes without actionable recovery guidance.
Get list of member corporations in an alliance from EveWho
Get basic alliance information by alliance ID including founder, executor, and creation date
Get character information including current corporation and alliance from EveWho
Get the latest 20 killmails involving a character from zKillboard
Get character combat statistics from zKillboard including kills, ISK destroyed/lost
Get CEO information for a corporation
Get basic corporation information by corporation ID including ticker, CEO, member count
Get list of corporation members including join dates and security status from EveWho
All 9 tools lack parameter descriptions in their schema definitions. The Input schema shows only 'type' and 'description' for parameters (e.g., alliance_id), but the 'description' field is minimal (e.g., 'The EVE Online alliance ID'). Per pattern:tool-description and review:param-validation-rules, every parameter must have a description explaining constraints, format, expected range, and context. Example: alliance_id should note 'A positive integer representing the EVE Online alliance ID. Obtain via resolve_entity_name_to_id() or ESI lookup.'
Output schemas are not documented in the tool definitions or README. Tools return TypeScript interfaces (EveWhoCharacterResponse, ZKillboardStats, etc.), but LLMs cannot see these types, they infer response structure by trial. Per pattern:tool and mxe:strip-api-responses, each tool must document what fields are returned, their types, and which are chaining IDs for downstream calls. For example, get_character_info should document: 'Returns {character_id: number, name: string, corporation_id: number, alliance_id?: number, security_status?: number}' so agents know what's available for follow-up queries.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-21 | F | 47 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 19 | - | v1 |
Resolve an entity name (character, corporation, or alliance) to its ID using ESI
Error handling provides no recovery guidance. In src/server.ts, fetchWithRetry() returns raw HTTP responses with status codes (500, 429, 408) but tool implementations do not wrap these in actionable error messages. Per pattern:recovery-guide, errors should tell the LLM: 'Alliance not found. Try resolve_entity_name_to_id() with the alliance name first.' Current approach forces LLMs to guess next steps on failures.
Tool descriptions lack context for LLM selection. Example: 'Get basic alliance information by alliance ID' does not explain when to use this vs get_alliance_corporations, or what prerequisites are needed (e.g., 'Call resolve_entity_name_to_id() first if you only have the alliance name'). Per pattern:tool-description, descriptions should include WHAT, WHEN, and any dependencies. Current descriptions average ~60-75 chars; target 50-200 chars with actionable guidance.
No pagination support documented or implemented. Tools like get_alliance_corporations and get_corporation_members return potentially large lists (corporations, members) but do not expose limit, offset, or cursor parameters. Per pattern:paginated-result and mxe:enforce-result-limits, tools returning lists must accept pagination and document max result counts. Without pagination, large responses blow context windows.
No input validation feedback. Tools accept numeric alliance_id and corporation_id parameters but do not validate ranges or provide clear error messages for invalid inputs. Per review:actionable-errors, errors should include the invalid value and constraint: 'Invalid alliance_id: got -123, must be a positive integer.'