A Model Context Protocol server that provides tools to manage OpenAI API keys, spending, and usage via the Admin API.
Two tools with clear verb-noun naming (get_costs, get_projects) and complete input schemas. Descriptions are present but generic (10-15 words each). All parameters have type annotations and descriptions via Annotated. However, output schemas are undocumented, LLMs cannot predict return structure. No error handling guidance. Parameters lack constraints (e.g., no limit on group_by cardinality, no validation of datetime ranges). Tool descriptions do not explain WHEN to use each tool or what distinguishes them. Missing pagination documentation despite implementing pagination internally.
Fetches OpenAI costs for the specified period.
Fetches OpenAI projects for the current organization.
Output schemas undocumented. Both tools return list[dict] with no field documentation. LLMs cannot predict structure (e.g., does get_costs return 'cost' or 'amount'? Does get_projects return 'id' or 'project_id'?). Breaks tool chaining and forces exploratory calls.
Tool descriptions are generic and lack context. 'Fetches OpenAI costs for the specified period' does not explain WHEN to call this vs alternatives, what the period means (billing cycle? custom range?), or what fields are returned. Descriptions should be 50-200 chars with actionable context.
No error handling guidance. Code calls response.raise_for_status() but does not document what errors are possible (401 Unauthorized, 429 Rate Limited, 500 Server Error) or how LLMs should recover. Missing pattern:recovery-guide.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 48 | 2026-07-28+ | v2 |
Pagination implemented but not exposed. Both tools paginate internally (limit=180, next_page/last_id logic) but do not accept page/offset/limit parameters. LLMs cannot control result size or iterate. Violates pattern:paginated-result.
Parameter constraints missing. group_by accepts list[Literal[...]] but no max length documented. project_ids has no cardinality limit. start_time/end_time have no range validation (e.g., max 90 days back?). Unbounded parameters invite invalid LLM calls.