Convert PDF bank statements to checked Excel, CSV or JSON with balance validation.
This is a well-structured MCP server with clear, production-focused tool definitions. All 5 tools have explicit schemas, descriptions, and parameter types. Tool names use consistent verb_noun patterns (convert_*, get_*, list_, set_). Descriptions are concise and actionable, ranging 90-280 chars. Parameters are typed with enums, ranges, and detailed descriptions. Output schemas are documented through Pydantic models. Error handling includes actionable guidance (e.g., suggesting alternative approaches when a resource is not found). The main gaps are: (1) lack of tool annotations on most tools (only some tools have read_only_hint, destructive_hint, idempotent_hint defined in code), (2) error taxonomy not explicitly in tool descriptions (though implemented in code), and (3) some parameters like 'timeout_seconds' have rationale in descriptions but could be clearer about retry semantics. Schemas are complete and JSON-serializable. Security is handled properly via OAuth middleware (credentials not exposed as parameters). The tool set is well-composed: convert_bank_statement (write), get_conversion (read, idempotent), list_conversions (read, paginated), get_account_balance (read), set_output_folder (write, stateless config). This is a B+ server, excellent domain coverage and clarity, minor gaps in annotation metadata exposure.
Convert one PDF bank statement through the complete MainBook workflow: create a job, upload, start, poll, and return structured data. This creates a job and spends page credits; it is not read-only.
Check available page credits and other account status. Idempotent and read-only.
Poll a conversion job by its job_id after calling convert_bank_statement with a timeout_seconds that expired before completion. Returns the same structured data as convert_bank_statement without creating a new job or spending additional credits. Idempotent.
List conversion jobs associated with the MainBook account, ordered by recency. Idempotent and read-only.
Store the local folder where binary result files (XLSX, CSV) are written. Called once during setup over stdio; HTTP mode ignores it. Idempotent.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) are defined in Python code as ToolAnnotations objects but are not explicitly exposed in the MCP tool registration that LLMs see. The annotations exist internally (CONVERT_ANNOTATIONS, READ_ANNOTATIONS, etc.) but may not be serialized in the tool_list response.
get_account_balance has an empty input schema ({}), which is correct for a read-only status check, but the description 'Check available page credits and other account status' does not explicitly state what fields are returned (page_credits, account_status, etc.). The caller must infer from the return type.
Error handling guidance is implemented in the code (MainBookAPIError, MainBookFileError, MainBookNetworkError subclasses) but is not documented in tool descriptions. Descriptions do not say 'If timeout_seconds expires, returns job_id for polling with get_conversion' or 'If file not found, check file_path is in allowed roots'. Error recovery paths should be explicit in descriptions.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 74 | 2026-07-28+ | v2 |
convert_bank_statement and get_conversion parameters include 'timeout_seconds' with a default that 'stays under the 60-second request timeout most MCP clients enforce.' This is correct design, but the description does not clearly state what happens to the job if timeout expires: is the job abandoned, or does it continue running? Clarify that the job continues and can be retrieved with get_conversion(job_id).
set_output_folder description states it is 'Called once during setup over stdio; HTTP mode ignores it' but does not explain the side effect: the folder path is persisted across calls. This state mutation is not typical for stateless HTTP, and the description should clarify idempotency and persistence semantics.