MCP server exposing Indy.fr accounting platform data
Strong foundation with 14 well-named tools following verb_noun convention (get_, list_, create_, upload_). All tools have descriptions (avg 180 chars, within 10-1024 baseline). Input schemas present with type definitions for all parameters. Key strengths: clear parameter descriptions with format guidance (ISO 8601 dates, enum values like 'caisse'/'manuel'/'divers'), security-conscious file validation in upload_receipt, and thoughtful filtering/pagination patterns. Gaps: output schemas not explicitly documented in code; some parameter descriptions could be more prescriptive about constraints; error handling guidance minimal; no tool annotations (readOnlyHint/destructiveHint) despite clear risk levels.
Create a new invoice draft in Indy.fr. Parameters: title (invoice title), client_id (use list_clients to look up), products (list of line items — each a dict with 'name' and 'unit_price_in_cents' keys, optionally 'quantity' and 'description'), notes (optional invoice notes).
Find finalized billing invoices that could match the given transactions, so an issued invoice can be reconciled with an incoming payment. The sales counterpart to find_matching_receipts. Parameters: transaction_ids (list of transaction ids to find matches for). Returns 'invoices' (candidate invoice objects) and 'transactions' (the transactions a match was found for); both empty when nothing matches.
Find already-uploaded but unattached receipts that could match the given transactions, so they can be linked instead of re-uploaded. Parameters: transaction_ids (list of transaction ids to find matches for). Returns 'receipts' (candidate receipt objects) and 'transactions' (the transactions a match was found for); both empty when nothing matches.
Return the full unfiltered list of billing clients registered in Indy.fr.
Output schemas not documented in code. LLMs cannot plan downstream calls or extract fields without knowing what each tool returns. Descriptions mention return structure (e.g., 'receipts' list, 'receiptData' fields) but no formal schema definition visible.
Tool annotations missing. upload_receipt and create_invoice_draft are WRITE operations; list_* and get_* are READ_ONLY. No readOnlyHint or destructiveHint in tool definitions, forcing LLMs to infer risk from descriptions alone.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | <=2025-11-25 | v2 |
Return the receipt/invoice documents ATTACHED to a given transaction. The underlying Indy endpoint also returns the account-wide pool of unattached receipts (pairingStatus 'UNRELATED'); this tool filters those out and returns only the attached ones (pairingStatus 'PAIRED'), so an empty 'receipts' list means the transaction has no receipt. (A transaction object's own 'receipts'/'receiptIds' field lists the same attachments — prefer it when you already have the transaction.)
Return filter metadata for transactions: available date ranges, bank accounts, and transaction categories. Call this before constructing list_transactions queries to discover valid filter values.
Fetch ALL transactions across all pages and return them as a flat list. Accepts the same filters as list_transactions (except page). Warning: may return large amounts of data — prefer list_transactions with pagination unless a complete dataset is required.
Search billing clients in Indy.fr with pagination. Parameters: search (free-text filter), current_page (1-based).
Return a paginated list of invoice drafts from Indy.fr. Parameters: start (0-based offset), limit (number of results, default 20).
Return a paginated list of finalized invoices from Indy.fr. Parameters: status (e.g. 'paid', 'pending', 'overdue' — omit for all), start (0-based offset), limit (number of results, default 20).
Return pending and upcoming (not yet booked) transactions from Indy.fr.
Return all saved products and services from the Indy.fr product library.
Return a paginated list of Indy.fr transactions (30 per page). Use get_transaction_filters to discover valid filter values. Parameters: page (1-based), search (free text), account_or_from (bank account filter), start_date / end_date (ISO 8601 date strings, e.g. '2024-01-01'), transaction_type (entry-method filter: 'caisse' / 'manuel' / 'divers' from get_transaction_filters — there is NO income/expense type; split those by the sign of amountInCents: negative = expense, positive = income/refund).
Upload a receipt or expense document (PDF or image) from disk and attach it to a transaction. Note: only receipts can be uploaded — invoices are created with create_invoice_draft, not uploaded. Parameters: transaction_id (target transaction), file_path (path to the document on this machine), filename (optional override for the name sent to Indy), content_type (optional MIME type; inferred from the extension when omitted). Indy runs OCR on the upload and returns the new receipt with extracted fields (description, amount, date) under 'receiptData'.
Minimal error handling guidance. upload_receipt validates file type and size with clear error messages (good), but most tools lack recovery hints. E.g., if list_transactions returns empty, should the LLM retry with different filters, or is that expected? No guidance.
Parameter constraints not fully formalized. list_transactions accepts 'transaction_type' with enum values 'caisse'/'manuel'/'divers', but no JSON Schema enum constraint visible, only documented in description text. LLMs may hallucinate invalid values.
Pagination inconsistency. list_transactions uses 1-based 'page' parameter; list_invoice_drafts and list_invoices use 0-based 'start' offset. This naming mismatch forces LLMs to reason about different pagination styles for similar operations.