MCP Server
DayZero exposes a Model Context Protocol (MCP) server that lets AI assistants — Claude, ChatGPT, Cursor, and other MCP-compatible clients — interact with your accounting data through natural language.
The server is mounted at /mcp and uses the Streamable HTTP transport (stateless: each request stands alone, with no server-side session). Authentication uses OAuth 2.1 — your client discovers the auth server, registers itself, and opens a browser for you to sign in to DayZero and approve access. No tokens to copy.
Just want to connect? Claude users can click Add DayZero to Claude — claude.ai opens the connector dialog prefilled; review it, click Add, and sign in. Every other client: add
https://mcp.ondayzero.com/mcpwith no credentials and you'll be prompted to sign in to DayZero in your browser and approve access. See Quick Connect below.
Note: REST API keys (
dz_…) from Settings → Developers authenticate the REST API only. They do not work on the MCP server — use the OAuth browser flow instead.
Quick Connect
The fastest path per client. Every row uses the same server URL — https://mcp.ondayzero.com/mcp — and ends in the same browser OAuth sign-in. Settings → Developers inside DayZero has one-click Add to Claude / Add to Cursor buttons and copy-paste snippets for the rest.
| Client | Fastest path |
|---|---|
| Claude (web, desktop & mobile) | Add DayZero to Claude — one click, prefilled connector dialog |
| Claude Code | claude mcp add --transport http dayzero https://mcp.ondayzero.com/mcp — see Connecting Claude Code |
| ChatGPT | Enable Developer mode, then add the URL as a connector — see Connecting ChatGPT |
| Codex (CLI, IDE extension & ChatGPT desktop app) | Two lines in ~/.codex/config.toml — see Connecting Codex |
| Cursor | Settings → MCP Servers → Add with the URL above, or the Add to Cursor button in DayZero — see Connecting Cursor |
On Claude Team/Enterprise plans only org owners can add custom connectors — send your admin the same link on the admin path:
https://claude.ai/admin-settings/connectors?modal=add-custom-connector&connectorName=DayZero&connectorUrl=https%3A%2F%2Fmcp.ondayzero.com%2FmcpDomain Profiles For Power Users
DayZero keeps the unified server at /mcp for general use and also exposes focused domain profiles for multi-server MCP setups. Each mount below core is one domain: the reads and the writes of the same records live together.
https://mcp.ondayzero.com/mcp/core(dayzero-core) — the default/mcpsurface as a mount: business picker, daily brief, the AR and AP happy paths, transaction review, close status, reportshttps://mcp.ondayzero.com/mcp/ar(dayzero-ar) — invoices from draft to paid, customers, credit memos, the AR snapshothttps://mcp.ondayzero.com/mcp/ap(dayzero-ap) — bills, vendors, vendor credits, AP approval routing, payment runs, aged payableshttps://mcp.ondayzero.com/mcp/inbox(dayzero-inbox) — the Bill Inbox: mail at the business's intake address (get_business_info.inbox_email), what reading each attachment found, drafts turned into bills, emailed receipts filed on their transactionshttps://mcp.ondayzero.com/mcp/banking(dayzero-banking) — transactions (categorize, split, bulk edit), bank accounts and balances, bank rules, receipts, transaction uploadshttps://mcp.ondayzero.com/mcp/counterparties(dayzero-counterparties) — naming rules and renames, merges, counterparty default ledgers, the counterparty registryhttps://mcp.ondayzero.com/mcp/ledger(dayzero-ledger) — chart of accounts, journal entries (including bulk upload and recurring), fixed assets and depreciation, prepaid amortization and tagshttps://mcp.ondayzero.com/mcp/close(dayzero-close) — close status and verification, accounting periods and sign-off, close packages and the publication gate, anomalies, the close-run trackerhttps://mcp.ondayzero.com/mcp/recon(dayzero-recon) — bank reconciliations, AI-match review, payment matching, Stripe payouts, external tie-outshttps://mcp.ondayzero.com/mcp/reports(dayzero-reports) — financial statements, generated reports, analytics, budgets, forecasts, models, exports, audit trailshttps://mcp.ondayzero.com/mcp/o2c(dayzero-o2c) — order to cash: pipeline deals, sales orders, customer contracts, job-costing projects, and bulk import for eachhttps://mcp.ondayzero.com/mcp/commerce(dayzero-commerce) — products, standard costs and COGS, inventory, Shopify, invoice posting ledgershttps://mcp.ondayzero.com/mcp/people(dayzero-people) — the people roster, org chart and payroll reconciliationhttps://mcp.ondayzero.com/mcp/credit(dayzero-credit) — the partner-credit book, credit lines and loans (read-only)https://mcp.ondayzero.com/mcp/automations(dayzero-automations) — workflows: the graph schema (describe_workflow_schema) and the tools a node may call, drafting, validating, testing and publishing (publishing needs a passing test'stest_run_hashand the user's approval; runs execute the published snapshot), running on DayZero's servers with anidempotency_key, polling a run, answering its approval steps, scheduleshttps://mcp.ondayzero.com/mcp/workers(dayzero-workers) — the agent workforce: the business's agent roles (list_agent_roles), their runs with what each agent is doing now and what waits on a person (list_agent_runs,get_agent_run), and handing a role a job, answering its question or stopping it (start_agent_run,answer_agent_run,stop_agent_run); a run's own writes are filed as proposed changes. Also SOPs from chat: the SOPs worth writing for the business (suggest_sops), drafting and editing one (create_sop,update_sop), setting it live, draft or retired with the person's approval (set_sop_status), and starting its team (build_team_from_sop; a person installs it on the SOP page)https://mcp.ondayzero.com/mcp/agents(dayzero-agents) — what this connection may do (get_connection_info: email, scopes, write access, bound business, staff grant), pending changes and approval rounds, the decision log, background jobs, client-portal requests and messages
Each profile keeps tools/list scoped to that domain (at most 40 tools, under strict hosted-client limits). Every mount also lists search_tools, call_tool, confirm_write, get_job_status, list_ledgers, upload_file and generate_upload_url, so a tool another mount carries is one search_tools + call_tool(name, arguments) away; call_tool applies the same permissions, dry_run and approval gate as calling the tool directly. Claude clients (claude.ai, Claude Code, Claude desktop) load tool schemas on demand, so on /mcp they are listed every tool they can call. Self-hosted deployments can force one profile process-wide with MCP_DOMAIN_PROFILE (for example MCP_DOMAIN_PROFILE=dayzero-ar).
Multi-Server Setup Examples
Use multiple MCP server entries when you want separate focused tool surfaces in one client session.
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"dayzero-core": {
"url": "https://mcp.ondayzero.com/mcp/core"
},
"dayzero-ar": {
"url": "https://mcp.ondayzero.com/mcp/ar"
},
"dayzero-ap": {
"url": "https://mcp.ondayzero.com/mcp/ap"
},
"dayzero-reports": {
"url": "https://mcp.ondayzero.com/mcp/reports"
},
"dayzero-banking": {
"url": "https://mcp.ondayzero.com/mcp/banking"
},
"dayzero-o2c": {
"url": "https://mcp.ondayzero.com/mcp/o2c"
},
"dayzero-recon": {
"url": "https://mcp.ondayzero.com/mcp/recon"
}
}
}Cursor: add one MCP server per profile in Settings → MCP Servers (same URLs above). Cursor will run OAuth for each server entry and keep tools separated by server.
ChatGPT: create one connector per profile under Settings → Connectors → Create using the profile URLs above.
GitHub Copilot / VS Code MCP: add each profile as a separate server in your MCP configuration (same URLs above) so tool discovery stays focused and below hosted limits. Add only the profiles you need; the example above is a starting set, and every other profile in the list works the same way.
What You Can Do
The MCP server exposes one tool per job across accounting domains; the Full tool reference below is generated from the live registry and lists every tool with its access level and approval gate. The table here groups the main workflows. Tools marked (write) mutate data and require write permission; everything else is a read-only query. Call search_tools with no query for a compact category map, or with a query to rank the tools for a job.
| Category | Highlights | Description |
|---|---|---|
| Discovery | list_my_businesses, find_business, get_business_info, get_connection_info, search_tools, search_entities, search / fetch (ChatGPT only) |
Find businesses and entities without knowing IDs upfront; find_business fuzzy-searches by name; get_connection_info reports the connection's scopes, write permission and bound business |
| Banking | list_bank_accounts, get_bank_balances, refresh_bank_balances (write) |
See connected bank accounts and current/available balances |
| Snapshots | get_daily_brief, get_ar_snapshot, get_aged_payables, get_ap_snapshot, get_payment_priority_suggestions, get_uncategorized_summary, get_month_end_package |
High-signal summaries — prefer these over paging huge lists |
| Chart of Accounts | list_ledgers, get_ledger, create_ledger, bulk_create_ledgers (write) |
Browse and inspect ledger accounts; add accounts one at a time or a whole list in one call (e.g. mirroring another system's chart before importing its history) |
| Transactions | list_transactions, get_transaction, update_transaction, mark_reviewed, categorize_transaction, recategorize_by_counterparty, mark_transactions_reconciled (write) |
Search, inspect, categorize, and mark bank lines reconciled |
| Invoices (AR) | create_invoice, update_invoice, finalize_invoice, send_invoice, mark_invoice_paid, void_invoice, list_invoice_payments, get_customer_statement, credit memos, payments (write) |
Full AR lifecycle, invoice payment history, and customer statement previews |
| Bills (AP) | create_bill, approve_bill, mark_bill_received, update_bill, cancel_bill, list_bill_payments, vendor credits, payments (write) |
AP approval, receive, payment workflows, and bill payment history |
| Order-to-Cash | list_deals, create_deal, update_deal, convert_deal_to_order, list_orders, create_order, update_order, advance_order_status, attach_order_document, list_contracts, create_contract, update_contract, link_invoice_to_contract, plus bulk_create_* / bulk_update_* for each (write except list/get) |
The whole pre-invoice chain: pipeline deal → sales order → countersigned contract → invoice. advance_order_status(target_status="countersigned") is what turns an order into a live contract. Working from a signed PDF: upload_file (base64 content) → extract_document_entities to read it → create_order with the line items → attach_order_document with the same s3_key. For more than a couple of rows always use the bulk_* variant — running them one at a time races on shared contract locks |
| Projects (job costing) | list_projects, get_project, create_project, update_project, bulk_create_projects, bulk_update_projects (write except list/get) |
Jobs that orders, contracts and invoices hang off; assign invoices to them with bulk_assign_invoices |
| Journal Entries | list_journal_entries, get_journal_entry, create_journal_entry, update_journal_entry (write) |
Read entry lists, inspect one entry, create journal entries, and fix an entry in place (the "fix the original entry" rule) |
| Customers & Vendors | list_*, get_*, create_*, update_*, export_dataset, bulk_create_vendors, bulk_create_customers (write) |
CRUD-style contact management plus CSV export/import |
| Counterparties | search_counterparty_registry, link_counterparty, unlink_counterparty, list_counterparty_defaults, export_counterparty_audit, create_counterparty_default, update_counterparty_default, delete_counterparty_default, bulk_create_counterparty_defaults, upload_file, generate_upload_url (write for link/unlink, default rules, and uploads) |
Registry search, link/unlink, default rules (merchant → ledger), audit export, and CSV bulk import (use upload_file for the s3_key) |
| Credit Memos & Vendor Credits | list_*, get_*, create_*, issue_*, apply_*, unapply_*, void_* (write) |
Full credit lifecycle for AR credit memos and AP vendor credits — create, issue, apply to / unapply from invoices and bills, and void |
| Tags, Budgets, Products | list_tags, list_budgets, get_budget, get_budget_vs_actual, list_products |
Supporting master data |
| Close & Quality | get_close_status, get_close_verification, list_anomalies, dismiss_anomaly, list_attention_items, mark_attention_read, month-end packages |
DayZero close intelligence: phased checklist, readiness score, explicit blockers, plus anomalies/inbox workflows |
| Periods & close sign-off | create_accounting_period, list_accounting_periods, get_accounting_period_settings, update_accounting_period_settings, record_period_sign_off, reopen_accounting_period (write except list/get) |
Open periods, record sign-offs, and reopen a closed period |
| Decisions & proposed changes | record_decision, list_decisions, update_decision, delete_decision, create_pending_change, list_pending_changes, get_pending_change (write except list/get) |
A log of dated rulings the categorizer follows, and a way to queue a previewed write for a person to approve in the app |
| Fixed assets & GL maintenance | create_fixed_asset, list_fixed_assets, get_fixed_asset, update_fixed_asset, place_asset_in_service, run_depreciation, dispose_asset, create_asset_category, amortize_transaction, create_recurring_journal_entry, list_recurring_templates (write except list/get) |
Depreciation, prepaid amortization and recurring entries (the ledger profile) |
| Audit & Oversight | get_entity_audit_trail, get_user_activity, get_activity_feed, analyze_audit_log |
Change history for an entity, what a user did ("what did Quincy do today?"), the business-wide activity feed, and AI analysis of unusual activity |
| Firm-wide | get_firm_client_overview, get_firm_user_activity |
For advisory-firm users: cross-client portfolio/AR-AP/work-queue overviews and one user's activity across all the firm's clients |
| Reports | list_report_types, generate_report, get_report, list_reports, get_financial_statement, email_report, export_dataset |
P&L, balance sheet, and other exports, plus whole-dataset pulls |
| Async Jobs | get_job_status, list_jobs, start_background_job, trigger_bulk_transaction_upload, trigger_bulk_je_upload, trigger_month_end_close (write except get_job_status and list_jobs) |
Start long-running workflows immediately and poll by job id |
| Reconciliation | list_reconciliations, get_reconciliation, start_reconciliation, get_unmatched, get_match_review, approve_match, reject_match, bulk_approve_matches, bulk_reject_matches, complete_reconciliation, download_reconciliation_pdf (write for start/approve/reject/complete) |
The full bank reconciliation workflow: start_reconciliation takes an uploaded statement (statement_s3_key) or source_type="plaid" for a bank feed with no file; review AI-suggested matches side by side, approve or reject them, and finish with the PDF |
| Analytics | get_financial_overview, get_top_expenses, get_cash_flow_totals, get_profit_trends, get_transaction_summary, compare_periods |
Server-side aggregations for analytical questions |
| Payroll, Shopify & models | apply_gusto_reconciliation, check_shopify_connection, get_shopify_posting_summary, import_model_workbook, build_model, refresh_model |
Gusto payroll reconciliation, Shopify posting checks, and importing an Excel model as a live dashboard |
| Credit (read-only) | get_credit_portfolio, list_credit_lines, get_credit_line, list_credit_loans |
The partner-credit book for funds and lenders; originations and payments stay on the REST API |
Modules the app has switched off (estimates, delayed charges, tax settings and payment terms, among others) have no MCP tools. Personal Gmail is not available over MCP either: a linked mailbox can be searched only by Regent in the DayZero app (see QuickBooks, Meta Ads, Gmail and MCP Connections).
You don't need to know your business ID upfront. The business_id parameter is optional on every tool — the server automatically resolves it:
- One business — selected automatically, zero friction.
- Multiple businesses — clients that support elicitation show a scope picker (firm-wide vs a specific business) as a native dropdown; other clients get your business list so the assistant can ask which one to use. Firm users with many clients can call
find_business("name")to fuzzy-search for the right ID. - Explicit ID — you can always pass a
business_iddirectly if you prefer.
For cross-client questions ("across all our clients"), advisory-firm users should use the firm-wide tools (get_firm_client_overview, get_firm_user_activity) instead of looping per business.
The assistant remembers your selection for the rest of the conversation. Say "switch to [business name]" at any time to change.
Note: All monetary amounts are in cents (e.g. $150.00 =
15000). IDs are UUID v7 strings. Pagination is cursor-based — pass thenext_cursorvalue from a response ascursorto get the next page. All date parameters use YYYY-MM-DD format.
Every tool marked write in the Full tool reference requires the write permission (a viewer-role token cannot call them): journal entries, transactions, bills, invoices, payments, contacts, counterparty registry links, counterparty default rules, vendor/customer exports and bulk imports, credit memos, vendor credits, reconciliation, anomalies, attention, file uploads (upload_file, generate_upload_url), and more. The assistant should confirm details with you before calling them.
Bulk imports (end-to-end): call upload_file(filename, content) with the file inline (text, or encoding="base64" for xlsx/pdf/images; up to 5 MB) to get an s3_key, then call bulk_create_vendors, bulk_create_customers, or bulk_create_counterparty_defaults (or the trigger_bulk_* uploads) with that s3_key. For a file over 5 MB, call generate_upload_url(filename) instead and send the file with an HTTP POST (outside MCP, e.g. curl -F) to the returned upload_url.
Every write tool accepts an optional dry_run=true parameter that returns a preview of the change without saving it. When a preview reports a plan_hash, pass that plan_hash back on the apply call. If the books moved between preview and apply (a sync landed, someone edited a row), the apply is refused as stale and you preview again. create_pending_change takes the same plan_hash so a person approving in the app is approving exactly what was previewed.
Journal entry drafts and standards:
- A draft for a human to post is
create_pending_change(tool_name="create_journal_entry", arguments={...}, preview_payload=..., summary=...). The approver applies it under their own identity, so the entry'screated_byis the approver. The arguments are the assistant tool's own shape, signed cents (debit positive, credit negative), with the date given explicitly:{"entry_date": "2026-09-30", "description": "Clearco $300K loan - interest accrual Sep 2026", "line_entries": [{"ledger_id": "<interest expense>", "amount_cents": 125000}, {"ledger_id": "<accrued interest>", "amount_cents": -125000}]}. - An entry allows one line per ledger and side.
create_journal_entry(combine_duplicate_lines=true)sums lines sharing a ledger, side and counterparty (descriptions joined with "; ") and the result reports how many were combined; without it the error names the ledger and side. - Called directly,
create_journal_entrytakesdate,descriptionandline_itemsof{ledger_id, amount_cents, type}(optionaldescriptionper line), whereamount_centsis a positive integer andtypeisdebitorcredit; debits must equal credits.update_journal_entryedits an entry in place (description,entry_date,line_updatesorline_entrieswith signedamount_cents, debit positive and credit negative) and refuses an entry in, or moved into, a closed period. create_journal_entryandupdate_journal_entryreturnwarnings(never errors) when the description is empty, only an id such as "JE 15845", or has no month or year. Use "- ". list_journal_entriesfilters bycreated_by_user_idandlinked_to(bill,invoice,credit_memo,vendor_credit,none); ask forfieldssuch asinvoice_id,bill_ids,credit_memo_id,vendor_credit_id,created_by_user_idto see the links and creator. Entries made before attribution was recorded have no creator.- Reversal is not an MCP tool: use
update_journal_entryto fix an entry in place, or the REST reverse route (POST /api/v1/journal-entries/{id}/reverse), which requiresreversal_date(YYYY-MM-DD) and never defaults to today.
Full tool reference
Auto-generated from the live MCP registry: 417 tools (216 write, 165 approval-gated, 42 exposed by default). Regenerate with make mcp-manifest.
| Tool | Access | Approval gate | Default set |
|---|---|---|---|
accept_payment_suggestion |
write | confirm | — |
add_feedback_comment |
write | — | — |
advance_order_status |
write | confirm | — |
amortize_transaction |
write | confirm | — |
analyze_audit_log |
read | — | — |
answer_agent_run |
write | — | — |
apply_bank_rules |
write | confirm | — |
apply_counterparty_defaults_to_categorized |
write | confirm | — |
apply_counterparty_naming_rule |
write | confirm | — |
apply_counterparty_payee_lines |
write | confirm | — |
apply_credit_memo |
write | confirm | — |
apply_gusto_reconciliation |
write | confirm | — |
apply_standard_cogs |
write | — | — |
apply_stripe_payout |
write | confirm | — |
apply_vendor_credit |
write | confirm | — |
approve_bill |
write | confirm | ✓ |
approve_match |
write | confirm | — |
approve_workflow_step |
write | confirm | — |
attach_inbox_receipt |
write | confirm | — |
attach_order_document |
write | confirm | — |
attach_transaction_receipt |
write | confirm | — |
backfill_customer_ar_subledgers |
write | confirm | — |
book_held_categories |
write | confirm | — |
build_model |
write | — | — |
build_team_from_sop |
write | — | — |
bulk_accept_payment_suggestions |
write | confirm | — |
bulk_approve_matches |
write | confirm | — |
bulk_assign_invoices |
write | confirm | — |
bulk_create_contracts |
write | confirm | — |
bulk_create_counterparty_defaults |
write | confirm | — |
bulk_create_customers |
write | confirm | — |
bulk_create_deals |
write | confirm | — |
bulk_create_invoices |
write | confirm | — |
bulk_create_ledgers |
write | confirm | — |
bulk_create_orders |
write | confirm | — |
bulk_create_projects |
write | confirm | — |
bulk_create_vendors |
write | confirm | — |
bulk_delete_draft_invoices |
write | confirm | — |
bulk_edit_transactions |
write | confirm | — |
bulk_mark_invoices_paid |
write | confirm | — |
bulk_reject_matches |
write | confirm | — |
bulk_update_contracts |
write | confirm | — |
bulk_update_counterparty |
write | confirm | — |
bulk_update_deals |
write | confirm | — |
bulk_update_invoices |
write | confirm | — |
bulk_update_projects |
write | confirm | — |
call_external_read_tool |
read | — | — |
call_external_write_tool |
write | confirm | — |
call_tool |
write | — | ✓ |
cancel_bill |
write | confirm | — |
cancel_workflow_run |
write | confirm | — |
categorize_transaction |
write | confirm | ✓ |
check_ap_approval_health |
read | — | — |
check_shopify_connection |
read | — | — |
compare_ar_snapshots |
read | — | — |
compare_external_bill_status |
read | — | — |
compare_external_trial_balance |
read | — | — |
compare_invoices_across_businesses |
read | — | — |
compare_periods |
read | — | — |
complete_reconciliation |
write | confirm | — |
confirm_write |
write | — | ✓ |
connect_shopify_store_with_token |
write | confirm | — |
convert_deal_to_order |
write | confirm | — |
convert_inbox_bill |
write | confirm | — |
convert_inbox_bills |
write | confirm | — |
create_accounting_period |
write | — | — |
create_asset_category |
write | confirm | — |
create_bank_rule |
write | confirm | — |
create_bill |
write | confirm | ✓ |
create_contract |
write | confirm | — |
create_counterparty_default |
write | confirm | — |
create_counterparty_naming_rule |
write | confirm | — |
create_credit_memo |
write | confirm | — |
create_customer |
write | confirm | — |
create_deal |
write | confirm | — |
create_document_request |
write | — | — |
create_feedback |
write | — | — |
create_feedback_linear_ticket |
write | — | — |
create_fixed_asset |
write | confirm | — |
create_invoice |
write | confirm | ✓ |
create_journal_entry |
write | confirm | — |
create_ledger |
write | confirm | — |
create_or_update_person |
write | confirm | — |
create_order |
write | confirm | — |
create_pending_change |
write | — | — |
create_project |
write | confirm | — |
create_recurring_journal_entry |
write | confirm | — |
create_recurring_templates_from_detection |
write | confirm | — |
create_sop |
write | — | — |
create_transaction_clarification |
write | — | — |
create_vendor |
write | confirm | ✓ |
create_vendor_credit |
write | confirm | — |
create_workflow |
write | — | — |
delete_bank_rule |
write | confirm | — |
delete_counterparty_default |
write | confirm | — |
delete_counterparty_naming_rule |
write | confirm | — |
delete_decision |
write | confirm | — |
delete_invoice |
write | confirm | — |
delete_saved_rename |
write | confirm | — |
delete_workflow |
write | confirm | — |
describe_workflow_schema |
read | — | — |
diff_transaction_export |
read | — | — |
diff_trial_balance |
read | — | — |
dismiss_anomalies_by_period |
write | confirm | — |
dismiss_anomaly |
write | confirm | — |
dispose_asset |
write | confirm | — |
download_reconciliation_pdf |
read | — | — |
email_report |
write | — | — |
enrich_transactions_from_export |
write | confirm | — |
export_counterparty_audit |
read | — | — |
export_dataset |
write | confirm | — |
extract_document_entities |
read | — | — |
extract_statement_transactions |
read | — | — |
fetch |
read | — | ✓ |
finalize_invoice |
write | confirm | ✓ |
find_business |
read | — | ✓ |
find_counterparty_inconsistencies |
read | — | — |
firm_capital_overview |
write | — | — |
generate_report |
write | — | ✓ |
generate_upload_url |
write | — | ✓ |
generate_workflow_graph |
read | — | — |
get_accounting_period_settings |
read | — | — |
get_activity_feed |
read | — | — |
get_aged_payables |
read | — | — |
get_agent_run |
read | — | — |
get_ap_approval_settings |
read | — | — |
get_ap_snapshot |
read | — | ✓ |
get_approval_round |
read | — | — |
get_ar_snapshot |
read | — | ✓ |
get_automation_settings |
read | — | — |
get_bank_balances |
read | — | — |
get_bank_rule_health |
read | — | — |
get_bank_rule_transactions |
read | — | — |
get_bill |
read | — | ✓ |
get_budget |
read | — | — |
get_budget_vs_actual |
read | — | — |
get_bulk_je_template |
read | — | — |
get_business_info |
read | — | — |
get_cash_flow_totals |
read | — | — |
get_cash_forecast |
read | — | — |
get_client_portal_attention |
read | — | — |
get_close_package_data |
read | — | — |
get_close_publication_gate |
read | — | — |
get_close_replay |
read | — | — |
get_close_status |
read | — | ✓ |
get_close_verification |
read | — | ✓ |
get_connection_info |
read | — | ✓ |
get_contract |
read | — | — |
get_counterparty_link_settings |
read | — | — |
get_credit_line |
read | — | — |
get_credit_memo |
read | — | — |
get_credit_portfolio |
read | — | — |
get_customer |
read | — | — |
get_customer_balance |
read | — | — |
get_customer_cash_receipts |
read | — | — |
get_customer_statement |
read | — | — |
get_daily_brief |
read | — | ✓ |
get_deal |
read | — | — |
get_entity_audit_trail |
read | — | — |
get_feedback |
read | — | — |
get_feedback_attachment_url |
read | — | — |
get_feedback_dom_snapshot |
read | — | — |
get_feedback_screenshot |
read | — | — |
get_feedback_stats |
read | — | — |
get_financial_attestation |
read | — | — |
get_financial_overview |
read | — | — |
get_financial_statement |
read | — | — |
get_firm_client_overview |
read | — | ✓ |
get_firm_user_activity |
read | — | — |
get_fixed_asset |
read | — | — |
get_inbox_email |
read | — | — |
get_inventory_book_vs_physical |
read | — | — |
get_inventory_gl_reconciliation |
read | — | — |
get_inventory_gl_repair_plan |
read | — | — |
get_inventory_valuation |
read | — | — |
get_invoice |
read | — | ✓ |
get_invoice_create_requirements |
read | — | ✓ |
get_invoice_posting_settings |
read | — | — |
get_job_status |
read | — | ✓ |
get_journal_entry |
read | — | — |
get_ledger |
read | — | — |
get_margin_by_sku |
read | — | — |
get_match_review |
read | — | — |
get_meta_ad_spend |
read | — | — |
get_month_end_package |
read | — | — |
get_order |
read | — | — |
get_org_chart |
read | — | — |
get_payment_priority_suggestions |
read | — | — |
get_payment_run |
read | — | — |
get_pending_change |
read | — | — |
get_profit_trends |
read | — | — |
get_project |
read | — | — |
get_quickbooks_sync_status |
read | — | — |
get_receipt_coverage |
read | — | — |
get_reconciliation |
read | — | — |
get_reconciliation_balance |
read | — | — |
get_recurring_template |
read | — | — |
get_report |
read | — | — |
get_shopify_fees |
read | — | — |
get_shopify_payout |
read | — | — |
get_shopify_posting_gaps |
read | — | — |
get_shopify_posting_summary |
read | — | — |
get_shopify_refunds |
read | — | — |
get_shopify_sales_report |
read | — | — |
get_shopify_sales_tax |
read | — | — |
get_shopify_sync_status |
read | — | — |
get_sop |
read | — | — |
get_subledger_gl_reconciliation |
read | — | — |
get_suggested_matches |
read | — | — |
get_top_expenses |
read | — | — |
get_transaction |
read | — | ✓ |
get_transaction_summary |
read | — | — |
get_trust_scorecard |
read | — | — |
get_uncategorized_summary |
read | — | ✓ |
get_unmatched |
read | — | — |
get_upload_headers |
read | — | — |
get_user_activity |
read | — | — |
get_vendor |
read | — | — |
get_vendor_balance |
read | — | — |
get_vendor_credit |
read | — | — |
get_workflow |
read | — | — |
get_workflow_run |
read | — | — |
grade_close_replay |
write | — | — |
import_model_workbook |
read | — | — |
import_ramp_receipts |
write | confirm | — |
import_stripe_payout_export |
write | confirm | — |
issue_credit_memo |
write | confirm | — |
issue_vendor_credit |
write | confirm | — |
keep_bank_connection |
write | confirm | — |
link_bill_payment |
write | confirm | ✓ |
link_counterparty |
write | confirm | — |
link_invoice_payment |
write | confirm | ✓ |
link_invoice_to_contract |
write | confirm | — |
list_accounting_periods |
read | — | — |
list_agent_roles |
read | — | — |
list_agent_runs |
read | — | — |
list_anomalies |
read | — | — |
list_ap_approval_queue |
read | — | — |
list_approval_rounds |
read | — | — |
list_asset_categories |
read | — | — |
list_attention_items |
read | — | — |
list_auto_approvals |
read | — | — |
list_bank_accounts |
read | — | — |
list_bank_rule_conflicts |
read | — | — |
list_bank_rules |
read | — | — |
list_bill_payments |
read | — | — |
list_bills |
read | — | ✓ |
list_budgets |
read | — | — |
list_close_steps |
read | — | — |
list_contracts |
read | — | — |
list_counterparty_defaults |
read | — | — |
list_counterparty_naming_rules |
read | — | — |
list_counterparty_payee_lines |
read | — | — |
list_credit_lines |
read | — | — |
list_credit_loans |
read | — | — |
list_credit_memos |
read | — | — |
list_customers |
read | — | ✓ |
list_deals |
read | — | — |
list_decisions |
read | — | — |
list_document_requests |
read | — | — |
list_duplicate_bank_accounts |
read | — | — |
list_external_tools |
read | — | — |
list_feedback |
read | — | — |
list_firm_conversations |
read | — | — |
list_fixed_assets |
read | — | — |
list_inbox_emails |
read | — | — |
list_invoice_payments |
read | — | — |
list_invoices |
read | — | ✓ |
list_jobs |
read | — | — |
list_journal_entries |
read | — | — |
list_ledgers |
read | — | ✓ |
list_month_end_packages |
read | — | — |
list_my_businesses |
read | — | ✓ |
list_notifications |
read | — | — |
list_orders |
read | — | — |
list_pending_changes |
read | — | — |
list_people |
read | — | — |
list_products |
read | — | — |
list_projects |
read | — | — |
list_quickbooks_sync_issues |
read | — | — |
list_reconciliations |
read | — | — |
list_recurring_templates |
read | — | — |
list_report_types |
read | — | ✓ |
list_reports |
read | — | — |
list_saved_renames |
read | — | — |
list_shopify_disputes |
read | — | — |
list_shopify_orders |
read | — | — |
list_shopify_payouts |
read | — | — |
list_sops |
read | — | — |
list_standard_costs |
read | — | — |
list_stripe_payout_matches |
read | — | — |
list_subscriptions |
read | — | — |
list_suspect_transfers |
read | — | — |
list_tags |
read | — | — |
list_transaction_clarifications |
read | — | — |
list_transactions |
read | — | ✓ |
list_uncosted_skus |
read | — | — |
list_vendor_approval_routes |
read | — | — |
list_vendor_credits |
read | — | — |
list_vendors |
read | — | ✓ |
list_workflow_runs |
read | — | — |
list_workflow_versions |
read | — | — |
list_workflows |
read | — | — |
manage_workflow_schedule |
write | confirm | — |
mark_all_attention_read |
write | confirm | — |
mark_attention_read |
write | confirm | — |
mark_bill_received |
write | confirm | ✓ |
mark_invoice_paid |
write | confirm | — |
mark_not_a_transfer |
write | confirm | — |
mark_reviewed |
write | — | — |
mark_transactions_reconciled |
write | confirm | — |
match_transaction |
write | confirm | — |
merge_counterparties |
write | confirm | — |
open_approval_round |
write | — | — |
place_asset_in_service |
write | confirm | — |
plan_close_run |
write | — | — |
post_inventory_cost_adjustments |
write | confirm | — |
propose_inventory_write_down |
write | confirm | — |
publish_workflow |
write | confirm | — |
read_transaction_receipt |
write | — | — |
rebuild_shopify_cogs |
write | confirm | — |
recategorize_by_counterparty |
write | confirm | — |
reconcile_meta_ad_spend |
read | — | — |
record_close_step |
write | — | — |
record_decision |
write | confirm | — |
record_period_sign_off |
write | confirm | — |
refresh_bank_balances |
write | — | — |
refresh_model |
write | — | — |
reject_match |
write | confirm | — |
reject_payment_suggestion |
write | confirm | — |
reject_workflow_step |
write | — | — |
release_bill_hold |
write | confirm | — |
remove_transaction_receipt |
write | confirm | — |
reopen_accounting_period |
write | confirm | — |
repair_quickbooks_sync |
write | confirm | — |
repair_shopify_posting |
write | confirm | — |
repair_stripe_fee_shortfalls |
write | confirm | — |
reprocess_inbox_email |
write | — | — |
request_transaction_receipts |
write | confirm | — |
reset_counterparty_names |
write | confirm | — |
resolve_quickbooks_sync_issue |
write | confirm | — |
respond_to_workflow_run |
write | confirm | — |
revert_workflow |
write | — | — |
review_inbox_email |
write | — | — |
revoke_auto_approval |
write | — | — |
run_depreciation |
write | confirm | — |
run_workflow |
write | confirm | — |
search |
read | — | ✓ |
search_counterparty_registry |
read | — | — |
search_entities |
read | — | ✓ |
search_tools |
read | — | ✓ |
search_workflow_node_tools |
read | — | — |
send_firm_message |
write | confirm | — |
send_invoice |
write | confirm | ✓ |
set_bill_hold |
write | — | — |
set_quickbooks_sync_mode |
write | confirm | — |
set_receipt_exempt |
write | — | — |
set_sop_status |
write | confirm | — |
split_transaction |
write | confirm | — |
split_transaction_by_receipt |
write | confirm | — |
start_agent_run |
write | — | — |
start_background_job |
write | confirm | — |
start_close_replay |
write | — | — |
start_reconciliation |
write | confirm | — |
start_stripe_payout_sync |
write | — | — |
steer_agent_run |
write | — | — |
stop_agent_run |
write | — | — |
submit_approval_round |
write | — | — |
suggest_sops |
read | — | — |
sync_quickbooks_now |
write | confirm | — |
sync_shopify |
write | confirm | — |
test_workflow |
read | — | — |
toggle_bank_rule |
write | — | — |
trigger_bulk_je_upload |
write | confirm | — |
trigger_bulk_transaction_upload |
write | confirm | — |
trigger_month_end_close |
write | confirm | — |
trigger_payment_matching |
write | — | — |
trigger_ramp_repair |
write | confirm | — |
unapply_credit_memo |
write | confirm | — |
unapply_vendor_credit |
write | confirm | — |
unlink_bill_journal_entry |
write | confirm | — |
unlink_counterparty |
write | confirm | — |
unlink_master_from_registry |
write | confirm | — |
unpublish_workflow |
write | — | — |
update_accounting_period_settings |
write | — | — |
update_automation_settings |
write | — | — |
update_bank_rule |
write | confirm | — |
update_bill |
write | confirm | — |
update_cash_forecast_timing |
write | — | — |
update_contract |
write | confirm | — |
update_conversation_status |
write | confirm | — |
update_counterparty_default |
write | confirm | — |
update_counterparty_link_settings |
write | — | — |
update_counterparty_naming_rule |
write | confirm | — |
update_customer |
write | confirm | — |
update_deal |
write | confirm | — |
update_decision |
write | confirm | — |
update_feedback |
write | — | — |
update_fixed_asset |
write | confirm | — |
update_inventory_ledger_settings |
write | confirm | — |
update_invoice |
write | confirm | — |
update_invoice_posting_settings |
write | confirm | — |
update_journal_entry |
write | confirm | — |
update_order |
write | confirm | — |
update_project |
write | confirm | — |
update_sop |
write | — | — |
update_standard_costs |
write | confirm | — |
update_transaction |
write | confirm | ✓ |
update_vendor |
write | confirm | — |
update_vendor_approval_route |
write | confirm | — |
update_workflow |
write | — | — |
upload_file |
write | — | ✓ |
validate_workflow |
read | — | — |
void_credit_memo |
write | confirm | — |
void_invoice |
write | confirm | — |
void_vendor_credit |
write | confirm | — |
widen_automation_settings |
write | confirm | — |
Approval gates
High-risk writes — payments (link_invoice_payment, link_bill_payment, mark_invoice_paid), voids (void_invoice, void_credit_memo, void_vendor_credit, cancel_bill), external sends (send_invoice), irreversible state changes (finalize_invoice), journal entries, merges and bulk posts — wait for your approval before committing. The same flow works in Claude Code, Cursor, Codex and claude.ai:
- Confirm dialog. A client that supports MCP elicitation on the 2026-07-28 protocol shows a native dialog summarizing the change (amounts in dollars). Choosing No in the form returns
{"approved": false, "reason": "rejected"}and commits nothing. - Approve in DayZero. Every other client, including Claude Code hosts that can't draw the dialog and decline it on their own, gets
{"status": "approval_required", "approval_id": "…", "approve_url": "…", "summary": "…"}back. The assistant gives you the link; you open it signed in to DayZero, review the tool, business and arguments, and choose Approve or Decline (with an optional note). The assistant then callsconfirm_write(approval_id): an approved write runs exactly that call once and returns its result, a declined one comes back asreason: "rejected"with your note, and an undecided one asstatus: "awaiting_approval"(it can passwait_secondsup to 50 to wait for you). The assistant can cancel a waiting write (cancel=true) but has no way to approve one: only you, signed in as the user the write belongs to, can. An approval belongs to the user and client that received it and expires after 30 minutes. - Large changes. A bulk tool's
confirm_large_change=true(go past its blast-radius limit) always takes the same approval, even for a tool you have a standing grant for.
dry_run=true previews never ask. The gate is also applied to any write whose name starts with delete_, bulk_delete_, void_, bulk_void_ or cancel_, so a newly added destructive tool cannot slip through. The Approval gate column of the Full tool reference marks every gated tool.
Two ways around a prompt, both set up by a person:
- Standing approvals. A per-tool "always allow" grant you have given in the DayZero in-app assistant lets that tool skip the prompt for that business. Only explicit per-tool grants count (the broader Auto-Approval toggles in the assistant settings are ignored on MCP), and tools that delete, are irreversible or have external effects can never be auto-approved.
list_auto_approvalsshows your grants;revoke_auto_approvalremoves one. - Proposed changes. An agent that should not apply a write itself can call
create_pending_changewith the tool name, its exact apply arguments, the preview and theplan_hash. A person approves or rejects it in the app's Proposed changes inbox; approval applies it as the approver, and the apply is refused as stale if the books moved since the preview. Read the outcome withlist_pending_changesandget_pending_change.
Close agents: ask in the portal, report gaps
The agents profile (/mcp/agents) is for close agents run from the Agent window. Two things it does that the other profiles do not:
- Ask the client in the portal, not by email.
create_transaction_clarificationputs a question beside one transaction (with optional one-tap answers) under the client's Questions page;create_document_requestasks for a file under Document requests. Both are for firm staff, reach only that business's own client users, can be cancelled, and need no approval. Read the answers back withlist_transaction_clarifications(status="answered")andlist_document_requests(status="fulfilled").list_firm_conversationsshows the message threads,send_firm_messageandupdate_conversation_statuswork on them (those two still ask for approval), andget_client_portal_attentionshows what the client sees on their dashboard. A connection bound to one business only lists that business's threads. - Report a gap instead of pasting a transcript.
create_feedback(kind="gap", tool_tried, error, sop_job?, expected?, excerpt?, severity?)files a feedback ticket for the DayZero team (sourceagent, tagplatform_gap) and returns{feedback_id, deduplicated}. The same gap seen again within 14 days adds a note to the open ticket instead of a new one. It changes no books and needs no approval; it is rate limited.
UI cards (MCP Apps)
Hosts that advertise MCP Apps / mcp-ui support receive rendered HTML cards as embedded ui://dayzero/* resources alongside the JSON payload on snapshot tools: get_daily_brief, get_ar_snapshot, get_ap_snapshot, get_aged_payables, get_uncategorized_summary, and get_payment_priority_suggestions. Cards show key figures, aging tables, and dollar-formatted amounts with automatic light/dark styling. Clients without UI support receive identical JSON-only responses.
Note:
create_invoicerequires Stripe Connect (or a demo business, orhistorical=truefor an invoice already issued elsewhere, which stays a local draft and never reaches Stripe) — callget_invoice_create_requirementsfirst. For a migrated invoice passhistorical=truewithinvoice_dateandinvoice_number. Typical flow:create_invoice→finalize_invoice→send_invoiceorlink_invoice_payment.mark_invoice_paidis for manual paid status without a bank match. AP:approve_bill→mark_bill_received(needs expenseledger_id).get_aged_payablespairs withget_ar_snapshot;get_payment_priority_suggestionsranks open bills late → early-pay discount → due within 7 days, with cash on hand.
Long-running workflows (trigger_bulk_transaction_upload, trigger_bulk_je_upload, trigger_month_end_close, generate_report, and bulk_create_invoices on a file of more than 500 rows) return immediately with {job_id, status: "started", poll_tool: "get_job_status"}. Do not wait inline; poll get_job_status(job_id) until completion/failure. list_jobs shows the business's recent jobs. Most MCP clients cancel a tool call after about a minute, which is why these tools hand back a job instead of blocking.
Multi-step agentic work that exceeds one call (hundreds of writes, many documents) can be handed to start_background_job: it runs detached on the server (about an hour of wall clock) under a write scope fixed at launch (allowed_write_tools, empty means read-only), and no human approves anything mid-run. Poll get_job_status for the summary and signed download links to any files it produced.
Reports follow: list_report_types → generate_report → poll get_job_status (use job_id) → optional get_report when the completed job returns a report_id. Pass wait=true to generate_report to wait up to wait_timeout_seconds (default 25, at most 55) and get the download link in one call; it falls back to the job handle if the report is not ready in time. output_format is csv (default) or xlsx. email_report sends a generated report's download link by email.
Whole datasets: export_dataset (up to 10,000 rows; format="jsonl" for programmatic use) replaces paging a list tool.
Download links (reports, exports, job files) are presigned, host-bound and expire after about an hour. Fetch them exactly as returned, with no Authorization header; changing the query string or adding auth breaks the signature.
When a tool fails
A failed tool returns a teaching error rather than a bare message — the same shape whether the failure came from the tool's own validation or from the data underneath it:
{
"error": "You have access to multiple businesses. Please specify which one to use: …",
"reason_code": "BUSINESS_SELECTION_REQUIRED",
"how_to_fix": "Ask the user which of the businesses listed in the error to use, then pass its business_id.",
"retryable": false,
"did_you_mean": []
}Read how_to_fix and did_you_mean before retrying, and don't retry at all
when retryable is false. Common reason_code values:
reason_code |
Meaning |
|---|---|
BUSINESS_SELECTION_REQUIRED |
You have several businesses; pass the business_id of the one you want (the error lists them) |
FIRM_SELECTION_REQUIRED |
You belong to several advisory firms; pass firm_id |
NOT_FOUND |
No record with that id in this business — look it up first, and check business_id |
INVALID_ARGUMENT / VALIDATION_ERROR / INVALID_ENUM / INVALID_DATE_FORMAT |
Fix the named argument; did_you_mean lists the accepted values |
UNKNOWN_TOOL |
No tool by that name; use search_tools and take a name from its result |
MISSING_REQUIRED_FIELD |
An update with no fields to change |
PERMISSION_DENIED |
Your role or grant doesn't cover this tool; access has to change first |
CONFLICT |
The record changed, or one like it already exists — re-read it and decide whether the write is still wanted |
AUTHENTICATION_REQUIRED |
The connection is not authenticated — re-authorize the integration |
NO_BUSINESS_ACCESS / NOT_A_FIRM_MEMBER |
The account reaches no business, or a firm-wide tool was called without advisory-firm membership — use a business-scoped tool |
UNSUPPORTED_REPORT_TYPE |
Call list_report_types and use one of its names |
MISSING_SCOPE_READ / MISSING_SCOPE_WRITE |
Re-authorize with the missing OAuth scope |
PARTIAL_SUCCESS |
A bulk call saved some rows — retry only the ones in data.failed |
COMMIT_FAILED |
Nothing was saved; retry the whole call |
RATE_LIMITED / TIMEOUT |
Retryable — wait a moment and call again |
UNKNOWN_ERROR |
Unclassified; read error |
A bare Error executing tool <name> with no envelope means an internal fault,
not something to correct in the call — it is reported to DayZero automatically.
Working with Large Datasets
List tools return a total field showing total matching records. Use this to decide how to proceed:
- Analytical questions ("what did we spend the most on?", "are we profitable?", "how much revenue last quarter?") — use the analytics tools (
get_financial_overview,get_top_expenses,get_cash_flow_totals,get_profit_trends,get_transaction_summary). These compute summaries server-side and return small payloads regardless of data volume. - Under ~100 matching records — paginate through them if you need individual details.
- Over ~100 matching records — narrow with filters (date range, search text, ledger_id, status) or use analytics tools. Don't page through thousands of records.
- Full exports — use
generate_reportfor a report file, orexport_datasetfor a raw dataset.
Strategy: summarize first, drill down second. Start with aggregate tools to understand the big picture, then use list tools with filters to examine specific subsets.
Prerequisites
- A DayZero login for the browser consent flow. MCP sign-in is open to every account; it needs no separate approval and no API key.
- API access not switched off for your user. If your advisory firm has disabled API access for you, authorization fails with
access_denied.
Connecting Claude Desktop
The fastest path is the install link — Add DayZero to Claude. It opens claude.ai's Add custom connector dialog with the name and URL prefilled; review it, click Add, and sign in to DayZero when prompted. Connectors are account-level, so one add covers Claude on web, desktop, and mobile.
Prefer local config? Add the server with just its URL. Claude registers itself, opens a browser for you to sign in to DayZero and approve access, then stores the MCP OAuth token automatically:
{
"mcpServers": {
"dayzero": {
"url": "https://mcp.ondayzero.com/mcp"
}
}
}Config file location:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Restart Claude Desktop after saving. You should see DayZero tools appear in the tools menu.
Connecting Claude Code
One command:
claude mcp add --transport http dayzero https://mcp.ondayzero.com/mcpThen run /mcp inside Claude Code to complete the browser sign-in. To share the server with your whole team, commit a .mcp.json at the repo root instead:
{
"mcpServers": {
"dayzero": {
"type": "http",
"url": "https://mcp.ondayzero.com/mcp"
}
}
}Calling your connected external MCP servers (Gusto and others)
Servers an admin connected under Integrations → External MCP servers (Gusto, Stripe, a CRM, ...) are reachable through the same DayZero connection, so Claude Code never holds the third-party credentials. Three tools do it (all on /mcp, and on the focused https://mcp.ondayzero.com/mcp/integrations mount); they need the admin role on the business:
list_external_tools— the connected servers and their tools, each markedread(runs without approval) orwrite(needs your approval). Passserver+toolto get a tool's input schema before the first call.call_external_read_tool(server, tool, arguments)— runs a tool trusted as read-only, with no approval prompt. It refuses anything else.call_external_write_tool(server, tool, arguments)— runs any other non-blocked tool after you approve the exact server, tool and arguments in DayZero (the sameapprove_url→confirm_writeflow as other gated writes). Write approval is never skipped.
Which tools count as read is an admin's call, made per connection on the Integrations page: either Trust read-only hints (tools the server itself marks read-only) or, for servers that don't annotate their tools, Allow as read on each tool. A tool the server marks destructive always needs approval, and a blocked tool never runs. For Gusto, mark the lookups you use — for example the company lookup (get_company, to see which company the connection is signed into), payroll detail (the per-employee breakdown of a payroll) and contractor payments (by date range) — as Allow as read. Tool names come from Gusto's server; check them with list_external_tools(server="gusto").
Example prompts in Claude Code:
- "Which Gusto company is our DayZero connection signed into?"
- "Pull the per-employee breakdown for the October 15 payroll from Gusto."
- "List Gusto contractor payments from 2026-09-01 to 2026-09-30."
Every external call is logged in DayZero's audit trail: who (the person who owns the DayZero token), through what (the MCP client, e.g. claude-code, and its OAuth client id), which server and tool, read or write, the outcome, and — for a write — the approval. Arguments are stored as a digest, not the payload. Results are third-party text and are marked untrusted.
Who did it, and where it came from
Every change made through DayZero is attributed in the audit trail (the History panel on a record, get_entity_audit_trail, get_activity_feed) to the person and the channel: browser (the app), api (an API key, shown by name), mcp (an MCP client, shown by its name), ai_chat (the in-app assistant), workflow (a workflow run) or system (background jobs). Writes an agent made after you approved them in DayZero also carry the approval.
Connecting Cursor
The Add to Cursor button under Settings → Developers in DayZero opens Cursor with the server prefilled — confirm the install and sign in when the browser opens.
To add it manually, go to Settings > MCP Servers in Cursor and add a new server:
- Name: DayZero
- URL:
https://mcp.ondayzero.com/mcp
Leave the headers blank — Cursor opens a browser for you to sign in and approve via OAuth.
Connecting ChatGPT
ChatGPT requires Developer mode before you can add an unlisted MCP connector:
- Enable it under Settings → Apps → Advanced settings → Developer mode (available on Plus and Pro; on Business, Enterprise, and Edu workspaces an admin may need to allow it — or an admin can add DayZero org-wide from the workspace admin console).
- Create a new connector with Name: DayZero, URL:
https://mcp.ondayzero.com/mcp.
ChatGPT discovers the OAuth endpoints, opens a browser for you to sign in to DayZero, and stores the token automatically. Connectors are account-level, so the same connection works in the ChatGPT web, desktop, and mobile apps.
Connecting Codex
Codex CLI, the Codex IDE extension, and the ChatGPT desktop app share one MCP configuration. Add two lines to ~/.codex/config.toml:
[mcp_servers.dayzero]
url = "https://mcp.ondayzero.com/mcp"Or configure it in the ChatGPT desktop app under Settings → MCP servers → Add server — name dayzero, transport Streamable HTTP, URL above. Codex opens your browser to sign in to DayZero the first time it connects.
Connecting Other MCP Clients
Any MCP client that supports Streamable HTTP transport can connect. The server implements the full MCP authorization spec, so compatible clients configure themselves automatically from the server URL alone:
- RFC 9728 Protected Resource Metadata —
https://mcp.ondayzero.com/.well-known/oauth-protected-resource/mcp - RFC 8414 Authorization Server Metadata —
https://api.ondayzero.com/.well-known/oauth-authorization-server
These advertise the authorization server, supported scopes, PKCE methods, and the authorize / token / registration endpoints.
A connector descriptor for directories and crawlers lives at https://mcp.ondayzero.com/.well-known/mcp.json (alias of /.well-known/mcp/server-card.json): the endpoints and domain mounts, both OAuth metadata URLs, logo, docs, categories, contact and the size of the default tool list.
The canonical resource URL (RFC 8707 audience) is https://mcp.ondayzero.com/mcp — no trailing slash.
Browser-based and hosted clients (Origin allowlist)
As part of the MCP spec's DNS-rebinding protection, the server validates the Origin header on every MCP request. Requests without an Origin header — desktop apps and CLIs such as Cursor, Claude Desktop, Codex CLI, and mcp-remote — always pass. Requests with an Origin header must match the allowlist, which covers:
- Anthropic —
https://claude.ai,https://claude.com - OpenAI —
https://chatgpt.com,https://chat.openai.com,https://platform.openai.com - Cursor —
https://cursor.com,https://cursor.sh - Local development —
http://localhost:*,http://127.0.0.1:*(e.g. MCP Inspector)
A hosted client whose origin is not allowlisted receives 403 Invalid Origin header on every MCP call after OAuth succeeds — the connector shows as connected but lists zero tools. If you're building or operating a hosted MCP client that should connect to DayZero, contact us so we can add your origin (self-hosted deployments can extend the list via the MCP_ALLOWED_ORIGINS_EXTRA environment variable).
Environment URLs
| Environment | MCP server URL | Authorization server |
|---|---|---|
| Production | https://mcp.ondayzero.com/mcp |
https://api.ondayzero.com |
| Local dev | http://localhost:8000/mcp |
http://localhost:8000 |
Use the MCP server URL in your client config. The protected-resource metadata is served from the MCP host (https://mcp.ondayzero.com/.well-known/oauth-protected-resource/mcp); the authorization server — its metadata at /.well-known/oauth-authorization-server, its issuer, and the /oauth2/* endpoints — stays on the API host (https://api.ondayzero.com). Clients discover this automatically from the MCP server URL.
Authentication
MCP uses OAuth 2.1 with browser consent. Tokens minted through this flow are MCP-only — they cannot call the REST API (/api/v1/*). Likewise, REST API keys and SPA session tokens cannot authenticate MCP tool requests.
OAuth 2.1 flow
- The client connects to
/mcpand receives a401with aWWW-Authenticateheader pointing at/.well-known/oauth-protected-resource. - It reads RFC 9728 protected-resource metadata and discovers the authorization server.
- It reads RFC 8414 authorization-server metadata at
/.well-known/oauth-authorization-server. - It dynamically registers itself (RFC 7591) at
POST /oauth2/register— no pre-shared client credentials needed. Alternatively a client can skip registration and use anhttpsURL it controls as itsclient_id(Client ID Metadata Documents): DayZero fetches that URL, which must serve the client's metadata JSON with a matchingclient_id. These clients are always public (PKCE, no secret). - It opens your browser to
GET /oauth2/authorizewith PKCE (S256) and an optional RFC 8707resourceparameter (must match the MCP server URL). - You sign in via Clerk and review the consent page, which shows:
- The app name and human-readable scope descriptions
- Your signed-in identity and accessible businesses (via
GET /oauth2/userinfo) - Which businesses the app may reach — all of them, or only one you pick — and an Allow changes box (see Choosing a business and allowing changes)
- Where you'll be redirected after approval (with loopback / non-HTTPS warnings when applicable)
- After you click Allow access, the client exchanges the authorization code at
POST /oauth2/mcp/tokenfor an MCP access token (plus a refresh token when the grant includesoffline_access). - The access token (valid for 60 minutes) is sent as
Authorization: Bearer …on every MCP request and refreshed automatically when it expires.
MCP sign-in is open to every account. If your firm has disabled API access for your user, authorization fails with access_denied.
OAuth scopes
Scopes appear on the consent page in plain English:
| Scope | What it allows |
|---|---|
mcp:read |
View your accounting data — read transactions, balances, invoices, and reports |
mcp:write |
Make changes on your behalf — create and modify journal entries, invoices, bills, and other records |
offline_access |
Stay connected — keep this app authorized without signing in each time |
mcp:admin |
Act as DayZero staff — staff-only tools (feedback triage, admin repairs) and every client business. Staff accounts only. |
Write tools require both mcp:write and write permission on the business. A token with only mcp:read can query data but cannot call write tools.
mcp:admin is different from the other scopes: it is not advertised in scopes_supported, a client cannot obtain it by asking, and a superuser's token does not carry it by default. It is granted only when a DayZero staff member ticks Act as DayZero staff on the consent screen. Without it, a staff member's token behaves like any customer's, and the admin tools return 403 with a message pointing back to that box.
A few scope rules to be aware of:
- Refresh tokens are only issued when the grant includes
offline_access. Without it, the client gets an access token only and must re-authorize when it expires. A refresh may narrow the scopes but never widen them. - If a client requests no scopes at all, it is granted
mcp:read offline_access(read-only, but able to stay connected). - If a client registered with an explicit
scope, requests are narrowed to that registered set — a read-only registration cannot later escalate tomcp:write.
If the token is missing or invalid, the server returns 401 with a WWW-Authenticate header pointing to the resource metadata endpoint.
Choosing a business and allowing changes
The consent screen asks two things before you approve:
Businesses. Keep All businesses you can access, or pick Only one business from the list. If you can open just one business, that business is picked for you. A connection limited to one business:
- works on that business only. Asking for any other business returns
403— "This connection is limited to ProScore. Reconnect DayZero to work on another business." A tool call that names another business anywhere in its arguments is refused before it runs; - uses that business when a tool call names none;
- cannot use firm-wide tools (
get_firm_client_overview,get_firm_user_activity) or DayZero staff tools, and is never staff — the Act as DayZero staff box is turned off while one business is picked; - lists the full tool catalog on
/mcp(minus staff tools), so agents can call any tool for that business; - keeps its business for good: refreshing the token never changes it. To work on another business, connect again and pick it. If you lose access to the business, the connection stops (
401, asking you to reconnect).
The token response names the business (
business_id,business_name),get_connection_inforeports it, and Settings → Developers shows it on the connected app. One app can hold one connection per business plus one for all businesses; disconnecting one leaves the others working.- works on that business only. Asking for any other business returns
Allow changes. Ticked, the app gets
mcp:writeand can create and edit records — each risky change still asks you first. Unticked, it can only read. The box starts ticked only when the app asked to make changes, and it is offered only when the app's registration allows changes.
Revoking access
OAuth-connected MCP clients (e.g. Claude Desktop, Cursor) create a connected app grant tied to your account. Revoke a grant to immediately invalidate its refresh token:
# List connected apps (requires a DayZero session or REST OAuth token)
curl "https://api.ondayzero.com/api/v1/oauth/grants" \
-H "Authorization: Bearer YOUR_SESSION_OR_API_TOKEN"
# Revoke a grant by ID
curl -X DELETE "https://api.ondayzero.com/api/v1/oauth/grants/GRANT_ID" \
-H "Authorization: Bearer YOUR_SESSION_OR_API_TOKEN"Revoking a grant blacklists its refresh token and every active access token issued under it, so access is cut off immediately — not when the access token would naturally expire. You can also disconnect an app from Connected apps under Settings → Developers.
Revoking an MCP grant does not affect REST API keys — manage those separately under Settings → Developers.
Security notes
- MCP tokens carry JWT
type=mcpand audience = the MCP resource URL — distinct from RESTaccess,refresh, andapitokens. - The consent screen is a React page served at
GET /oauth2/authorize; standalone error pages use Jinja2 templates. Both ship strict security headers (CSP nonce,X-Frame-Options: DENY,Referrer-Policy: no-referrer). - Dynamic client registrations expire after ~90 days of inactivity; clients re-register automatically.
- Registered redirect URIs are validated:
https, loopbackhttp(with a callback path), and the app schemescursor://,vscode://,cursor-ide://andclaude://are allowed;javascript:/data:/file:andhttpon non-loopback hosts are rejected, as are URIs with credentials or a fragment. - PKCE (
S256) is mandatory — authorization codes cannot be exchanged without a valid code verifier. - DNS-rebinding protection validates the
Hostheader and allowlists theOriginheader on every MCP request (see Browser-based and hosted clients). Requests with an unrecognizedOriginare rejected with403. - Refresh tokens are bound to the client they were issued to; the refresh grant requires
client_id(and the client secret for confidential clients) and rejects tokens presented by a different client. - Refresh tokens rotate on every use. Replaying an already-rotated token after a short grace window (about 5 minutes, which absorbs retries) is treated as possible theft and revokes the grant, so the client must sign in again.
POST /oauth2/register,POST /oauth2/mcp/tokenandGET /oauth2/authorizeare rate-limited per client IP and return429with aRetry-Afterheader when exceeded.
Example Conversation
Once connected, just start asking questions — no setup required:
Single business (most common):
You: What invoices are overdue?
Assistant: You have 3 overdue invoices totaling $4,250.00…
The server auto-detected your business behind the scenes. No IDs needed.
Multiple businesses:
You: Show me last month's transactions
Assistant: You have access to 2 businesses:
- Acme LLC — admin
- Beta Corp — viewer
Which one would you like to use?
You: Acme
Assistant: Here are Acme LLC's transactions for last month…
After you pick, the assistant remembers your choice for the rest of the conversation. Say "switch to Beta Corp" at any time to change.
More things you can ask:
- "List all bank accounts"
- "Show me the last 10 transactions from checking"
- "Generate a profit and loss report for Q1 2026"
- "Create a journal entry for $500 rent expense on March 1"
- "Search for anything related to Acme Corp"
- "Compare the operating budget to actuals this quarter"
- "What are our top expenses this year?"
- "Are we cash-flow positive this quarter?"
- "How have profit margins changed over the past 6 months?"
- "How many transactions came in last month?"
- "What should I look at today?" (Daily Brief)
- "Mark that Amazon transaction as reviewed"
- "Add a new vendor called Acme Hosting with email billing@acme.com"
- "Create a $250 bill from Acme Hosting due next Friday"
- "Finalize draft invoice #1042"
- "Email invoice #1042 to the customer"
- "How much do we owe vendors by aging bucket?"
- "Void invoice #1042"
- "Create a $25 credit memo for Acme and issue it"
- "Cancel the draft bill from Acme Hosting"
- "Mark these three bank transactions as reconciled"
- "What's blocking us from creating invoices via API?"
Troubleshooting
| Problem | Solution |
|---|---|
| Tools don't appear | Verify the URL is https://mcp.ondayzero.com/mcp (no trailing slash) and restart the client |
| Only ~40 tools show up | Expected on /mcp: it advertises a curated starter set and the assistant finds the rest with search_tools. To see a whole domain, connect its profile mount |
A write returns status: approval_required |
The write is gated and your client can't show a confirmation dialog. Give the user the approve_url from the result; they open it signed in to DayZero and choose Approve or Decline. Then call confirm_write(approval_id). The approval expires after 30 minutes, and the assistant cannot approve for the user. See Approval gates |
| Connected, but zero tools | The client's Origin isn't allowlisted — MCP calls get 403 Invalid Origin header after OAuth. Claude, ChatGPT, and Cursor origins are supported; for other hosted clients see Origin allowlist |
| Browser sign-in doesn't open | Ensure your MCP client supports OAuth 2.1 with dynamic client registration |
access_denied during consent |
Your firm has switched off API access for your user — ask a firm admin to re-enable it |
| Stuck re-authorizing | Your registered client may have expired — the client re-registers automatically; just retry the connection |
| 401 Unauthorized | Re-run the OAuth sign-in; REST API keys (dz_…) do not work on MCP |
| 403 on write tools | Your grant may only include mcp:read — re-authorize with write access, or check your business role |
| 403 Forbidden (business) | Your token doesn't have access to the specified business_id |
| 404 Not Found | Ensure the URL is exactly /mcp — not /mcp/ with a redirect, /mcp/mcp, or /api/mcp |
| Unknown application / registration expired | Close the browser tab and reconnect from your MCP client so it re-registers |
| Connection timeout | Ensure the DayZero API is reachable from your network |
Session terminated on every tool call |
The MCP connector lost its Streamable HTTP session (common after a deploy or when the client doesn't re-initialize). Disconnect and reconnect the DayZero connector in your MCP client, or start a new chat. DayZero runs in stateless Streamable HTTP mode so new requests don't depend on a server-side session ID; if this persists after reconnecting, report it with the client name and timestamp. |
What's Next?
- Authentication — managing API tokens
- First Request — getting started with the REST API
- Reports — available report types and formats