{
  "name": "mcp.zovo.one remote MCP endpoints",
  "protocol": "MCP streamable HTTP (2025-06-18)",
  "transport": "streamable-http",
  "auth": {
    "oauth": "none - this endpoint deliberately has no OAuth flow; a static token is all a client needs",
    "forms": [
      {
        "form": "header",
        "scheme": "Authorization: Bearer <token>",
        "use_when": "your client can set a header (Claude Code with --header, curl, an SDK)",
        "example": "https://mcp.zovo.one/mcp/<server>"
      },
      {
        "form": "url-path",
        "scheme": "https://mcp.zovo.one/mcp/<server>/t/<token>",
        "use_when": "your client accepts a URL and nothing else - Claude.ai custom connectors, the Claude Desktop connector dialog, several IDE pickers",
        "note": "the same token, the same tiers and the same rate limits as the header; the URL itself is the credential, so treat it as private"
      },
      {
        "form": "url-query",
        "scheme": "https://mcp.zovo.one/mcp/<server>?token=<token>",
        "use_when": "a client that takes a query string but not a header"
      }
    ],
    "precedence": "an Authorization header wins over a token in the URL",
    "connect_page": {
      "url": "https://mcp.zovo.one/mcp/connect",
      "what": "mints a free token and prints the ready URL for every server, with per-client instructions"
    },
    "whoami": {
      "url": "https://mcp.zovo.one/mcp/whoami",
      "also": "https://mcp.zovo.one/mcp/whoami/t/<token>",
      "returns": "{tenant, tier, bound}"
    },
    "anonymous": {
      "mint": "https://mcp.zovo.one/mcp/token",
      "format": "anon_<32 hex>",
      "tier": "free",
      "data_retention_days": 30,
      "rate_limit": "600/hour",
      "mint_rate_limit": "10/hour per client IP"
    },
    "pro": {
      "buy": "https://mcp.zovo.one/buy/<product>",
      "format": "MCPL1.<payload>.<signature>",
      "verified": "Ed25519, offline",
      "rate_limit": "6000/hour",
      "bound_purchase": "Buying through https://mcp.zovo.one/buy/<product>?tenant=<anon token> binds that purchase to the anonymous token: the same URL then runs in Pro mode over the same anonymous data document, with no key to paste and nothing to move. The free-cap answers on this endpoint already carry that link."
    },
    "guide": "https://mcp.zovo.one/guides/mcp-server-free-vs-pro"
  },
  "endpoints": [
    {
      "name": "time-tracker",
      "url": "https://mcp.zovo.one/mcp/time-tracker",
      "tools": [
        "timer_start",
        "timer_stop",
        "timer_status",
        "entry_add",
        "entry_list",
        "entry_delete",
        "entry_edit",
        "project_set_rate",
        "report",
        "invoice_summary",
        "export_csv",
        "license_status",
        "license_activate"
      ],
      "free_limits": "reports cover the last 7 days, 2 rated projects",
      "notes": "export_csv returns a download link valid for one hour instead of a local file path"
    },
    {
      "name": "price-tracker",
      "url": "https://mcp.zovo.one/mcp/price-tracker",
      "tools": [
        "price_check",
        "watch_add",
        "watch_list",
        "watch_remove",
        "watch_refresh",
        "price_history",
        "price_add_manual",
        "alerts_pending",
        "license_status",
        "license_activate"
      ],
      "free_limits": "3 watches, last 30 observations per watch",
      "notes": "public http/https pages only; private, loopback, link-local and metadata addresses are refused, before and after every redirect"
    },
    {
      "name": "invoice",
      "url": "https://mcp.zovo.one/mcp/invoice",
      "tools": [
        "business_set",
        "client_add",
        "client_list",
        "invoice_create",
        "invoice_from_hours",
        "invoice_list",
        "invoice_get",
        "invoice_mark_paid",
        "invoice_pdf",
        "overdue_report",
        "license_status",
        "license_activate"
      ],
      "free_limits": "3 invoices per calendar month, footer line on the rendered document",
      "notes": "invoice_pdf renders a print-ready HTML document behind a one-hour download link"
    },
    {
      "name": "expense-tracker",
      "url": "https://mcp.zovo.one/mcp/expense-tracker",
      "tools": [
        "expense_add",
        "expense_list",
        "expense_update",
        "expense_delete",
        "receipt_attach",
        "category_rules",
        "expense_settings",
        "expense_summary",
        "mileage_add",
        "expense_export",
        "expense_to_invoice",
        "license_status",
        "license_activate"
      ],
      "free_limits": "last 30 days, 3 projects, 5 category rules, 200 export rows, 20 rebill items per call, csv/json export (xlsx is Pro)",
      "notes": "expense_export returns a download link valid for one hour (xlsx is delivered as the real binary workbook). receipt_attach is not available: this endpoint has no filesystem, so attach receipts with the stdio server"
    },
    {
      "name": "spreadsheet",
      "url": "https://mcp.zovo.one/mcp/spreadsheet",
      "tools": [
        "sheet_load",
        "sheet_files",
        "sheet_unload",
        "sheet_info",
        "sheet_read",
        "sheet_query",
        "sheet_stats",
        "sheet_find",
        "sheet_add_column",
        "sheet_convert",
        "sheet_write",
        "license_status",
        "license_activate"
      ],
      "mode": "inline data",
      "how": "There is no disk here, so you send the data instead of a path: sheet_load {name, csv} or sheet_load {name, xlsx_base64} stores it under your token, and every other tool takes that name as its `path` argument. sheet_files lists what is loaded, sheet_unload deletes one.",
      "outputs": "sheet_convert, sheet_write and sheet_add_column write into the same per-token store and return a download link valid for one hour; xlsx comes back as the real binary workbook.",
      "free_limits": "5,000 rows and 5 MB read per sheet, 500 rows written per file",
      "storage": "2 MB of loaded sheets per token"
    },
    {
      "name": "currency",
      "url": "https://mcp.zovo.one/mcp/currency",
      "tools": [
        "rates_latest",
        "convert",
        "convert_many",
        "fx_rates_for",
        "rate_history",
        "rate_on",
        "currencies_list",
        "cache_status",
        "license_status",
        "license_activate"
      ],
      "free_limits": "historical rates over the last 90 days (Pro reads the series back to 1999-01-04)",
      "notes": "ECB reference rates. The two ECB files are one shared cache for the whole endpoint, refreshed at most every 6 hours (daily) and 24 hours (history); nothing here is per-token, and only https://www.ecb.europa.eu is ever fetched"
    },
    {
      "name": "timezone",
      "url": "https://mcp.zovo.one/mcp/timezone",
      "tools": [
        "now",
        "convert_time",
        "overlap",
        "find_meeting_slots",
        "dst_changes",
        "business_days",
        "contacts_set",
        "contacts_list",
        "ics_create",
        "license_status",
        "license_activate"
      ],
      "free_limits": "3 participants, 5 days per search, 5 saved contacts, 3 calendar files per month",
      "notes": "contacts are kept per token; ics_create returns a download link valid for one hour instead of a local file path, and out_path is only the name that file carries"
    },
    {
      "name": "docx",
      "url": "https://mcp.zovo.one/mcp/docx",
      "tools": [
        "doc_upload",
        "doc_files",
        "doc_delete_upload",
        "business_set",
        "doc_create",
        "doc_from_markdown",
        "doc_read",
        "doc_to_html",
        "doc_fill_template",
        "proposal_create",
        "contract_create",
        "license_status",
        "license_activate"
      ],
      "mode": "upload and download",
      "how": "There is no disk here: doc_upload {name, docx_base64} stores an existing .docx under your token and every tool takes that name as its `path`; doc_read and doc_fill_template also accept docx_base64 directly, which stores the file under the same root (default name 'inline' / 'template'). doc_files lists what is uploaded, doc_delete_upload removes one.",
      "outputs": "doc_create, doc_from_markdown, proposal_create, contract_create, doc_fill_template and doc_to_html return a download link valid for one hour; .docx comes back as the real binary file (application/vnd.openxmlformats-officedocument.wordprocessingml.document).",
      "free_limits": "3 proposals or contracts per calendar month, templates up to 10 placeholders, footer line and default letterhead",
      "storage": "2 MB of uploaded documents per token, and at most 2 MB in one upload. The practical ceiling on a base64 paste is far lower and is measured, not theoretical: the model retypes the payload into the call, and in the round-14 measurement 13 KB of base64 died at 16 minutes without emitting the call while 1.4 KB took 47 seconds (D-R74). Above about 10 KB, pass url instead of docx_base64 and the fetch happens here"
    },
    {
      "name": "resume",
      "url": "https://mcp.zovo.one/mcp/resume",
      "tools": [
        "doc_upload",
        "doc_files",
        "doc_delete_upload",
        "profile_set",
        "profile_get",
        "resume_create",
        "resume_to_markdown",
        "resume_to_html",
        "resume_read",
        "cover_letter_create",
        "tailor_to_job",
        "license_status",
        "license_activate"
      ],
      "mode": "upload and download",
      "how": "The profile is stored per token: profile_set once, then resume_create, resume_to_html, resume_to_markdown, cover_letter_create and tailor_to_job read it. There is no disk here, so resume_read takes docx_base64 directly, or a name uploaded with doc_upload {name, docx_base64}.",
      "outputs": "resume_create, resume_to_html and cover_letter_create return a download link valid for one hour; .docx comes back as the real binary file. resume_to_markdown returns the markdown in the answer.",
      "free_limits": "3 cover letters per calendar month, the \"modern\" resume style, one default profile variant, 2,000 characters of job description in tailor_to_job",
      "storage": "2 MB of profile, letter history and uploaded documents per token"
    },
    {
      "name": "recurring",
      "url": "https://mcp.zovo.one/mcp/recurring",
      "tools": [
        "schedule_create",
        "schedule_list",
        "schedule_get",
        "schedule_update",
        "schedule_pause",
        "schedule_resume",
        "schedule_delete",
        "schedule_skip",
        "schedule_upcoming",
        "invoice_generate_due",
        "schedule_history",
        "forecast",
        "license_status",
        "license_activate"
      ],
      "mode": "shares the invoice store",
      "how": "invoice_generate_due writes real invoices into the same per-token invoice data the /mcp/invoice endpoint serves, under the same number series, so invoice_list and overdue_report there show them. Set the issuer and the clients once with business_set and client_add on /mcp/invoice.",
      "outputs": "each generated invoice comes back as a print-ready HTML document behind a one-hour download link (there is no PDF renderer on Workers)",
      "free_limits": "3 active schedules, 30 days of schedule_upcoming, 12 periods per forecast"
    },
    {
      "name": "clauses",
      "url": "https://mcp.zovo.one/mcp/clauses",
      "tools": [
        "clause_add",
        "clause_get",
        "clause_update",
        "clause_delete",
        "clause_list",
        "clause_search",
        "clause_import",
        "clause_export",
        "contract_assemble",
        "variables_list",
        "license_status",
        "license_activate"
      ],
      "how": "The clause library is per token and is seeded with the starter set on first use. clause_import needs a file on a disk, which this endpoint does not have: add clauses with clause_add, or import locally over stdio.",
      "outputs": "contract_assemble and clause_export return a download link valid for one hour; .docx comes back as the real binary file.",
      "free_limits": "10 clauses of your own on top of the starter set, 8 clauses per assembled document, markdown import and export (JSON is Pro)"
    },
    {
      "name": "pdf",
      "url": "https://mcp.zovo.one/mcp/pdf",
      "tools": [
        "pdf_upload",
        "pdf_files",
        "pdf_delete_upload",
        "pdf_info",
        "pdf_count",
        "pdf_merge",
        "pdf_split",
        "pdf_pages",
        "pdf_rotate",
        "pdf_stamp",
        "pdf_watermark_business",
        "pdf_reorder",
        "pdf_text",
        "license_status",
        "license_activate"
      ],
      "mode": "upload and download",
      "how": "There is no disk here: pdf_upload {name, pdf_base64} stores a PDF under your token and every `path` argument - and every entry of `paths` - is that name. pdf_files lists what is stored, pdf_delete_upload removes one.",
      "outputs": "pdf_merge, pdf_split, pdf_pages, pdf_rotate, pdf_stamp, pdf_watermark_business and pdf_reorder return a download link valid for one hour, served as application/pdf. The file is also kept under your token, so a merged file can be stamped by the next call.",
      "free_limits": "up to 5 files per merge, files up to 30 pages for split, pages, rotate and stamp, the PAID and DRAFT stamp presets in their preset colours; pdf_info, pdf_count and pdf_text are unlimited",
      "storage": "2 MB of stored PDFs per token, and at most 2 MB in one upload - the 256 KB request-body cap binds long first, which is roughly 190 KB of PDF once base64-encoded",
      "notes": "pdf_text is best-effort extraction with node:zlib and has no OCR, exactly as it is over stdio"
    },
    {
      "name": "calendar",
      "url": "https://mcp.zovo.one/mcp/calendar",
      "tools": [
        "ics_import",
        "calendars_list",
        "events_list",
        "events_search",
        "free_busy",
        "conflicts",
        "next_event",
        "event_export",
        "event_to_time_entry",
        "ics_forget",
        "license_status",
        "license_activate"
      ],
      "mode": "import and download",
      "how": "ics_import {text, name} pastes a calendar export in; ics_import {url, name} fetches a public https or webcal feed (Pro). A path is not available: this endpoint has no filesystem. Calendars are kept per token and calendars_list shows them.",
      "outputs": "event_export returns a download link valid for one hour, served as text/calendar; out_path is only the name that file carries",
      "free_limits": "2 calendars, a 31-day window per read, 50 events per export; importing from a URL is Pro",
      "storage": "2 MB of imported calendars per token; one import is capped at 5 MB, and the 256 KB request-body cap binds long first",
      "notes": "a feed URL is checked against every literal private, loopback, link-local and metadata address before the first hop and again after every redirect; there is no override"
    },
    {
      "name": "kanban",
      "url": "https://mcp.zovo.one/mcp/kanban",
      "tools": [
        "task_add",
        "task_list",
        "task_move",
        "task_update",
        "task_done",
        "task_delete",
        "task_search",
        "board",
        "task_start_timer",
        "task_log_time",
        "project_list",
        "overdue",
        "weekly_review",
        "columns_set",
        "license_status",
        "license_activate"
      ],
      "how": "Boards, columns and tasks are kept per token; nothing is uploaded and nothing is downloaded. task_add creates the board on first use, board renders it as a table, and columns_set changes the column set.",
      "free_limits": "3 projects, 200 open tasks, the default 5 columns (a custom column set is Pro)",
      "notes": "day boundaries - due today, overdue, weekly_review - are computed in the timezone on the shared business profile for your token when one is set (business_set {timezone} on /mcp/invoice), and in UTC otherwise. task_start_timer hands the task to /mcp/time-tracker, which is a separate document for the same token, so the sibling-project warning the stdio server prints is not available here",
      "storage": "512 KB of boards and tasks per token"
    },
    {
      "name": "image",
      "url": "https://mcp.zovo.one/mcp/image",
      "tools": [
        "image_upload",
        "image_files",
        "image_delete_upload",
        "image_info",
        "image_resize",
        "image_convert",
        "image_compress",
        "image_crop",
        "image_thumbnails",
        "image_watermark",
        "image_strip_metadata",
        "image_batch_resize",
        "image_dominant_colors",
        "license_status",
        "license_activate"
      ],
      "mode": "upload and download",
      "how": "There is no disk here: image_upload {name, image_base64} stores a PNG, JPEG, BMP, GIF or TIFF under your token and every `path` argument - and every entry of `paths` - is that name. The format is read from the magic bytes, not from the name. image_files lists what is stored, image_delete_upload removes one.",
      "outputs": "image_resize, image_convert, image_compress, image_crop, image_strip_metadata, image_thumbnails and image_batch_resize return a download link valid for one hour, served with the real image content type (image/png, image/jpeg, image/bmp, image/gif, image/tiff). The file is also kept under your token, so a resized image can be cropped by the next call. out_dir is not a directory here: each output is its own link.",
      "free_limits": "sources up to 4 MP and 5 files per batch call; image_info is unlimited, and image_dominant_colors is Pro",
      "storage": "2 MB of stored images per token, and at most 2 MB in one upload - the 256 KB request-body cap binds long first, which is roughly 190 KB of image once base64-encoded",
      "notes": "decoding runs on jimp under nodejs_compat. image_watermark is not available: it draws with bitmap font files loaded from a filesystem, which this endpoint does not have"
    },
    {
      "name": "bank-statement",
      "url": "https://mcp.zovo.one/mcp/bank-statement",
      "tools": [
        "bank_upload",
        "bank_files",
        "bank_delete_upload",
        "statement_import",
        "transactions_list",
        "transactions_search",
        "category_rules",
        "transaction_categorize",
        "statement_summary",
        "reconcile_expenses",
        "recurring_detect",
        "statement_export",
        "accounts_list",
        "license_status",
        "license_activate"
      ],
      "mode": "upload and download",
      "how": "There is no disk here: bank_upload {name, content} sends the bank export as text (content_base64 sends the bytes instead, which keeps a UTF-16 export from Excel readable) and statement_import takes that name as its `path`. bank_files lists what is stored, bank_delete_upload removes one. Columns, delimiter, date order and number locale are detected from the file, and a line already stored is skipped rather than doubled, so re-importing an overlapping export is safe.",
      "outputs": "statement_export returns a download link valid for one hour, served as text/csv or application/json",
      "free_limits": "2 accounts, reads the last 12 months, 5 category rules; reconcile_expenses, recurring_detect and statement_export are Pro",
      "storage": "2 MB of uploaded statements and stored transactions per token, and at most 1 MB in one upload (the 256 KB request-body cap binds first)",
      "notes": "reconcile_expenses reads the expense ledger stored for the SAME token on /mcp/expense-tracker, hydrated read-only and never written. The parser reads delimited exports (comma, semicolon, tab), exactly as it does over stdio"
    },
    {
      "name": "quotes",
      "url": "https://mcp.zovo.one/mcp/quotes",
      "tools": [
        "quote_create",
        "quote_list",
        "quote_get",
        "quote_update",
        "quote_send_text",
        "quote_accept",
        "quote_decline",
        "quote_pdf",
        "quote_report",
        "license_status",
        "license_activate"
      ],
      "mode": "shares the invoice store",
      "how": "Quote a client with quote_create (prices in MINOR units: 9000 is 90.00 EUR), send it with quote_send_text, and quote_accept turns it into a real invoice in the same per-token invoice data the /mcp/invoice endpoint serves, under the same number series and the same client list. Set the issuer once with business_set on /mcp/invoice; the shared business profile is the same for both.",
      "outputs": "quote_pdf returns a print-ready HTML quote behind a one-hour download link (there is no PDF renderer on Workers, so it is the same document invoice_pdf produces, in the quote layout). quote_send_text returns the pasteable text in the answer and the same text as a .txt download link.",
      "free_limits": "5 open quotes at a time (accepted, declined and lapsed ones never count); quote_pdf and quote_report are Pro",
      "notes": "an accepted quote's stored lines are copied into the invoice, never recomputed, so a VAT default changed between quoting and accepting cannot move the total the client agreed to. The invoice is written through the shared engine, so the /mcp/invoice free cap of 3 invoices a month does not apply to it; the quotes free cap does. Today's date comes from the timezone on the shared profile when one is set, which is what a validity window is counted in"
    },
    {
      "name": "barcode",
      "url": "https://mcp.zovo.one/mcp/barcode",
      "tools": [
        "qr_create",
        "qr_wifi",
        "qr_vcard",
        "qr_payment_sepa",
        "invoice_payment_qr",
        "barcode_create",
        "barcode_batch",
        "code_list",
        "license_status",
        "license_activate"
      ],
      "mode": "download",
      "how": "There is no disk here: out_path is not a path, it is only the name the downloaded file carries (1-64 characters of letters, digits, underscore or dash). Leave it out and an SVG comes back inline in the answer, ready to paste into a document; a PNG always comes back as a link.",
      "outputs": "qr_create, qr_wifi, qr_vcard, qr_payment_sepa, invoice_payment_qr, barcode_create and barcode_batch return a download link valid for one hour, served as image/svg+xml or image/png",
      "free_limits": "20 codes per calendar month, SVG output; PNG output and barcode_batch are Pro",
      "notes": "invoice_payment_qr reads the invoice stored for the SAME token on /mcp/invoice for the amount and the reference, hydrated read-only and never written, and takes the beneficiary IBAN and name from the shared business profile (business_set on /mcp/invoice). A PNG barcode carries no printed digits under the bars: jimp's bitmap fonts are files on a filesystem this endpoint does not have, and the SVG, which is the default, draws its own text and does carry them"
    },
    {
      "name": "zip",
      "url": "https://mcp.zovo.one/mcp/zip",
      "tools": [
        "zip_upload",
        "zip_files",
        "zip_delete_upload",
        "zip_create",
        "zip_list",
        "zip_extract",
        "zip_extract_text",
        "zip_add",
        "zip_bundle_month",
        "zip_history",
        "license_status",
        "license_activate"
      ],
      "mode": "upload and download",
      "how": "There is no disk here: zip_upload {name, content_base64} sends an archive's bytes (a name ending .zip is checked for the PK magic before it is stored) or {name, content} sends a text file to pack, and every `path` argument is one of those names. zip_files lists what is stored, zip_delete_upload removes one. zip_create packs uploaded files by name; `dir` is refused rather than ignored, because there is no directory tree to walk.",
      "outputs": "zip_create and zip_add return the archive as a download link valid for one hour (application/zip), and zip_extract returns ONE link per entry, served with that entry's own content type. There are no directories, so out_dir is accepted and ignored and at most 20 entries are extracted per call.",
      "free_limits": "20 archives per calendar month, 25 MB per archive, 200 entries per archive; zip_list, zip_extract and zip_extract_text are free on every tier, because the archive somebody sent you is the one that most needs checking",
      "storage": "2 MB of uploaded files and the register per token, and at most 1 MB in one upload - the 256 KB request-body cap binds long first, which is roughly 190 KB of archive once base64-encoded",
      "notes": "every bomb, traversal, absolute-path and symlink guard is decided from the central directory before a byte is inflated, and each entry's CRC is checked against the data, exactly as over stdio. zip_bundle_month is a local (stdio) tool only: it bundles the output FOLDERS the sibling servers write on a disk, and every hosted endpoint hands its documents back as a download link instead, so there is no folder here to read"
    },
    {
      "name": "billing-docs",
      "url": "https://mcp.zovo.one/mcp/billing-docs",
      "tools": [
        "credit_note_create",
        "credit_note_list",
        "credit_note_get",
        "credit_note_pdf",
        "credit_note_text",
        "purchase_order_create",
        "purchase_order_list",
        "purchase_order_get",
        "purchase_order_pdf",
        "purchase_order_text",
        "purchase_order_receive",
        "billing_docs_report",
        "license_status",
        "license_activate"
      ],
      "mode": "shares the invoice store",
      "how": "Credit an invoice with credit_note_create (in full, by amount_minor, or line by line: prices in MINOR units, 9000 is 90.00 EUR) against an invoice in the same per-token invoice data the /mcp/invoice endpoint serves, and raise supplier orders with purchase_order_create. Set the issuer once with business_set on /mcp/invoice; the shared business profile is the same for both, and a supplier the invoice server already knows brings its address and VAT id onto the order.",
      "outputs": "credit_note_pdf and purchase_order_pdf return a print-ready HTML document behind a one-hour download link (there is no PDF renderer on Workers, so it is the invoice layout titled CREDIT NOTE or PURCHASE ORDER). credit_note_text and purchase_order_text return the pasteable text in the answer and the same text as a .txt download link.",
      "free_limits": "5 documents per calendar month, credit notes and purchase orders together; both text exports are free, and credit_note_pdf, purchase_order_pdf and billing_docs_report are Pro",
      "notes": "a credit note can never take back more than the invoice's remaining creditable amount, which is the invoice total less everything already credited against it. Crediting a whole invoice or a whole line copies the stored numbers rather than recomputing them; a partial amount is split across the invoice's own VAT rates, in proportion to each rate's share of the total, so a mixed-rate invoice is never credited at one rate. Every money field on a credit note is stored negative, the unit price included"
    },
    {
      "name": "deposits",
      "url": "https://mcp.zovo.one/mcp/deposits",
      "tools": [
        "deposit_record",
        "deposit_list",
        "deposit_apply",
        "deposit_refund",
        "deposit_balance",
        "deposit_statement_text",
        "deposit_statement_pdf",
        "deposits_report",
        "license_status",
        "license_activate"
      ],
      "mode": "shares the invoice store",
      "how": "Record the money a client paid up front with deposit_record (amounts in MINOR units: 50000 is 500.00 EUR), then deposit_apply puts part or all of it on an invoice in the same per-token invoice data the /mcp/invoice endpoint serves, and deposit_refund gives the rest back. deposit_balance and deposits_report say what is still held. Set the issuer once with business_set on /mcp/invoice; the shared business profile is the same for all of them.",
      "outputs": "deposit_statement_pdf returns a print-ready HTML statement behind a one-hour download link (there is no PDF renderer on Workers, so it is the same A4 layout the credit note uses, titled DEPOSIT STATEMENT). deposit_statement_text returns the pasteable text in the answer and the same text as a .txt download link.",
      "free_limits": "5 deposits recorded per calendar month; deposit_apply, deposit_refund, deposit_list, deposit_balance and deposit_statement_text are free and unlimited on every tier, because money already held has to be able to leave the book. deposit_statement_pdf and deposits_report are Pro",
      "notes": "deposit_apply writes the payment onto the invoice the way the invoice server's own invoice_mark_paid writes one - paid_minor, paid_date and status - but ADDS to paid_minor rather than replacing it, so a deposit applied after a bank transfer does not erase that transfer. It can never pay out more than the deposit still holds or more than the invoice still owes, and a deposit is applied at its own currency and never converted. A refund never touches the invoice: giving a client their own money back is not a payment of a bill"
    },
    {
      "name": "per-diem",
      "url": "https://mcp.zovo.one/mcp/per-diem",
      "tools": [
        "perdiem_rates",
        "perdiem_calc",
        "trip_record",
        "trip_list",
        "trip_export",
        "perdiem_report",
        "license_status",
        "license_activate"
      ],
      "mode": "bundled rate tables",
      "how": "perdiem_rates lists a scheme's rates with the authority, instrument, source URL and effective date they came from; perdiem_calc prices one trip; trip_record saves it. Start and end are instants: either ISO 8601 carrying its own offset, or a local datetime plus an IANA timezone, so a trip across a clock change is 23 or 25 hours and not 24. The traveller's name comes from the shared business profile (business_set on /mcp/invoice).",
      "outputs": "JSON only. There is no document to render and nothing is written outside your own trip store. trip_export returns the exact expense_add ARGUMENTS for a trip, one payload for subsistence and, with split_lodging, a second for lodging, to pass to /mcp/expense-tracker yourself: this endpoint never appends to that ledger, because the expense server's id counter, category rules and VAT split all live inside its own expense_add handler.",
      "free_limits": "5 trips recorded per calendar month; perdiem_rates, perdiem_calc and trip_list are free and unlimited on every tier, because a per diem rate is public information published by a tax authority. trip_export and perdiem_report are Pro",
      "notes": "the rates are BUNDLED tables, not a feed: pl (Dz.U. 2022 poz. 2302), uk (HMRC benchmark scale rates) and us (GSA CONUS). Nothing is fetched, so the same trip prices the same way on every run, and every answer carries the header saying which instrument the figure came from and when it was read. A rate that could not be stated with confidence from the published text was OMITTED rather than guessed, so a destination that is not bundled is REFUSED by name and sent to the source instead of being priced from a near-match. Currencies are never added together: there is no exchange rate in this endpoint"
    },
    {
      "name": "asset-register",
      "url": "https://mcp.zovo.one/mcp/asset-register",
      "tools": [
        "asset_add",
        "asset_list",
        "asset_schedule",
        "asset_journal",
        "asset_dispose",
        "asset_report",
        "license_status",
        "license_activate"
      ],
      "mode": "bundled rate tables",
      "how": "asset_add puts one fixed asset on the register with the rate, useful life and convention read off the bundled tax table (cost and residual in MINOR units: 600000 is 6,000.00 PLN), asset_schedule builds its depreciation schedule per year or per month, asset_journal gives one month's debit and credit lines, asset_dispose books a sale or a write-off against net book value, and asset_report values the register. The scheme is derived from the shared business profile currency (business_set on /mcp/invoice) when you leave it out, and every answer says so in words rather than pretending it is a stored fact.",
      "outputs": "JSON only. There is no document to render and nothing is written outside your own register. asset_journal returns the expense_add ARGUMENTS for the month, one payload per currency, to pass to /mcp/expense-tracker yourself: this endpoint never appends to that ledger, because the expense server's id counter, category rules and VAT split all live inside its own expense_add handler.",
      "free_limits": "10 assets in the register; asset_list, asset_schedule and asset_dispose are free and unlimited on every tier, because a depreciation rate is published by a tax authority and an asset already on the register has to be able to leave it. asset_journal and asset_report are Pro",
      "notes": "the rates are BUNDLED tables, not a feed: pl (the annual depreciation rate annex to the CIT act of 15 February 1992, keyed to the KST 2016), uk (Capital Allowances Act 2001 writing down allowances) and us (IRS Publication 946 MACRS GDS). Nothing is fetched, so the same asset depreciates the same way on every run, and every answer carries the header saying which instrument the rate came from and when it was read. A category that could not be stated with confidence from the published text was OMITTED rather than guessed, so an unbundled category is REFUSED by name rather than matched to a near neighbour - and never by substring, because \"land\".includes(\"and\") would have priced equipment at the land row's 0 percent in silence. The schedule periods sum EXACTLY to cost less residual to the minor unit, with the rounding remainder placed on the last period rather than dropped, and a residual over cost is refused. Currencies are never added together: there is no exchange rate in this endpoint"
    },
    {
      "name": "statement-of-account",
      "url": "https://mcp.zovo.one/mcp/statement-of-account",
      "tools": [
        "statement_build",
        "statement_aging",
        "statement_text",
        "statement_pdf",
        "dunning_text",
        "statements_report",
        "license_status",
        "license_activate"
      ],
      "mode": "reads three stores, writes none of them",
      "how": "statement_build states one client's account for a period (opening balance, invoices issued, payments received, credit notes, deposits applied, closing balance), statement_aging breaks what is owed into 0-30, 31-60, 61-90 and over 90 days past the due date AS AT a date you choose, and dunning_text writes the chaser at level 1 friendly, 2 firm or 3 final demand. Every figure is read from the same per-token data your /mcp/invoice, /mcp/billing-docs and /mcp/deposits endpoints serve; the issuer and the bank details a chaser prints come from the shared business profile (business_set on /mcp/invoice).",
      "outputs": "statement_pdf returns a print-ready HTML statement behind a one-hour download link (there is no PDF renderer on Workers, so it is the same A4 layout the credit note and the deposit statement use, titled STATEMENT OF ACCOUNT). statement_text and dunning_text return the pasteable text in the answer and the same text as a .txt download link.",
      "free_limits": "5 distinct statements per calendar month, counted by client, period and currency, so re-rendering one you already built is free forever in all three renderings; statement_aging is free and unlimited on every tier, because 'who owes me money' is the question this endpoint exists for. statement_pdf, dunning_text level 3 and statements_report are Pro",
      "notes": "the three sibling stores are hydrated READ-ONLY and never written: this endpoint reports on books it does not own. A store that is missing is not an error and reads as zero rows; a store that is present and did not parse is reported as unreadable with a sentence naming which figure is incomplete, rather than being read as an empty book, and an unreadable invoice ledger refuses every tool by name. paid_minor on the invoice is the authority and the payment rows are only the attribution, so a deposit already applied is broken out rather than counted twice, and deposit money still HELD is a memo line and never in the balance. Aging is as at the date asked for in both directions - an invoice issued after it is not on the books, a payment made after it has not happened - and due today is not overdue. Currencies are never added together, and no dunning level states a late fee, an interest rate or a legal cost, because this endpoint holds no contract terms and no jurisdiction"
    },
    {
      "name": "cash-book",
      "url": "https://mcp.zovo.one/mcp/cash-book",
      "tools": [
        "ledger_build",
        "trial_balance",
        "ledger_lines",
        "month_close",
        "ledger_export_csv",
        "ledger_report",
        "license_status",
        "license_activate"
      ],
      "mode": "reads six stores, writes none of them",
      "how": "ledger_build derives one double-entry ledger for one period in one currency from the same per-token data your /mcp/invoice, /mcp/billing-docs, /mcp/deposits, /mcp/expense-tracker, /mcp/bank-statement and /mcp/asset-register endpoints serve; trial_balance proves the debits equal the credits to the minor unit; ledger_lines lists the legs, filtered by account, source server, source document or date; month_close names what the month leaves unposted and records a trial balance snapshot. Every line carries the server, the document id and the document date it came from.",
      "outputs": "JSON, plus ledger_export_csv, which returns the period's legs as RFC 4180 CSV behind a one-hour download link (text/csv, one row per leg). Nothing is ever written into any of the six books: no payment, no status, no counter.",
      "free_limits": "3 distinct periods per calendar month, metered by from, to and currency, so rebuilding a period already in the register is free forever; trial_balance and ledger_lines are free and unlimited on every tier, because whether the books add up is the question this endpoint exists for and a free tier that hides the answer is a demo. month_close, ledger_export_csv and ledger_report are Pro",
      "notes": "the bank import posts NOTHING. A bank line and a payment record are one movement seen twice, so cash is posted from the DOCUMENTS, which are the only rows carrying a second leg, and each bank row is matched to a posted cash movement of the same amount, the same direction and a date within three days, as evidence written onto the line as bank_ref. On the worked month that is 99.6 percent duplication: posting the import as well moves cash from -10,543.00 to -21,111.00 EUR and the trial balance still comes to zero, because every duplicated receipt arrives with its own contra. What is left after matching - a bank debit with no expense behind it, a posted movement with no bank line - is the entire reason to import a statement. Nothing is ever balanced with a plug: an entry whose own legs do not add up is posted as the document states it and the difference is raised by name. A deposit applied to an invoice never touches cash, because the cash arrived when the deposit did. Expense VAT comes OUT of a VAT-inclusive gross, never on top of it. An open purchase order is a memo and is never posted. This ledger opens at nothing: a balance here is the period's MOVEMENT, because an opening figure nobody can walk back to a document is the first invented number in a set of books. Currencies are never added together. A store that is missing reads as zero rows and says so; a store that is present and did not parse is reported as unreadable, distinctly, because a figure that could not be computed is not a figure of zero and a ledger short one whole store still balances perfectly"
    },
    {
      "name": "amortization",
      "url": "https://mcp.zovo.one/mcp/amortization",
      "tools": [
        "loan_create",
        "loan_schedule",
        "loan_repay_early",
        "loan_journal",
        "loan_list",
        "loans_report",
        "license_status",
        "license_activate"
      ],
      "mode": "arithmetic on terms you record",
      "how": "loan_create records one loan or lease from its terms (principal, fees and balloon in MINOR units, the rate in nominal annual basis points) and returns its id, its level payment and its effective annual rate; loan_schedule builds every period - opening balance, payment, interest, principal, closing balance - with the total interest; loan_repay_early prices settling or overpaying at a period, gross and net of the lender's penalty; loan_journal gives the double entry for one period or one month; loans_report values the debt per currency and names the next payment due.",
      "outputs": "JSON only. NO tool here writes a file, so there is nothing to download and nothing is published. loan_journal returns the expense_add ARGUMENTS for the interest alone, to pass to /mcp/expense-tracker yourself: this endpoint posts to no ledger, because the expense server's id counter, category rules and VAT split live inside its own expense_add handler.",
      "free_limits": "3 loans in the register; loan_schedule and loan_list are free and unlimited on every tier, because what a payment is made of is the question this endpoint exists for and a free tier that hides it is a demo. loan_repay_early, loan_journal and loans_report are Pro",
      "notes": "the payment never varies and the last period absorbs the rounding residual in its interest and principal SPLIT, not in the payment, so every payment is the amount on the agreement and the closing balance reaches the balloon, or zero, exactly. Compounding and payment frequency are two different clocks: the rate for one payment period is the equivalent rate taken through the compounding clock, never the nominal rate divided by the number of payments, which is worth about 1 percent of the interest on a one-year loan in the lender's favour and is invisible in a quote. NO SCHEDULE IS STORED - only the terms are, and every row is derived on the call, because a stored schedule is a second copy of what the rate and the term already decide and the copy is the one that gets believed after somebody edits the rate. A level payment rounded once can clear the debt before the term ends, and the schedule STOPS where the debt does rather than filling out the term with rows the borrower does not owe. Fees are paid at drawdown and are not interest; a balloon is due WITH the last payment and never inside it. Only the interest is an expense: booking the whole payment overstates the cost of the business by the principal every period and still reconciles against the bank. Nothing is posted from here, and currencies are never added together"
    },
    {
      "name": "petty-cash",
      "url": "https://mcp.zovo.one/mcp/petty-cash",
      "tools": [
        "float_open",
        "topup_record",
        "voucher_add",
        "voucher_delete",
        "reconcile",
        "replenish_request",
        "float_report",
        "license_status",
        "license_activate"
      ],
      "mode": "a float you keep, on your own token",
      "how": "float_open opens a petty cash tin on the imprest system - the amount the tin is topped back up to at every replenishment, in whole MINOR units, so 50000 is EUR 500.00. voucher_add records one receipt paid out of it, voucher_delete removes one entered wrongly, topup_record records cash physically going back in, reconcile counts the tin against the paperwork, replenish_request works out the cheque that restores the imprest and float_report states every float against its imprest with the history of what the counts found.",
      "outputs": "JSON only. NO tool here writes a file, so there is nothing to download and nothing is published. replenish_request returns the expense_add ARGUMENTS per category, to pass to /mcp/expense-tracker yourself, and the double entry in /mcp/cash-book's own account ids: this endpoint posts to no ledger and no expense book, because the expense server's id counter, category rules and VAT split live inside its own expense_add handler.",
      "free_limits": "1 float and 20 vouchers a calendar month; reconcile and voucher_delete are free and unlimited on every tier, because whether the cash in the tin matches the paperwork is the question this endpoint exists for and a free tier that withholds the answer is a demo. replenish_request and float_report are Pro",
      "storage": "512 KB of floats and vouchers per token",
      "notes": "the replenishment is IMPREST MINUS BALANCE and never the sum of the vouchers. The two differ by exactly what the counts found over or short, and reimbursing the voucher total restores the float that much light for good, every cycle, while every reconciliation still reports a clean difference. NO BALANCE IS STORED - the imprest, the top-ups, the counts and the vouchers decide it on the call, because a stored balance is the copy that gets believed after somebody deletes a voucher. A count is a FACT, so it moves the book balance and the difference is carried forward as a cash_over_short line rather than re-reported at every later count. A float is cash in a tin: a voucher larger than the balance is refused, and so is a back-dated one that would leave any LATER day negative, named by the day it breaks rather than the day it was typed. A voucher already covered by a count cannot be deleted, and a byte-identical one is refused by id unless duplicate_ok says the same thing really was bought twice. Under the imprest system petty_cash does not move: a replenishment credits cash and debits the expenses, and the float account is not in that journal at all. The chart of accounts is IMPORTED from /mcp/cash-book rather than restated, so a category spelled three ways is one account and no rename there can leave this endpoint posting to an account that ledger does not have. Currencies are never added together"
    },
    {
      "name": "work-order",
      "url": "https://mcp.zovo.one/mcp/work-order",
      "tools": [
        "work_order_create",
        "work_order_add_line",
        "work_order_status",
        "work_order_get",
        "work_order_list",
        "work_order_delete",
        "completion_report_text",
        "completion_report_pdf",
        "work_order_invoice_payload",
        "work_orders_report",
        "license_status",
        "license_activate"
      ],
      "mode": "your own board, plus the invoice client records read-only",
      "how": "work_order_create opens a job against a client already in your /mcp/invoice client records, at a site address, with a requested date and a priority; work_order_add_line records the hours (kind labour, with the rate in MINOR units) and the parts fitted (kind parts, with the unit cost in MINOR units and an optional markup percent); work_order_status walks the job draft to scheduled to in_progress to done to invoiced, one step at a time, each step carrying its own date; completion_report_text and completion_report_pdf are the document the customer signs; work_order_invoice_payload hands back invoice_create arguments; work_orders_report values the board.",
      "outputs": "JSON, plus two documents: completion_report_text returns the report inline AND as a .txt download link, and completion_report_pdf returns the A4 report as an HTML print-to-PDF download (there is no PDF renderer on Workers). out_path is a NAME here, not a path: it only decides what the downloaded file is called.",
      "free_limits": "5 OPEN work orders, counted on the board rather than on the calendar, so closing a job frees its slot and work_order_delete on a draft with no lines is free on every tier; completion_report_text is free, because the completion report is the one document the customer signs. completion_report_pdf, work_order_invoice_payload and work_orders_report are Pro",
      "storage": "512 KB of work orders per token",
      "notes": "the markup goes on the UNIT cost and never on the line total. Seven parts at 1299 minor units with 15 percent on top is 1494 a unit and 10,458 on the line; marking up the line total is 10,457, and only the first is a figure an invoice can reproduce, because /mcp/invoice rounds a unit price into minor units first and computes the line from that stored value. The payload's totals are computed by the invoice server's OWN computeTotals over the payload's own items, so there is no second implementation to disagree. NO TOTAL IS STORED - the lines decide it on every call, because a stored total is the copy that gets believed after somebody edits a line. The status machine moves one step forward at a time: a skipped step is refused naming the step that IS next, because every step carries its own date and a job that reached invoiced without done was never marked finished. A backwards step is refused, because a job that has to go back is a new work order. Hours are counted on the LINE date, not on the order date, so a February call worked in March logs its hours in March. This endpoint creates NO invoice and marks nothing: work_order_invoice_payload returns arguments, and the invoice client records it reads are hydrated READ-ONLY and never written. A client name that matches no invoice client record is refused unless you pass an address, because a misspelling would raise an invoice with an empty BILL TO block. A labour rate is never improvised: no default hourly rate exists in the shared profile today, so rate_minor is refused by name rather than invented onto a report the customer signs"
    },
    {
      "name": "catalogue",
      "url": "https://mcp.zovo.one/mcp/catalogue",
      "tools": [
        "sku_set",
        "sku_get",
        "sku_list",
        "sku_delete",
        "rate_set",
        "rate_get",
        "lines_resolve",
        "price_list_text",
        "price_list_pdf",
        "catalogue_report",
        "license_status",
        "license_activate"
      ],
      "mode": "your own price list",
      "how": "sku_set records a product with its unit and a price row carrying the day that price comes into force, per currency and per tier; sku_get and sku_list read the price in force on any date; rate_set and rate_get do the same for hourly labour rates by role; lines_resolve turns a list of sku and role lines into invoice_create-ready and quote_create-ready items priced as of each line's date; price_list_text and price_list_pdf print the list a customer is sent; catalogue_report names the rows in force, the rows a later row already replaces and the SKUs with no price in your default currency.",
      "outputs": "JSON, plus two documents: price_list_text returns the list inline AND as a .txt download link, and price_list_pdf returns the A4 list as an HTML print-to-PDF download (there is no PDF renderer on Workers). out_path is a NAME here, not a path: it only decides what the downloaded file is called.",
      "free_limits": "25 SKUs, and one price tier; lines_resolve and price_list_text are free and unlimited on every tier, because pricing a line is the one thing the invoice and quote servers come here for and a catalogue nobody can read is not a catalogue. Deleting an unused SKU is free, so the cap is one you can get back under. price tiers other than standard, price_list_pdf and catalogue_report are Pro",
      "storage": "512 KB of SKUs, rate cards and the usage register per token",
      "notes": "NO CURRENT PRICE IS STORED. A SKU holds its price ROWS with the day each came into force, and the price on a date is the latest valid_from at or before it, worked out on the call, because a stored current price is the copy still being quoted a month after the rise. A date before every row has no price and is refused rather than priced off the earliest row. The two payloads are in DIFFERENT SCALES on purpose, because the two servers take them differently: invoice_create takes unit_price in MAJOR units and quote_create takes unit_price_minor in MINOR units, prices are held in minor units as the only lossless form, and swapping the two payloads misprices the job by 100x. The money and VAT arithmetic is /mcp/invoice's own computeTotals, imported rather than copied, so a resolved line and the invoice raised from it cannot disagree by a minor unit. An unknown code is refused BY NAME and never priced, and a partial name matching more than one product is refused with the list rather than resolved to the first. This endpoint creates NO invoice and NO quote: lines_resolve returns arguments, and no sibling store is read or written"
    },
    {
      "name": "change-order",
      "url": "https://mcp.zovo.one/mcp/change-order",
      "tools": [
        "change_order_create",
        "change_order_add_line",
        "change_order_status",
        "change_order_get",
        "change_order_list",
        "change_order_delete",
        "contract_value",
        "change_order_document",
        "change_order_invoice_payload",
        "license_status",
        "license_activate"
      ],
      "mode": "your own change orders, against a quote or work order named by its id",
      "how": "change_order_create raises a change order against a quote or work order by its id, with the client, a one-line title, the date and, on the first change order against that reference, the original contract value in whole MINOR units, which every later one inherits; change_order_add_line records each added or removed line with its quantity and unit price, or a changed line with the old and the new quantity and price, each with a reason and a date; change_order_status walks it draft to sent to approved or rejected, or draft or sent to void, each step dated; change_order_get and change_order_list read them; contract_value states the running value of one reference; change_order_document is the approval sheet the client signs; change_order_invoice_payload hands back invoice_create and quote_create arguments for the approved delta.",
      "outputs": "JSON, plus one document: change_order_document returns the approval sheet inline AND as a .txt download link valid for one hour. change_order_invoice_payload returns the approved delta as invoice_create arguments in MAJOR units and quote_create arguments in MINOR units, and creates neither.",
      "free_limits": "5 OPEN change orders (draft and sent), counted on the pile the client has not answered rather than on the calendar, so approving, rejecting or voiding one frees its slot, and change_order_delete on a draft with no lines is free on every tier; contract_value is free and unlimited, because the running value is the question this endpoint exists for. change_order_document and change_order_invoice_payload are Pro",
      "storage": "512 KB of change orders per token",
      "notes": "the original contract value is stated ONCE per reference and inherited by every later change order against it; a call that states a different figure is refused, because a contract with two original values has two running values and the customer sees whichever was typed last. NO DELTA AND NO RUNNING VALUE IS STORED: the lines and the status history decide both on every call. The running value is the original plus APPROVED deltas only; draft and sent deltas are shown as pending and never added in, and rejected and void ones count for nothing. A changed line becomes TWO items on the invoice payload, a reversal of the old quantity at the old price and the new quantity at the new price, never one net item, so both figures reproduce on a calculator; a removed line is a negative quantity at the price it was booked at. The two payloads are in DIFFERENT SCALES on purpose: invoice_create takes unit_price in MAJOR units and quote_create takes unit_price_minor in MINOR units, and swapping them misprices the delta by 100x; quote_create.ready is false whenever any quantity is not positive, because that server refuses one. Lines are added only while a change order is a draft, a draft cannot be approved unsent, and every status date must follow the last. This endpoint opens neither the quotes store nor the work-order store, creates NO invoice and NO quote, and the money arithmetic is /mcp/invoice's own computeTotals, imported rather than copied"
    },
    {
      "name": "bill-of-sale",
      "url": "https://mcp.zovo.one/mcp/bill-of-sale",
      "tools": [
        "sale_create",
        "sale_update",
        "sale_finalize",
        "sale_list",
        "sale_get",
        "sale_delete",
        "sale_render",
        "sale_summary",
        "license_status",
        "license_activate"
      ],
      "mode": "your own sales book",
      "how": "sale_create records the sale - buyer, seller, the item with its VIN, serial or IMEI where it has one, the price in whole MINOR units (120000 is USD 1,200.00) and the date - and returns the BOS-YYYY-NNNN number of the draft; sale_update changes anything on the draft; sale_finalize freezes it into the signing copy; sale_render prints it as Markdown, self-contained HTML or both, with signature lines for seller and buyer; sale_summary totals the book per currency. The seller defaults to the shared business profile (business_set on /mcp/invoice).",
      "outputs": "sale_render returns both renderings in the answer AND as download links valid for one hour, the HTML laid out for print-to-PDF; out_path is a NAME here, not a path: it is only the stem the downloaded files carry. Drafts render with a DRAFT watermark so a review copy cannot be signed by mistake.",
      "free_limits": "10 drafts and 5 finalized documents, so a real side-business year rather than a trial; rendering, reading, listing and deleting are never metered",
      "storage": "512 KB of bills of sale per token",
      "notes": "a byte-identical sale to the same buyer is refused unless duplicate_ok says the same item really was sold twice. A finalized document cannot be edited and sale_delete on one needs confirm_finalized true, because the finalized copy is the local copy of a record the buyer may already hold; the BOS number is never reissued, so a gap in the series is the record that a document was deleted. The as-is clause is on by default - the norm for second-hand sales - and a warranty passed alongside it stands, because the clause reads 'except as stated in this document'. The document is a generic template, not legal advice, and says so on its face. Currencies are never added together"
    },
    {
      "name": "credit-note",
      "url": "https://mcp.zovo.one/mcp/credit-note",
      "tools": [
        "credit_note_create",
        "credit_note_update",
        "credit_note_finalize",
        "credit_note_list",
        "credit_note_get",
        "credit_note_delete",
        "credit_note_render",
        "credit_note_summary",
        "license_status",
        "license_activate"
      ],
      "mode": "your own credit note book",
      "how": "credit_note_create issues the note against an invoice reference or standalone - recipient, reason (returned_goods, overcharge, discount_correction, service_issue, other), lines with quantity, unit price in whole MINOR units and tax rate, and the currency - and returns a DRAFT with a draft id no client sees; credit_note_update revises the draft; credit_note_finalize burns the final CN-YYYY-NNNN number and freezes the note; credit_note_render returns the document inline as Markdown or as a self-contained printable HTML page; credit_note_summary totals what you have credited per currency, per reason and per month.",
      "outputs": "JSON and the inline document. NO tool here writes a file, so there is nothing to download and nothing is published: credit_note_render's answer IS the document.",
      "free_limits": "10 finalized credit notes, lifetime. Drafts, edits, deletion of drafts, listing, rendering and the totals are free and unlimited, because a free tier that withholds the rendered document is a demo. The free tier stamps a one-line footer on the render",
      "storage": "512 KB of credit notes per token",
      "notes": "the number is burned only at finalize, so the final series never has a gap from a discarded draft, and a finalized note can neither be edited nor deleted - it is the document the client may have seen. A credit note that credits a total of zero is refused. A byte-identical note is refused unless duplicate_ok says the same credit really is issued twice. The line gross is quantity x unit price rounded half-up once, tax is rounded half-up per line, and the totals are plain sums of the rounded lines, so the printed lines always reproduce the total. Currencies are never added together"
    },
    {
      "name": "job-card",
      "url": "https://mcp.zovo.one/mcp/job-card",
      "tools": [
        "job_card_create",
        "job_card_log_labor",
        "job_card_log_material",
        "job_card_update_status",
        "job_card_list",
        "job_card_get",
        "job_card_print",
        "job_card_delete",
        "job_card_summary",
        "license_status",
        "license_activate"
      ],
      "mode": "your own board of job cards",
      "how": "job_card_create opens a card for one job - client, site, what the job is, the currency, the scheduled date - and returns its JC-YYYY-NNNN number; job_card_log_labor records a worker's day (hours to the hundredth, the hourly rate in whole cents) and job_card_log_material records what went in (quantity to the thousandth, the unit cost in whole cents), each line valued once at log time, hours x rate or quantity x unit cost, rounded half-up to the cent; job_card_update_status walks the card open to in_progress to done to invoiced to archived, one dated step at a time; job_card_print renders the card with a client signature line; job_card_summary totals a day or a Monday-to-Sunday week, per currency.",
      "outputs": "JSON, plus the printable card: job_card_print returns it INLINE as Markdown or as self-contained HTML that references nothing external. NO tool writes a file, so there is nothing to download.",
      "free_limits": "10 active cards; archiving a finished job frees its slot. Logging, the running totals, the printable card and the summaries are never metered: the card is the record of what the job cost",
      "storage": "512 KB of job cards per token",
      "notes": "every line value is computed ONCE, when the entry is logged, and totals are the sums of the stored lines, so a total can never drift from the lines it is made of. A skipped or backwards status step is refused naming the step that IS next, because every step carries its own date; a card with labor or materials logged cannot be deleted - archive it, which keeps the record and frees the slot. A future-dated entry is refused: work cannot have been done yet. The JC number is never reissued. Currencies are never added together"
    },
    {
      "name": "dunning-letters",
      "url": "https://mcp.zovo.one/mcp/dunning-letters",
      "tools": [
        "invoice_register",
        "payment_record",
        "letter_render",
        "letter_sent",
        "overdue_list",
        "aging_summary",
        "chase_today",
        "invoice_status",
        "invoice_delete",
        "license_status",
        "license_activate"
      ],
      "mode": "your own chase register",
      "how": "invoice_register starts chasing an unpaid invoice - client, invoice reference, the amount in whole MINOR units (125000 is USD 1,250.00), the currency and the due date - and returns the three-letter escalation schedule: reminder 1 falls due at due + the first gap, reminder 2 at due + the second, the final notice at due + the third (default 7, 14, 21 days), due-anchored and sequential, so a later letter never leapfrogs an unsent earlier one. letter_render writes the letter for the stage currently due as Markdown or self-contained printable HTML; letter_sent records that you sent it; payment_record logs money received and closes the ladder when the balance is covered; chase_today, overdue_list, aging_summary and invoice_status read the register.",
      "outputs": "JSON and the inline letter. NO tool writes a file, so there is nothing to download: letter_render's answer IS the letter, and NOTHING is emailed or sent anywhere - this server renders the letter text, and sending it is your act.",
      "free_limits": "3 active unpaid invoices chased at once; an invoice that gets paid frees its slot. The letters, the aging and the history are never metered: the cap is on how many chases run at once",
      "storage": "512 KB of chase register per token",
      "notes": "NO BALANCE IS STORED: what is still owed is derived from the invoice amount and the recorded payments on every call. The sender's name and email come from the shared business profile (business_set on /mcp/invoice); without one the letters are signed [Your name] and say so. A late fee is stated only when you register late_fee_percent_per_month, and then as simple interest, pro-rata on a 30-day month, rounded once to the minor unit - no letter invents a fee, an interest rate or a legal cost, and the final notice says plainly that what a before-action letter must contain varies by jurisdiction. The money formatting is /mcp/asset-register's own formatMoney, imported rather than copied. Currencies are never added together"
    },
    {
      "name": "checklist",
      "url": "https://mcp.zovo.one/mcp/checklist",
      "tools": [
        "checklist_create",
        "checklist_item_add",
        "checklist_item_remove",
        "checklist_show",
        "checklist_list",
        "checklist_delete",
        "run_start",
        "run_check",
        "run_show",
        "run_list",
        "run_sign_off",
        "run_status",
        "run_report",
        "run_delete",
        "license_status",
        "license_activate"
      ],
      "mode": "your own checklists, and the dated, signed runs of them",
      "how": "checklist_create builds a reusable checklist (a name, a category, an optional description) and returns its CL-NNNN id; checklist_item_add adds the steps, each with a section, a required flag and an optional note; run_start starts a dated run against a job - a title, an optional reference, an optional date - and returns its RUN-YYYY-NNNN id with the steps COPIED in; run_check answers one step pass, fail or na with who and when; run_show reads the whole run with what is outstanding; run_sign_off freezes a complete run with the signer's name; run_report produces the document; run_status reopens a complete run or abandons one; checklist_list, checklist_show and run_list read.",
      "outputs": "JSON, plus the run report: run_report returns it as plain text on every tier, and Pro passing out_path also gets it back as a .txt download link valid for one hour. out_path is a NAME here, not a path: it only decides what the downloaded file is called.",
      "free_limits": "3 checklists, and unlimited runs of them - what is metered is how many DIFFERENT checklists you keep, not how many jobs you check. Every read, every progress figure and the report TEXT are free on every tier. Writing the report to a file with out_path is Pro",
      "storage": "512 KB of checklists and runs per token",
      "notes": "A run COPIES its checklist's items when it starts, with the checklist version recorded: editing the checklist afterwards never changes a run already under way, because a list somebody ticked and signed has to be the list they actually saw. NO progress figure is stored: the counts, what is outstanding and whether a run can be signed off are derived on every call. na means the step did not apply - it counts as ANSWERED and never as passed. complete is a reading, never set by hand: a run becomes complete when its last step is answered and goes back to open when a step returns to pending. Sign-off is refused while a required step is unanswered or failed unless force is true, and either way the exceptions stay on the record and print on the report. A signed-off run cannot be edited, reopened or deleted - it is the record of what somebody put their name to - and the CL and RUN id series are never reissued. The name at the top of a printed report comes from the shared business profile (business_set on /mcp/invoice); no sibling store is ever opened"
    },
    {
      "name": "packing-list",
      "url": "https://mcp.zovo.one/mcp/packing-list",
      "tools": [
        "packing_list_create",
        "packing_expect",
        "carton_add",
        "pack_item",
        "unpack_item",
        "packing_list_show",
        "packing_list_list",
        "carton_report",
        "packing_shortfall",
        "packing_list_status",
        "packing_slip",
        "packing_list_delete",
        "license_status",
        "license_activate"
      ],
      "mode": "your own packing lists, each against the order it ships on",
      "how": "packing_list_create opens a list against an order reference - WO-, INV-, Q- or a plain order, inferred when omitted - with the consignee and an optional ship-to, and returns its PL-YYYY-NNNN number; packing_expect declares one line the order says should ship; carton_add adds a carton with its empty weight in WHOLE GRAMS and optionally all three dimensions in WHOLE CENTIMETRES; pack_item puts a quantity of one item into a named carton; packing_shortfall reads ordered against packed, line by line; carton_report weighs every carton and the shipment - net, gross, volumetric, chargeable; packing_list_status moves draft to packed to shipped, recording carrier and tracking; packing_slip produces the document; packing_list_show and packing_list_list read.",
      "outputs": "JSON, plus the packing slip: packing_slip returns it as plain text on every tier, and Pro passing out_path also gets it back as a .txt download link valid for one hour. out_path is a NAME here, not a path: it only decides what the downloaded file is called.",
      "free_limits": "3 OPEN packing lists at once, counted on the shipments in flight rather than on the calendar: marking one shipped or cancelling it frees its slot, and deleting a draft is free. The shortfall, the carton weights and the slip TEXT are free on every tier. Writing the slip to a file with out_path is Pro",
      "storage": "512 KB of packing lists per token",
      "notes": "the slip carries NO PRICES, and that is the point of it: it travels inside the box, and the consignee's warehouse is not the party that sees what the goods cost - the invoice against the same order is a different document, on /mcp/invoice. NO weight and NO shortfall is stored: the net, gross, volumetric and chargeable figures are derived on every call, mass in WHOLE GRAMS and dimensions in WHOLE CENTIMETRES throughout for the reason money is in minor units. A packed line with no unit_grams makes every net and gross figure a LOWER BOUND and says so; a carton with no dimensions makes the shipment's chargeable weight null, never a guess. Chargeable is the greater of gross and volumetric, volumetric at a divisor of 5000 (courier air), 6000 (IATA air) or 4000 (some road tariffs). A packed line with no ordered line is reported as not_on_order, never dropped. Shipping while lines are short needs force: true and the exceptions stay on the record; a shipped list cannot be edited, reopened or deleted - it is the record of what left the building. NOTHING is read from the quotes, work-order or invoice stores: what the order says is declared with packing_expect, so this endpoint opens no sibling document"
    },
    {
      "name": "delivery-schedule",
      "url": "https://mcp.zovo.one/mcp/delivery-schedule",
      "tools": [
        "delivery_schedule_create",
        "deliverable_add",
        "deliverable_status",
        "deliverable_delete",
        "delivery_schedule_get",
        "delivery_schedule_list",
        "delivery_schedule_delete",
        "late_report",
        "delivery_schedule_document",
        "milestone_payload",
        "license_status",
        "license_activate"
      ],
      "mode": "your own delivery schedules, each against a quote, work order or change order",
      "how": "delivery_schedule_create opens the schedule against a reference - WO-, CO- or a quote, inferred when omitted - with the reference document's own date, the client, a one-line title and the currency, and returns its DS-YYYY-NNNN number; deliverable_add adds one dated deliverable with an optional value in whole MINOR units net of VAT (90000 is EUR 900.00); deliverable_status walks each one planned to in_progress to delivered to accepted, every step dated; delivery_schedule_get and delivery_schedule_list read as at any as_of date; late_report says what has slipped as at a date, worst first, with value at risk per currency; delivery_schedule_document renders the sign-off document; milestone_payload hands back invoice_create and quote_create arguments for the delivered-and-accepted deliverables.",
      "outputs": "JSON, plus one document: delivery_schedule_document returns the schedule INLINE as plain text with counts as at a date and a sign-off block. NO tool writes a file, so there is nothing to download. milestone_payload returns invoice_create arguments in MAJOR units and quote_create arguments in MINOR units, and creates neither document.",
      "free_limits": "3 open schedules; a schedule stops counting once every deliverable on it is accepted, and deleting an empty one is free on every tier. late_report is free and unlimited, because what is late is the question this endpoint exists for. delivery_schedule_document and milestone_payload are Pro",
      "storage": "512 KB of delivery schedules per token",
      "notes": "NO status, NO lateness and NO total is stored: a deliverable holds its due date, its value and its dated status history, and the current status, the delivered and accepted dates, what is late and every total are derived on the call. Late is read against the as_of the caller passes, never the machine's clock: a deliverable is late once as_of is PAST its due date, and one due on as_of sits in due_today; a delivered deliverable is delivered_late or delivered_on_time by comparing dates, which no longer moves with as_of. One reference carries ONE schedule, because two would give two answers to what is late on it. No due date and no status move may fall before the reference document's own date, and a status history may not run backwards. The two payloads are in DIFFERENT SCALES on purpose: invoice_create takes unit_price in MAJOR units and quote_create takes unit_price_minor in MINOR units, and swapping them misprices the milestone by 100x; every unit price is a whole minor unit, so rounding_drift_minor is zero. A deliverable with no value_minor is not worth zero: it is counted apart and excluded BY NAME from the payload, never billed as zero. VAT falls back to the shared business profile's default_tax_rate (business_set on /mcp/invoice), the money formatting is /mcp/invoice's own formatMoney, imported rather than copied, and currencies are never added together. This endpoint opens no sibling store and creates NO invoice and NO quote"
    },
    {
      "name": "supplier-list",
      "url": "https://mcp.zovo.one/mcp/supplier-list",
      "tools": [
        "supplier_add",
        "supplier_list",
        "supplier_get",
        "supplier_update",
        "supplier_remove",
        "supplier_mark_reviewed",
        "supplier_due_review",
        "supplier_export",
        "license_status",
        "license_activate"
      ],
      "mode": "your own supplier directory",
      "how": "supplier_add records who you buy from - the name, what they supply, the contact, the payment terms, the lead time in days and notes - and returns its SUP-YYYY-NNNN number; supplier_list reads the directory A to Z with a category filter and a free-text search across every field; supplier_update changes only the fields you pass; supplier_mark_reviewed stamps the record as checked against reality; supplier_due_review is the report of what has gone stale, most overdue first, where a record never reviewed is always due; supplier_export hands the directory over as CSV or a Markdown table.",
      "outputs": "JSON, plus the exports: supplier_export returns the CSV or Markdown table INLINE in the answer. NO tool writes a file, so there is nothing to download.",
      "free_limits": "10 suppliers, with reading, updating, searching, review stamps and CSV export free and unlimited on every tier; removing one you no longer use frees its slot. Markdown export and the due-review report are Pro",
      "storage": "512 KB of supplier records per token",
      "notes": "a second record carrying a name already in the directory is refused, because two records of one supplier cannot be told apart; supplier_update changes the record that exists. A partial name matching more than one supplier is refused with the candidates rather than resolved to the first. The SUP number is never reissued, so a gap in the series is the record that a row was removed. This endpoint opens no sibling store and reads no profile"
    },
    {
      "name": "service-agreement",
      "url": "https://mcp.zovo.one/mcp/service-agreement",
      "tools": [
        "agreement_create",
        "agreement_get",
        "agreement_list",
        "agreement_update_status",
        "clause_library",
        "agreement_render",
        "agreement_checklist",
        "license_status",
        "license_activate"
      ],
      "mode": "your own agreements book",
      "how": "agreement_create writes the agreement before the work starts - the two parties, the scope of services, the deliverables, the rate in whole cents (8500 is 85.00) with its unit (hour, day or project), the payment terms, start and end dates, a termination notice period, a liability cap and the governing jurisdiction - stores it, and returns it rendered as Markdown with a signature block, numbered SA-YYYY-NNNN; agreement_checklist is the before-you-send-it pass, listing missing fields and flagging one-sided gaps neutrally; agreement_update_status moves it draft to sent to signed to expired, one dated step at a time; clause_library lists the five built-in clauses (IP assignment, mutual confidentiality, late payment interest, kill fee, revision rounds); agreement_render produces the document for signing.",
      "outputs": "JSON and the inline document. NO tool writes a file, so there is nothing to download: agreement_render's answer IS the agreement, as Markdown or as self-contained printable HTML that references nothing external.",
      "free_limits": "3 active agreements, with reading, listing, the checklist and Markdown rendering free and unlimited on every tier; an agreement stops counting the moment it expires, so expiring a finished engagement frees its slot. The full clause texts and the print-ready HTML are Pro",
      "storage": "512 KB of agreements per token",
      "notes": "every render carries a one-line note that it is a template, not legal advice - a generic starting point whose terms a lawyer in the governing jurisdiction should read. The status machine moves one step at a time: a skipped step is refused naming the one step that is next, a step dated before the step before it is refused so the history reads as a timeline, and expired is final. An end date before the start date is refused, as is a clause id the library does not carry. The SA number is never reissued. This endpoint opens no sibling store"
    },
    {
      "name": "maintenance-log",
      "url": "https://mcp.zovo.one/mcp/maintenance-log",
      "tools": [
        "asset_add",
        "maintenance_log",
        "maintenance_due",
        "asset_history",
        "maintenance_export",
        "asset_remove",
        "license_status",
        "license_activate"
      ],
      "mode": "your own equipment register",
      "how": "asset_add puts one piece of equipment on the register - name, serial or asset tag (unique across the register), location, currency - and returns its AST-YYYY-NNNN number; maintenance_log records the work: the day, what was done, the cost in whole cents (12000 is 120.00), who did it, and when the next service falls due, as next_due (a date) or interval_days (a number of days), never both; maintenance_due is the report - what is overdue and by how many days, what falls due within the next N days, what has no schedule - computed from the stored dates at call time; asset_history reads one asset's whole log with its total spend and spend per technician; maintenance_export hands a date range over as CSV or a Markdown summary per asset.",
      "outputs": "JSON, plus the exports: maintenance_export returns the CSV or Markdown INLINE in the answer. NO tool writes a file, so there is nothing to download.",
      "free_limits": "3 assets on the register, with logging, the per-asset history and CSV export free and unlimited on every tier; removing an asset frees its slot. The due report and the Markdown summaries are Pro",
      "storage": "512 KB of assets and log entries per token",
      "notes": "overdue is computed against today at the moment you ask, never stored, so the register cannot go stale: an interval is turned into a date once, when the work is logged. Work dated in the future is refused, and a next_due before the work date is refused. Costs are integer cents in the asset's own currency and a total spend is the sum of the stored entries, so it can never drift from the lines. An asset carrying a log cannot be removed without confirm: true, because removing it loses the record of work done; the AST number is never reissued. Currencies are never added together. This endpoint opens no sibling store"
    },
    {
      "name": "mileage-log",
      "url": "https://mcp.zovo.one/mcp/mileage-log",
      "tools": [
        "trip_add",
        "trip_list",
        "trip_remove",
        "rate_set",
        "rate_list",
        "mileage_summary",
        "mileage_export",
        "license_status",
        "license_activate"
      ],
      "mode": "your own mileage log",
      "how": "trip_add logs one drive - the date, where from and to, the distance in miles or km, the purpose, the category (business, medical, moving, charitable, personal) - and returns its TR-YYYY-NNNN number; rate_set records what one mile or km is worth for one category in one jurisdiction from a date forward, an effective-dated series rather than one global number; mileage_summary prices a date range (default the current calendar year) per category: the rate each trip earned, the one in force on its day, and the deductible amount totalled per currency; mileage_export is the CSV for the accountant.",
      "outputs": "JSON, plus the export: mileage_export returns the CSV INLINE in the answer. NO tool writes a file, so there is nothing to download.",
      "free_limits": "20 trips per calendar month, counted on the month of the trip date, so reconstructing last year's log at tax time does not consume this month's allowance; the list and the summary are never metered, and one rate per jurisdiction and category is free (overwriting it stays free). The year-over-year rate series and the CSV export are Pro",
      "storage": "512 KB of trips and rates per token",
      "notes": "NO rate ships with this endpoint and none of it is tax advice: the rates you set are your own figures to verify. A trip's amount is its distance times the rate in force on the day it was driven, rounded half-up to the cent, and every total is the sum of those rounded per-trip amounts, so the CSV reconciles line by line with the summary. Distances in miles and in km are kept apart and never added together; a trip whose unit differs from the rate's is converted first (1 mile = 1.609344 km exactly). A trip with no applicable rate is listed with the reason, never silently dropped, and the export refuses while any non-personal trip in the window is unpriced, so an accountant never receives a log with silent gaps. A future-dated trip is refused: it cannot have been driven yet. The TR number is never reissued"
    }
  ],
  "limits": {
    "request_body_bytes": 262144,
    "jsonrpc_batching": "not accepted - send one request object per POST",
    "stored_bytes_per_token_per_endpoint": {
      "default": 524288,
      "spreadsheet": 2097152,
      "docx": 2097152,
      "resume": 2097152,
      "pdf": 2097152,
      "calendar": 2097152,
      "image": 2097152,
      "bank-statement": 2097152,
      "zip": 2097152,
      "cash-book": 2097152,
      "currency": "no per-token storage"
    },
    "download_ttl_seconds": 3600,
    "idle_data_retention_days": 35
  },
  "one_click_install": "download <name>.mcpb from https://github.com/theluckystrike/mcp-servers/releases/latest and open it in Claude Desktop; no JSON and no terminal",
  "stdio_install": "git clone https://github.com/theluckystrike/mcp-servers.git, npm install, npm run build -w packages/mcp-license -w servers/<name>, then: claude mcp add <name> -- node /absolute/path/to/mcp-servers/servers/<name>/dist/index.js",
  "stdio_install_npm_pending": "claude mcp add <name> -- npx -y @theluckystrike/mcp-<name> - NOT WORKING YET: no @theluckystrike package is published, so this returns 404. Use one_click_install or stdio_install.",
  "remote_install": "claude mcp add --transport http <name> https://mcp.zovo.one/mcp/<name> --header \"Authorization: Bearer <token>\"",
  "remote_install_no_header": "claude mcp add --transport http <name> https://mcp.zovo.one/mcp/<name>/t/<token>",
  "source": "https://github.com/theluckystrike/mcp-servers"
}