Model Context Protocol (MCP) server for Zenskar API - customer management, invoicing, and billing operations
Server provides 30 tools with consistent naming patterns (verb_noun: list*, get*, generate, pause, update, expire, ingest). Most tools have descriptions and input schemas visible in src/server.js. However, output schemas are completely undocumented, the rubric requires documented return types for A+ tools (baseline: 100% of A+ tools have documented return types). Parameter descriptions are present and adequate (10-50 words typically). Security concern: ingestUsageEvents accepts raw 'events' array without documented validation. Error handling and recovery guidance are absent. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear WRITE vs READ_ONLY risk declarations. The server treats READ_ONLY resources correctly and provides pagination (limit/offset) on list tools, but lacks actionable error messages and per-tool output documentation.
Expire a contract by setting its end date to a past date and pruning future phases
Generate an invoice for a contract with specified billing dates
Get balance sheet accounting report grouped by account category
Get billing cycles for a contract
Get detailed information for a specific contract
Get detailed information for a specific credit note
Get detailed information for a specific customer
Output schemas completely undocumented. No tool declares what fields it returns, forcing LLMs to guess structure and lose signal from responses.
No tool annotations despite clear destructive intent. WRITE tools (generateInvoice, pauseContract, updateContract, expireContract, ingestUsageEvents) lack destructiveHint and idempotentHint, preventing agents from reasoning about safety and retry behavior.
No error handling guidance. Tools return raw API errors without recovery hints. E.g., generateInvoice may fail if contract ID invalid, but tool description provides no remediation path like 'Try getContractById first.'
Inferred effective spec: 2025-06-18+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 53 | 2025-06-18+ | v2 |
| 2026-03-09 | F | 21 | - | v1 |
Get income statement accounting report grouped by account category
Get detailed information for a specific invoice
Get line items for a specific invoice
Get HTML preview of an invoice
Ingest usage events for a raw metric with customer_id, timestamp, and data payload
List all aggregates (billable metrics) with pagination and filtering support
List all payments with pagination and filtering support
List all business entities with pagination and filtering support
List all contacts with pagination and filtering support
List all contracts with pagination and filtering support
List all credit notes with pagination and filtering support
List all addresses for a specific customer
List all customers with pagination and filtering support
List all entitlements with pagination and filtering support
List all invoices with pagination and filtering support
List all background jobs with pagination and filtering support
List all journal entries with pagination and filtering support
List all payment methods for a specific customer
List all billing plans with pagination and filtering support
List all products with pagination and filtering support
List all raw metrics with pagination and filtering support
Pause a contract starting from a specified date
Update contract details including end date and phases
ingestUsageEvents accepts unbounded 'events' array without documented validation. No MAX_BULK_INGEST_EVENTS constraint visible in tool schema (only in validator code). LLMs may pass arrays exceeding server limits.
Read-only tools lack readOnlyHint annotation. While risk=READ_ONLY is declared externally, the tool schema itself does not signal safety, forcing agents to reparse declarative metadata instead of trusting the schema.
datetime parameter handling lacks clarity. generateInvoice accepts 'from_date', 'to_date', 'bill_for_date' as datetime but description doesn't explicitly state ISO-8601 or Unix timestamp behavior. Schema conversion logic exists (src/tool-schema.js line 44) but not exposed to LLM.
No per-tool rate limiting or pagination caps documented. listCustomers, listInvoices etc. accept limit/offset but no constraint prevents LLM from passing limit=10000, potentially causing timeouts or resource exhaustion.
updateContract and pauseContract expose complex object parameters ('phases' array, 'unpause_extension_policy' enum) with minimal inline documentation. LLMs struggle to infer nested structure without explicit JSON examples or sub-schema documentation.