ExpenseBot
REMOTE · MCP.EXPENSEBOT.AI · 2 COMPONENTS
Receipt ingestion, Gmail capture, expense analysis, and reviewed reports for AI-agent workflows.
Available components
Last scanned (44 minutes ago)
Scores higher than 64% of remote servers
Reachable. Last reached 5 Nov 2026.
Category Data and Analytics
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security63
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation check failed: no authorisation is required to call this server, and it exposes a tool marked destructive (complete_setup). See how to fix → View diagnostics → Fail
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- The HSTS (Strict-Transport-Security) header is present. View diagnostics → Pass
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability63
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 15381 tokens (~236/item across 65 items; 65 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
- No destabilizing schema changes in the last 30 days.Pass
Tool Coverage99
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 98% of tool parameters carry a description.Partial
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety50
- Injection-marker check failed: the server instructions contains an instruction to conceal the call from the user, the text "never tell the user", at byte 6890 of that field. See how to fix → Fail
- All 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 66 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 5 Nov 26 0
- Stability: fail → pass ▲ security
- Tool “get_mileage_summary” rewrote its description, which is the text the model reads security
- Tool “add_mileage_entry” rewrote its description, which is the text the model reads security
- “add_mileage_entry” added an optional parameter “vehicleId” cosmetic
- “add_mileage_entry” added an optional parameter “unit” cosmetic
- “add_mileage_entry” added an optional parameter “trackingMode” cosmetic
- “add_mileage_entry” added an optional parameter “operationId” cosmetic
- “search_knowledge” reworded the description of “fullAnswer” cosmetic
- “get_mileage_summary” reworded the description of “query” cosmetic
- “get_mileage_summary” reworded the description of “groupBy” cosmetic
- “add_mileage_entry” reworded the description of “tag” cosmetic
- “add_mileage_entry” reworded the description of “roundTrip” cosmetic
- “add_mileage_entry” reworded the description of “purpose” cosmetic
- “add_mileage_entry” reworded the description of “notes” cosmetic
- “add_mileage_entry” reworded the description of “distance” cosmetic
- “add_mileage_entry” reworded the description of “destination” cosmetic
- “add_mileage_entry” reworded the description of “date” cosmetic
- “add_mileage_entry” reworded the description of “city” cosmetic
- “add_mileage_entry” reworded the description of “category” cosmetic
- 4 Nov 26 −3
- Injection markers: pass → fail ▼ security
- The server rewrote its instructions, which are the text every model session reads security
- Tool “whatif_tax_setaside” rewrote its description, which is the text the model reads security
- Tool “whatif_client” rewrote its description, which is the text the model reads security
- Tool “update_expense” rewrote its description, which is the text the model reads security
- Tool “submit_receipt” rewrote its description, which is the text the model reads security
- Tool “share_report” rewrote its description, which is the text the model reads security
- Tool “search_expenses” rewrote its description, which is the text the model reads security
- Tool “search” rewrote its description, which is the text the model reads security
- Tool “scan_gmail” rewrote its description, which is the text the model reads security
- Tool “process_gmail_receipts” rewrote its description, which is the text the model reads security
- Tool “parse_expense” rewrote its description, which is the text the model reads security
- Tool “group_expenses” rewrote its description, which is the text the model reads security
- Tool “get_trip_suggestions” rewrote its description, which is the text the model reads security
- Tool “get_spreadsheet_url” rewrote its description, which is the text the model reads security
- Tool “get_spending_summary” rewrote its description, which is the text the model reads security
- Tool “get_scan_status” rewrote its description, which is the text the model reads security
- Tool “get_pnl” rewrote its description, which is the text the model reads security
- Tool “get_per_tag_pnl” rewrote its description, which is the text the model reads security
- Tool “get_last_receipt_result” rewrote its description, which is the text the model reads security
- Tool “get_accounting_integration_status” rewrote its description, which is the text the model reads security
- Tool “fix_compliance” rewrote its description, which is the text the model reads security
- Tool “fetch” rewrote its description, which is the text the model reads security
- Tool “create_report” rewrote its description, which is the text the model reads security
- Tool “correct_expenses” rewrote its description, which is the text the model reads security
- Tool “add_mileage_entry” rewrote its description, which is the text the model reads security
- Tool “add_cash_expense” rewrote its description, which is the text the model reads security
- Tool “add_income” rewrote its description, which is the text the model reads security
- New tool “omit_expenses” functional
- “add_income” reworded the description of “paymentMethod” cosmetic
- “submit_receipt” reworded the description of “uploadRefs” cosmetic
- “submit_receipt” reworded the description of “filesToUpload” cosmetic
- “search_expenses” reworded the description of “tagAssignment” cosmetic
- “search_expenses” reworded the description of “query” cosmetic
- “group_expenses” reworded the description of “replaceExistingTags” cosmetic
- “get_report_details” reworded the description of “checkFreshness” cosmetic
- “get_report_details” reworded the description of “analysisRequested” cosmetic
- “get_last_receipt_result” reworded the description of “withinSeconds” cosmetic
- “get_income_summary” reworded the description of “incomeTagPrefix” cosmetic
- “fix_compliance” reworded the description of “undo” cosmetic
- “fix_compliance” reworded the description of “status” cosmetic
- “fix_compliance” reworded the description of “selection” cosmetic
- “fix_compliance” reworded the description of “operationId” cosmetic
- “fix_compliance” reworded the description of “change” cosmetic
- “create_report” reworded the description of “recipientRole” cosmetic
- “correct_expenses” reworded the description of “undo” cosmetic
- “correct_expenses” reworded the description of “status” cosmetic
- “correct_expenses” reworded the description of “selection” cosmetic
- “correct_expenses” reworded the description of “operationId” cosmetic
- “correct_expenses” reworded the description of “change” cosmetic
- “check_compliance” reworded the description of “analysisRequested” cosmetic
- “add_income_from_file” reworded the description of “rowEdits” cosmetic
- 3 Nov 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “get_last_receipt_result” rewrote its description, which is the text the model reads security
- Tool “get_spreadsheet_url” rewrote its description, which is the text the model reads security
- MCP protocol: Implements a current MCP spec version (2026-07-28). functional
- MCP protocol version: 2025-11-25 → 2026-07-28 functional
- 2 Nov 26 0
- The server rewrote its instructions, which are the text every model session reads security
- New tool “complete_setup”, which the server declares destructive security
- Tool “search_expenses” rewrote its description, which is the text the model reads security
- Tool “send_report_to_accounting” rewrote its description, which is the text the model reads security
- Tool “scan_gmail” rewrote its description, which is the text the model reads security
- Tool “request_accounting_integration” rewrote its description, which is the text the model reads security
- Tool “group_expenses” rewrote its description, which is the text the model reads security
- Tool “get_subscription_audit” rewrote its description, which is the text the model reads security
- Tool “get_spreadsheet_url” rewrote its description, which is the text the model reads security
- Tool “get_scan_status” rewrote its description, which is the text the model reads security
- Tool “get_recent_activity” rewrote its description, which is the text the model reads security
- Tool “get_monthly_books_review” rewrote its description, which is the text the model reads security
- Tool “get_mileage_summary” rewrote its description, which is the text the model reads security
- Tool “get_last_receipt_result” rewrote its description, which is the text the model reads security
- Tool “get_expense_splits” rewrote its description, which is the text the model reads security
- Tool “get_expense_by_id” rewrote its description, which is the text the model reads security
- Tool “get_accounting_integration_status” rewrote its description, which is the text the model reads security
- Tool “fix_compliance” rewrote its description, which is the text the model reads security
- Tool “create_report” rewrote its description, which is the text the model reads security
- Tool “correct_expenses” rewrote its description, which is the text the model reads security
- Tool “add_mileage_entry” rewrote its description, which is the text the model reads security
- Tool “add_income_from_file” rewrote its description, which is the text the model reads security
- Tool “add_income” rewrote its description, which is the text the model reads security
- Tool “add_cash_expense” rewrote its description, which is the text the model reads security
- Tool “scan_gmail_years” rewrote its description, which is the text the model reads security
- Tool “update_expense” rewrote its description, which is the text the model reads security
- Tool “submit_receipt” rewrote its description, which is the text the model reads security
- Tool “trace_document” rewrote its description, which is the text the model reads security
- New tool “get_setup_status” functional
- “search_expenses” added an optional parameter “includePaidWith” cosmetic
- “search_expenses” added an optional parameter “paymentStatus” cosmetic
- “get_scan_status” added an optional parameter “provider” cosmetic
- “get_scan_status” added an optional parameter “jobId” cosmetic
- “scan_gmail” added an optional parameter “provider” cosmetic
- “scan_gmail_years” added an optional parameter “provider” cosmetic
- “update_expense” added an optional parameter “expectedPaidWith” cosmetic
- “search_expenses” reworded the description of “clientEmail” cosmetic
- “search_expenses” reworded the description of “dateRange” cosmetic
- “list_reports” reworded the description of “clientEmail” cosmetic
- “list_client_invoices” reworded the description of “clientEmail” cosmetic
- “get_trip_suggestions” reworded the description of “clientEmail” cosmetic
- “get_subscription_audit” reworded the description of “dateRange” cosmetic
- “get_statement_import_status” reworded the description of “clientEmail” cosmetic
- “get_spending_summary” reworded the description of “dateRange” cosmetic
- “get_spending_summary” reworded the description of “clientEmail” cosmetic
- “get_report_details” reworded the description of “clientEmail” cosmetic
- “get_pnl” reworded the description of “dateRange” cosmetic
- “get_pnl” reworded the description of “clientEmail” cosmetic
- “get_per_tag_pnl” reworded the description of “dateRange” cosmetic
- “get_monthly_books_review” reworded the description of “clientEmail” cosmetic
- “get_mileage_summary” reworded the description of “dateRange” cosmetic
- “get_income_summary” reworded the description of “dateRange” cosmetic
- “get_expense_splits” reworded the description of “clientEmail” cosmetic
- “get_deep_analytics” reworded the description of “dateRange” cosmetic
- “get_credits_refunds” reworded the description of “clientEmail” cosmetic
- “get_client_invoice” reworded the description of “clientEmail” cosmetic
- “get_client_advance_balances” reworded the description of “clientEmail” cosmetic
- “create_report” reworded the description of “dateRange” cosmetic
- 30 Oct 26 0
- Tool “get_trip_suggestions” rewrote its description, which is the text the model reads security
- 27 Oct 26 0
- Tool “get_spreadsheet_url” rewrote its description, which is the text the model reads security
- Tool “add_cash_expense” rewrote its description, which is the text the model reads security
- Tool “add_income_from_file” rewrote its description, which is the text the model reads security
- Tool “correct_expenses” rewrote its description, which is the text the model reads security
- Tool “create_report” rewrote its description, which is the text the model reads security
- Tool “create_tag” rewrote its description, which is the text the model reads security
- Tool “fix_compliance” rewrote its description, which is the text the model reads security
- Tool “get_last_receipt_result” rewrote its description, which is the text the model reads security
- Tool “get_trip_suggestions” rewrote its description, which is the text the model reads security
- Tool “group_expenses” rewrote its description, which is the text the model reads security
- Tool “search_expenses” rewrote its description, which is the text the model reads security
- Tool “send_report_to_accounting” rewrote its description, which is the text the model reads security
- Tool “submit_receipt” rewrote its description, which is the text the model reads security
- Tool “update_expense” rewrote its description, which is the text the model reads security
- “get_trip_suggestions” added an optional parameter “area” cosmetic
- “get_trip_suggestions” added an optional parameter “dateRange” cosmetic
- “get_trip_suggestions” added an optional parameter “destination” cosmetic
- “get_trip_suggestions” added an optional parameter “includeCandidates” cosmetic
- “get_trip_suggestions” added an optional parameter “includePossibleAdditions” cosmetic
- “get_trip_suggestions” added an optional parameter “mode” cosmetic
- “get_trip_suggestions” added an optional parameter “offset” cosmetic
- “get_trip_suggestions” added an optional parameter “refresh” cosmetic
- “add_income_from_file” reworded the description of “rowEdits” cosmetic
- “create_report” reworded the description of “dateRange” cosmetic
- “get_client_advance_balances” reworded the description of “clientEmail” cosmetic
- “get_client_invoice” reworded the description of “clientEmail” cosmetic
- “get_credits_refunds” reworded the description of “clientEmail” cosmetic
- “get_deep_analytics” reworded the description of “dateRange” cosmetic
- “get_expense_splits” reworded the description of “clientEmail” cosmetic
- “get_income_summary” reworded the description of “dateRange” cosmetic
- “get_mileage_summary” reworded the description of “dateRange” cosmetic
- “get_monthly_books_review” reworded the description of “clientEmail” cosmetic
- “get_per_tag_pnl” reworded the description of “dateRange” cosmetic
- “get_pnl” reworded the description of “clientEmail” cosmetic
- “get_pnl” reworded the description of “dateRange” cosmetic
- “get_report_details” reworded the description of “checkFreshness” cosmetic
- “get_report_details” reworded the description of “clientEmail” cosmetic
- “get_spending_summary” reworded the description of “clientEmail” cosmetic
- “get_spending_summary” reworded the description of “dateRange” cosmetic
- “get_statement_import_status” reworded the description of “clientEmail” cosmetic
- “get_subscription_audit” reworded the description of “dateRange” cosmetic
- “get_trip_suggestions” reworded the description of “clientEmail” cosmetic
- “get_trip_suggestions” reworded the description of “limit” cosmetic
- “list_client_invoices” reworded the description of “clientEmail” cosmetic
- “list_reports” reworded the description of “clientEmail” cosmetic
- “search_expenses” reworded the description of “clientEmail” cosmetic
- “search_expenses” reworded the description of “dateRange” cosmetic
- “search_expenses” reworded the description of “query” cosmetic
- “submit_receipt” reworded the description of “filesToUpload” cosmetic
- “submit_receipt” reworded the description of “note” cosmetic
- “submit_receipt” reworded the description of “tag” cosmetic
- “submit_receipt” reworded the description of “uploadRefs” cosmetic
- 26 Oct 26 0
- Tool “group_expenses” rewrote its description, which is the text the model reads security
- Tool “search_expenses” rewrote its description, which is the text the model reads security
- New tool “create_tag” functional
- “search_expenses” added an optional parameter “tagAssignment” cosmetic
- “search_expenses” added an optional parameter “groupBy” cosmetic
- “search_expenses” added an optional parameter “countries” cosmetic
- “group_expenses” added an optional parameter “replaceExistingTags” cosmetic
- 23 Oct 26 0
- The server rewrote its instructions, which are the text every model session reads security
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Probed https://mcp.expensebot.ai/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=mcp.expensebot.ai | CN=YR2,O=Let's Encrypt,C=US | 8 Sept 2026 | 7 Dec 2026 | RSA 2048 | SHA256-RSA | 69f8cf9d11963ed221401116573c17f0a84 |
| SANs: mcp.expensebot.ai | ||||||
| CN=YR2,O=Let's Encrypt,C=US (CA) | CN=Root YR,O=ISRG,C=US | 3 Sept 2025 | 2 Sept 2028 | RSA 2048 | SHA256-RSA | 4ebd24947e24d394802d84a52fd5b319 |
| CN=Root YR,O=ISRG,C=US (CA) | CN=ISRG Root X1,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | RSA 4096 | SHA256-RSA | f24b6d17f9d9ad7cb1c9fea78782699f |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of mcp.expensebot.ai. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| ai. | present | 1814, 3799 | 8, 8 | Verified |
| expensebot.ai. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication No authorisation required
The endpoint answered without asking for a token. Anyone who knows the URL can reach it.
| Result | No authorisation required |
|---|---|
| HTTP status | 200 |
| Header | Value |
|---|---|
| strict-transport-security | max-age=63072000 |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://mcp.expensebot.ai/mcp | Verified | 200 | |
| http (plaintext) | http://mcp.expensebot.ai/mcp | HTTPS enforced | 308 | https://mcp.expensebot.ai/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
get_spending_summary ~174
Summarize the user's recorded expenses with totals and breakdowns by category, merchant, month, tag, source, or payment method. Supports date ranges, period comparisons, and total, count, or average metrics. Read-only. Income or profit questions: get_income_summary/get_pnl. Returns: { message, data: { total, breakdown?, comparison?, sampleMeta? } }.
| Name | Type | Req | Description |
|---|---|---|---|
| categories | array | – | Optional configured expense categories to include in the summary. |
| clientEmail | string | – | Accountants: accepted client email only. |
| dateRange | – | – | One period variant matching user wording. |
| groupBy | string | – | – |
| metric | string | – | – |
| query | string | – | Natural language question (e.g., 'how much did I spend in March', 'top merchants this quarter') |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|null | – | Inline analytics; null without sheet/data. |
| estimatedTime | number | – | Async: seconds. |
| jobId | string | – | Async branch only. |
| message | string | – | Narrative. |
| pollEndpoint | string | – | Async branch only. |
| pollInterval | number | – | Async: milliseconds. |
| response | string | – | Chat alias of message. |
| success | boolean | – | Async branch only. |
| type | string | – | Async analytics_pending: poll pollEndpoint/poll_analytics(jobId). |
No examples provided.
get_spreadsheet_url ~296
Return the master Google Sheet and authenticated workspace links, including the Year-End screen link. Show only 1–2 relevant returned links. Open/view/edit spreadsheet: Sheet. Receipt added: Review expenses + Sheet; income added: Review income + Sheet. Gmail scan/connection: Scan Gmail. Bank/card connection/reconciliation: Reconcile. Configuration: Automation Hub/General Settings. Category/G/L/account codes: Category management. Client/project/trip groups: Group management. Personal classification: Personal rules. Client billing: use returned clientBillingHandoffs for the current step: manageClients (client list), tagReadyExpenses (blank/default-Business rows), createClientReport (report by assigned group). Named client's exact grouping: search_expenses then group_expenses. Google Photos: returned authenticated picker with consent. Receipt storage: returned Drive folder only; never invent/request a folder ID. Complete unambiguous cash expense/mileage: direct write tool. Multiple/incomplete expenses, credits/refunds, tax/tip/per diem or visual review: Manual expense. Route/repeated/calendar/rideshare mileage, per diem or review: Mileage and travel. Income file without chat attachment or complex review: Import income (previews every row). Team setup: returned role-aware handoff (solo owner: Add teammates; owner/co-admin: Team Management); explain owner-access requirements. Complex reports: Create report. Read-only; no row changes.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| dashboardUrl | string | yes | – |
| data | object | yes | – |
| gmailActionNeededUrl | string | yes | – |
| gmailScanUrl | string | yes | – |
| message | string | yes | – |
| reportsUrl | string | yes | – |
| reviewExpensesUrl | string | yes | – |
| reviewIncomeUrl | string | yes | – |
| spreadsheetId | string | yes | – |
| spreadsheetUrl | string | yes | – |
| success | boolean | yes | – |
| yearEndUrl | string | – | Authenticated Year-End screen link. |
No examples provided.
get_statement_import_status ~93
Check 'Did my statement finish importing?' for at most five jobs. Returns status and authenticated review link. Extraction isn't saved; read/save jobs may overlap, so counts aren't statement totals. No job found doesn't prove no import; older non-job imports are excluded. Read-only: never uploads, parses, saves, retries, or recovers.
| Name | Type | Req | Description |
|---|---|---|---|
| clientEmail | string | – | Accountants: accepted client email only. |
| Name | Type | Req | Description |
|---|---|---|---|
| availability | string | yes | – |
| imports | array | yes | – |
| limitations | array | yes | – |
| links | object | yes | – |
| status | string | yes | – |
| success | boolean | yes | – |
No examples provided.
get_subscription_audit ~117
Find recurring subscriptions, duplicate charges, price increases and trial-conversion suspects in recorded expenses, optionally by cost (e.g. over $20/month). Returns message/data with recurring, duplicates, priceIncreases, trialConversions, totalMonthlyCost and sampleMeta.
| Name | Type | Req | Description |
|---|---|---|---|
| dateRange | – | – | One period variant matching user wording. |
| focus | string | – | Narrow the audit to a single category (default: all) |
| query | string | – | Natural language subscription question (e.g., 'find duplicate subscriptions', 'price increases this year') |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object|null | – | – |
| message | string | – | – |
| success | boolean | – | Present only on the error branch (out of scope) / async path. |
No examples provided.
get_trip_suggestions ~416
Review trips from the Review Expenses Find engine. Default is high-confidence only; for the trip list set includeCandidates:true (real trips first, second homes and regular spots grouped); page with offset while remaining > 0. Name a trip by destination (e.g. Copenhagen); mode:area lists expenses in a country or city. Show dates, recorded locations, count and uncertainty; locations are not travel or client proof. Copy exact selections to group_expenses with a user-chosen trip/client name and confirm:false, then request approval. Possible additions stay out unless the user includes them (includePossibleAdditions:true). Merge/deduplicate selections for one destination; separate destinations need separate confirmations. Preserve existing assignments, Personal and read-only rows. Never infer clients or countries from currency. clientEmail mode is read-only.
| Name | Type | Req | Description |
|---|---|---|---|
| area | string | – | Country or city for mode area, e.g. "Denmark" or "Copenhagen, Denmark". Ambiguous places return candidates to ask about. |
| clientEmail | string | – | Accountants: accepted client email only. |
| dateRange | object | – | Inclusive period to find overlapping trips; returns full trip membership, including boundary dates outside the period. |
| destination | string | – | Trip the user named, e.g. "Copenhagen". Several matches return them for clarification; never guess. |
| includeCandidates | boolean | – | Default false: high-confidence only. True: also show uncertain candidates without saving recommendations or changing expenses. |
| includePossibleAdditions | boolean | – | Default false. True only when the user explicitly asks to include the separate possible additions in the selection. |
| limit | integer | – | Result cap (default 3, max 10), not an exhaustive list; see remaining. |
| mode | string | – | episode (default): trips. area: every expense located in the area. |
| offset | integer | – | Skip this many results to page through remaining trips. |
| refresh | boolean | – | Recheck current recorded expenses for suggested trips; never change their tags. |
| Name | Type | Req | Description |
|---|---|---|---|
| count | integer | – | – |
| message | string | – | – |
| proposals | array | – | Read-only trip proposals; accepting one continues through group_expenses. |
| remaining | integer | – | More matching trips available with a larger offset. |
| success | boolean | yes | – |
No examples provided.
group_expenses ~470
Group exact expenses for a user-named client/project/trip/job, with an optional report. Reuse existing groups; propose new only if needed. Full expenseIds from search_expenses. Preserve assignments unless explicitly replacing (replaceExistingTags:true). First call previews even with early confirm:true: show rows, count, totals, group, exclusions/conflicts; ask approval once, then repeat identical operationId/selection with confirm:true. Group-and-report: createReport:true on confirmation; never a separate broader create_report query. excludePersonal:true removes Personal-tagged and Personal-category rows before preview, preserving markers. Skip rows on other ordinary reports; no matches: no duplicate, link to Reports. Exact report/Bill Client links. Say group, not tag. Preview totals are provisional; use terminal count/total/currency. Bill Client opens a reviewed flow, not a created/sent/confirmed invoice. Sharing requires share_report recipient confirmation. No unsolicited tax/substantiation advice or check_compliance/get_report_details/tax calls unless explicitly requested.
| Name | Type | Req | Description |
|---|---|---|---|
| approveNewGroup | boolean | – | True only when the preview says a new group is required. |
| confirm | boolean | – | Omit/false for preview; true only after explicit approval. |
| createReport | boolean | – | Create a report from the exact eligible grouped expenses. |
| excludePersonal | boolean | – | Exclude Personal-tagged and Personal-category expenses from both grouping and the exact report. |
| excludedCategories | array | – | Expense categories to exclude before preview and grouping. |
| excludedTags | array | – | Existing groups to exclude before preview and grouping. |
| group | object | – | The user-named destination group to apply to every eligible selected expense. |
| operationId | string | yes | Stable idempotency key generated once for the preview and reused unchanged. |
| replaceExistingTags | boolean | – | Default false keeps existing assignments; true only after the user explicitly asks to replace; preview shows both. |
| reportTitle | string | – | Optional title when createReport is true; otherwise ExpenseBot derives one from the group. |
| selection | object | – | Exact expenses returned by search_expenses and approved for this bounded operation. |
| status | boolean | – | Read operation status using operationId. |
| undo | boolean | – | Undo a completed grouping within its undo window. |
| Name | Type | Req | Description |
|---|---|---|---|
| candidates | array | – | – |
| confirmation | object | – | – |
| creationStatus | string | – | – |
| exclusions | object | – | – |
| finalAnswer | string | – | – |
| group | object | – | – |
| manifest | object | – | – |
| message | string | – | – |
| operationId | string | – | – |
| preview | object | – | – |
| report | object | – | – |
| reportsUrl | string | – | – |
| requiresConfirmation | boolean | – | – |
| requiresNewGroupApproval | boolean | – | – |
| responseGuidance | string | – | – |
| reviewExpensesUrl | string | – | – |
| status | string | yes | – |
| success | boolean | yes | – |
| suggestedTag | string | – | – |
| undo | object | – | – |
No examples provided.
list_categories ~61
List the user's configured expense categories and billing accounts. Use this BEFORE calling tools that need a category (add_cash_expense, add_mileage_entry, create_report) so you pass the user's actual category names, not guesses. Returns the live list from their spreadsheet.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| billingAccounts | array | – | Billing/card accounts, when configured. |
| categories | array | yes | Expense categories for the user. |
| success | boolean | yes | – |
No examples provided.
list_client_close_readiness ~153
Accountant-only month-end overview of accepted client workspaces. Returns page-level readiness and affected-client category counts with an authenticated Client Reports link. Use for 'how many clients need attention before month end'. No client identities, amounts, or individual items are returned; select a client in ExpenseBot to resolve items. Unavailable sources remain unknown. Each page uses the current roster; do not combine pages into a verified total.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Client workspaces per page; default and maximum 5. |
| page | integer | – | Page number; starts at 1. Use nextPage from the previous result. |
| period | string | – | Calendar month YYYY-MM; defaults to the last completed UTC month. |
| Name | Type | Req | Description |
|---|---|---|---|
| asOf | string | yes | – |
| categories | array | yes | – |
| coverage | string | yes | – |
| evaluatedClientCount | integer | yes | – |
| limitations | array | yes | – |
| links | object | yes | – |
| message | string | yes | – |
| pageInfo | object | yes | – |
| period | string | yes | – |
| scope | string | yes | – |
| statusCounts | object | yes | – |
| success | boolean | yes | – |
| unavailableCandidateCount | integer | yes | – |
No examples provided.
list_client_invoices ~190
List the user's issued client invoices (accounts receivable) — who owes them money, how much, and when it is due. Examples: 'which invoices are outstanding', 'what does Acme still owe me', 'any overdue invoices', 'how much am I waiting to get paid'. status accepts 'active' (default), 'open', 'overdue', 'needs_review', 'paid', 'void', 'superseded', or 'all'. Returns invoice numbers, status, totals by currency, delivery state, and private document links. Read-only.
| Name | Type | Req | Description |
|---|---|---|---|
| clientEmail | string | – | Accountants: accepted client email only. |
| clientName | string | – | Optional: exact client name (case-insensitive). |
| limit | number | – | Max invoices to return (default 25, max 100). |
| status | string | – | Filter by invoice status (default active/outstanding). |
| Name | Type | Req | Description |
|---|---|---|---|
| invoices | array | yes | – |
| success | boolean | yes | – |
No examples provided.
list_income_categories ~46
List ExpenseBot's fixed income tax categories. Unlike Expense Accounts, these are not user-configured. Use this BEFORE calling add_income so you pass an exact canonical category instead of guessing.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| categories | array | yes | – |
| legacy | array | – | Deprecated income categories still accepted on read. |
| notes | string | – | – |
| success | boolean | yes | – |
No examples provided.
list_reports ~134
List the user's expense reports with pagination. Filter by status (All, Draft, Submitted, Shared). Each exact report includes its app, Bill Client, and accounting handoff URLs. Use the matching accounting URL only when the user explicitly asks to send or export that report; the app keeps organization, mapping, preview, and final confirmation.
| Name | Type | Req | Description |
|---|---|---|---|
| clientEmail | string | – | Accountants: accepted client email only. |
| filter | string | – | Optional report-status filter; All returns every authorized status. |
| limit | integer | – | Maximum reports to return on this page. |
| page | integer | – | One-based results page to return. |
| Name | Type | Req | Description |
|---|---|---|---|
| creationStatus | string | yes | Provenance of the listing, e.g. "existing_only". |
| filter | string | – | – |
| limit | integer | – | – |
| page | integer | – | – |
| reports | array | – | Present when the user has reports. |
| responseGuidance | string | – | – |
| success | boolean | yes | – |
No examples provided.
list_tags ~83
List the user's configured groups. ExpenseBot stores clients, projects, project codes, properties, and trips as tags (for example 'Client: Acme', 'Vegas Trip', or 'Property: 123 Main'). Use this when the user asks 'what groups/projects/clients do I have?' and before filtering, grouping, or reporting when the intended existing name is unclear.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| success | boolean | yes | – |
| tags | array | yes | Client / project / trip groups (Column K values). |
No examples provided.
mark_client_invoice_paid ~130
Mark an issued client invoice as paid after explicit confirmation. Requires a strict calendar-valid paidDate in YYYY-MM-DD format. This updates the accounts-receivable invoice record only; it never creates or moves an Income row. Record the actual payment separately or link an existing Income row.
| Name | Type | Req | Description |
|---|---|---|---|
| invoiceId | string | yes | Stable invoice ID from list_client_invoices. |
| paidAmount | number | – | Optional amount received. |
| paidDate | string | yes | Calendar-valid payment date in YYYY-MM-DD format. |
| paidVia | string | – | Optional payment method or source, such as bank transfer or check. |
| Name | Type | Req | Description |
|---|---|---|---|
| incomeRowCreated | boolean | yes | – |
| invoiceId | string | yes | – |
| invoiceNumber | string|null | – | – |
| message | string | yes | – |
| paidAmount | number|null | yes | – |
| paidDate | string | yes | – |
| paidVia | string | yes | – |
| status | string | yes | – |
| success | boolean | yes | – |
No examples provided.
omit_expenses ~314
Omit exact recorded expenses from reports, insights and exports, or restore them (leave out, exclude, don't count). First search_expenses for full expenseId values. A grounded preview is automatic with confirm omitted/false: show exact rows (date, merchant, amount), count and skips, ask once, then repeat identical operationId, action and expenseIds with confirm:true. Premature confirmation returns preview. Omit is reversible and keeps the spreadsheet row; never deletes. Rows on a submitted report are skipped and stay on it. Act only on rows the user chose; never decide rows are duplicates or personal. Recategorize: correct_expenses. Result gives applied/skipped/conflicted/failed counts and Undo. Over 100 rows: https://www.expensebot.ai/review-expenses?source=mcp.
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | – | omit hides rows from reports, insights and exports; restore puts omitted rows back. |
| confirm | boolean | – | Omit/false previews only; true only after the user approves the preview. |
| expenseIds | array | – | Full expenseId (Column Q Receipt ID) values from search_expenses; never dates, rows or merchants. |
| operationId | string | yes | Idempotency key; generate once and reuse unchanged to confirm. |
| reason | string | – | The user's own short reason, shown in the Omitted view. Never invent one. |
| status | boolean | – | Read status by operationId. |
| undo | boolean | – | Undo within the Undo window. |
| Name | Type | Req | Description |
|---|---|---|---|
| counts | object | – | – |
| finalAnswer | string | – | – |
| operationId | string | – | – |
| preview | object | – | – |
| reviewExpensesUrl | string | – | – |
| skipped | object | – | By reason: ALREADY_OMITTED, ALREADY_ACTIVE, ON_REPORT, NOT_FOUND, SPLIT_OR_SHARED_ID, ENTITLEMENT. |
| status | string | yes | – |
| success | boolean | yes | – |
| undo | object | – | – |
No examples provided.
parse_expense ~96
Parse a natural language expense description into structured fields. Does NOT add the expense: returns fields to show the user; once they approve, save with add_cash_expense. Example: "Lunch at Chipotle $15.50 today" → {merchant: "Chipotle", total: 15.50, ...}
| Name | Type | Req | Description |
|---|---|---|---|
| text | string | yes | Natural language expense (e.g., "Coffee at Starbucks $6.50 yesterday") |
| Name | Type | Req | Description |
|---|---|---|---|
| categoryNames | array | yes | – |
| expenses | array | yes | – |
| success | boolean | yes | – |
| validationErrors | array | yes | – |
No examples provided.
prepare_client_invoice ~370
Prepare a client invoice from a saved ExpenseBot report without creating it. Reads canonical report rows, allocates a unique invoice number, verifies the client ledger identity and advance, and returns exact totals plus a short-lived preparationId. Call this first, show the preview to the user, then call create_client_invoice after explicit confirmation. It reserves the invoice number and preview for 30 minutes but creates no invoice, document, Income row, email, or payment.
| Name | Type | Req | Description |
|---|---|---|---|
| advanceApplied | number | – | Verified client advance to apply against this invoice. |
| billToEmail | string | – | Optional client email printed on the invoice. This does not send email. |
| clientAddress | string | – | Optional billing address printed in the invoice's Bill To section. |
| clientName | string | yes | Full client or business name shown on the invoice. |
| customLineItems | array | – | Optional fee/service lines. They are taxed but never marked up. |
| invoiceNumber | string | – | Optional custom invoice number. ExpenseBot allocates one when omitted. |
| issueDate | string | yes | Calendar-valid invoice date in YYYY-MM-DD format. |
| markupPct | number | – | Markup applied only to rebilled expense rows. |
| mentionSupportingReceipts | boolean | – | When true, note on the invoice that supporting receipts are available. |
| paymentTerms | string | – | Invoice due terms. Defaults to the client's billing profile or net30. |
| receiptIds | array | – | Optional exact report receipt IDs. Defaults to every current report expense. |
| reportId | string | yes | Saved ExpenseBot report ID to invoice. |
| taxLabel | string | – | Tax label such as HST, GST, or VAT. |
| taxPct | number | – | Tax percentage applied after markup and custom line items; use 0 for no tax. |
| Name | Type | Req | Description |
|---|---|---|---|
| expiresAt | string | yes | – |
| preparationId | string | yes | – |
| preview | object | yes | – |
| success | boolean | yes | – |
No examples provided.
process_gmail_receipts ~108
Process specific Gmail emails as receipts when the user supplies Gmail message IDs; to find receipts use scan_gmail. No server preview: on call each email is converted to PDF, extracted by AI and added to the user's expense spreadsheet. Max 25 emails per request. Requires Gmail connected in ExpenseBot.
| Name | Type | Req | Description |
|---|---|---|---|
| accountEmail | string | – | Optional: which Gmail account to use (for users with multiple linked accounts) |
| emailIds | array | yes | Gmail message IDs to process as receipts |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object | – | – |
| emailCount | integer | – | – |
| error | string | – | – |
| message | string | yes | – |
| processInfo | object | – | – |
| processedItems | array | – | – |
| reviewExpensesUrl | string | – | – |
| spreadsheetUrl | string|null | – | – |
| submissionId | string | – | – |
| success | boolean | yes | – |
No examples provided.
request_accounting_integration ~115
Request an exact accounting package only after checking reviewed direct/import-file destinations and finding no match. Do not use this for a listed or Beta destination or general compatibility. A confirmation-gated write: after user approval, creates one deduplicated request bound to the authenticated account and emails ExpenseBot's internal team. Does not create an integration or immediate availability. For accepted/already-recorded requests, say ExpenseBot will email an update within one week.
| Name | Type | Req | Description |
|---|---|---|---|
| packageName | string | yes | Exact accounting package requested by the user. |
| Name | Type | Req | Description |
|---|---|---|---|
| duplicate | boolean | yes | – |
| message | string | yes | – |
| packageName | string | yes | – |
| success | boolean | yes | – |
No examples provided.
scan_gmail ~212
Trigger a background Gmail scan to discover and process receipt emails from the last ~60 days (default). No server preview: starts on call and runs in the background; the user gets an email summary when done. Like clicking "Find Receipts in Gmail" in the UI. For whole PAST YEARS (e.g. 2023, or 2020-2022) use scan_gmail_years instead; to check a scan's progress use get_scan_status. With provider:outlook, returns an access-gated screen handoff only; no scan starts.
| Name | Type | Req | Description |
|---|---|---|---|
| accountEmail | string | – | Optional: which Gmail account to scan |
| endDate | string | – | Optional: explicit end date (YYYY-MM-DD) |
| lookbackDays | integer | – | How many days back to scan (default 60, max depends on subscription) |
| provider | string | – | Default Gmail. |
| startDate | string | – | Optional: explicit start date (YYYY-MM-DD) instead of lookbackDays |
| Name | Type | Req | Description |
|---|---|---|---|
| _metadata | object | – | – |
| data | object | – | – |
| message | string | – | – |
| orchestrated | boolean | – | – |
| provider | string | – | – |
| reviewExpensesUrl | string|null | – | – |
| scanInProgress | boolean | – | – |
| scanInitiated | boolean | – | – |
| sessionId | string | – | – |
| spreadsheetUrl | string|null | – | – |
| status | string | – | – |
| submissionId | string | – | – |
| success | boolean | yes | – |
No examples provided.
scan_gmail_years ~251
provider:outlook returns a handoff; never starts. Scan completed Gmail periods for receipts. In eligible split-tax-year accounts, a number is the period's ending year (2025 = 2024–25 tax year); otherwise it is a calendar year. Use returned tax-period labels and inclusive ISO bounds. Long-running: the first eligible period starts immediately; the rest queue one at a time (each full period typically takes hours; the app may close). Preview without confirmStart (no scan starts), ask the user to confirm, then start with confirmStart:true. For recent receipts (~60 days), use scan_gmail. The in-progress period cannot be year-scanned; use get_scan_status for progress.
| Name | Type | Req | Description |
|---|---|---|---|
| accountEmail | string | – | Optional: which connected Gmail inbox to scan (multi-inbox users). Defaults to the primary. |
| confirmStart | boolean | – | Omit or false = preview only (no scan starts). Must be exactly true to start scanning. |
| provider | string | – | Default Gmail. |
| years | array | yes | Completed periods; ending year for eligible tax-year accounts (2025 = 2024–25), calendar year otherwise. Max 10. |
| Name | Type | Req | Description |
|---|---|---|---|
| account | string | – | – |
| alreadyQueued | array | – | – |
| alreadyScanned | array | – | – |
| archiveThroughYear | integer | – | – |
| eligible | array | – | – |
| gmailUrl | string | – | – |
| message | string | yes | – |
| notEligible | array | – | – |
| preview | boolean | – | – |
| provider | string | – | – |
| queuedYears | array | – | – |
| scanInitiated | boolean | – | – |
| scanning | array | – | – |
| startedYear | integer|null | – | – |
| success | boolean | yes | – |
No examples provided.
search ~111
Search the user's ExpenseBot data — expenses, reports, and knowledge base. Returns matching items with id, title, and url. Use the returned id with the `fetch` tool to get full details. Powers Deep Research and Company Knowledge integrations. For filtered expense lists, totals or expenseIds to edit use search_expenses; for help articles use search_knowledge.
| Name | Type | Req | Description |
|---|---|---|---|
| query | string | yes | Natural language search (e.g., 'Uber rides in March', 'Q1 client report', 'mileage Acme') |
| Name | Type | Req | Description |
|---|---|---|---|
| results | array | yes | – |
No examples provided.
search_expenses ~581
Search spreadsheet expenses by category, merchant, dates, amount or tags. When hasMore, reuse nextCursor with identical filters; avoid overlapping ranges. Optional query does deterministic non-embedding recall over merchant, city/location, Notes (e.g. receipt items, delivery source, payer or business purpose), Tag and category; ANDed with structured filters. Query examples: Tribeca restaurant, client dinner note. Results include matchedFields, matchReason and exact expenseId. expenseId is the exact durable Receipt ID for update_expense. paymentStatus is bookkeeping only, never bank settlement proof. For card/account nicknames use includePaidWith:true; page-only labels cannot filter all expenses. Country/client review: groupBy:country needs explicit YYYY-MM-DD bounds, at most 100 matches; narrow oversized ranges. Use configured travel categories; foreign locations do not prove travel. Keep unknown countries separate; ask about ambiguous places, never infer from currency. Country review allows categories/merchants/tags/countries/tagAssignment, no query or pagination. Show counts and per-currency totals; copy selectionItems (tag/date/location expectations) to group_expenses once a destination is chosen.
| Name | Type | Req | Description |
|---|---|---|---|
| categories | array | – | Filter by expense categories (e.g., ['Travel', 'Meals']) |
| clientEmail | string | – | Accountants: accepted client email only. |
| countries | array | – | Country-review filter: supported country names/codes, or unknown. Never infer a country from currency or an ambiguous city. |
| cursor | string | – | Opaque nextCursor returned by the previous search_expenses page. Reuse the same filters; never construct or edit this value. |
| dateRange | – | – | One period variant matching user wording. |
| groupBy | string | – | Read-only country review; requires explicit dateRange.start/end and at most 100 matches. |
| hasReceipt | boolean | – | When true, return only expenses with a receipt link. When false, return only expenses without one. |
| includePaidWith | boolean | – | Page labels only; unavailable differs from blank. No label filter. |
| limit | integer | – | Results per page (default 20, maximum 50) |
| maxAmount | number | – | Maximum expense amount |
| merchants | array | – | Filter by merchant names (e.g., ['Uber', 'Starbucks']) |
| minAmount | number | – | Minimum expense amount |
| paymentStatus | string | – | Bookkeeping prefix filter before pagination; not bank settlement. Ordinary search only. |
| query | string | – | Optional case-insensitive keyword recall over the fields listed in the tool description; ANDed with structured filters. |
| tagAssignment | string | – | Country review: unassigned = blank/Business; no_client = no canonical client tag (incl. project/trip tags). Neither implies business use. |
| tags | array | – | Filter by tags |
| Name | Type | Req | Description |
|---|---|---|---|
| count | integer | yes | Rows matched by the filters. |
| countryGroups | array | – | Complete bounded country review; unknown locations remain separate. |
| expenses | array | yes | Matching expense rows, newest first, paginated. |
| hasMore | boolean | – | – |
| message | string | – | – |
| nextCursor | string|null | – | Opaque signed continuation; reuse with identical filters. |
| pageInfo | object | – | – |
| queryApplied | string | – | – |
| total | number|null | yes | Home-currency sum in normal search; null in country review. Use countryGroups totalsByCurrency, never sum currencies. |
| totalMatched | integer | – | Present for free-text searches. |
No examples provided.
search_knowledge ~161
Search ExpenseBot's complete product and help knowledge base. Use this before guessing when the user asks how a feature works, what ExpenseBot supports, or needs setup, billing, Gmail, scan, report, workflow, or troubleshooting instructions. Set fullAnswer:true on the first call when the user asks for complete, detailed, or step-by-step instructions. Use the default excerpt mode for discovery and quick answers; if an excerpt is truncated, call again with fullAnswer:true before presenting complete instructions. Each result has a stable id.
| Name | Type | Req | Description |
|---|---|---|---|
| fullAnswer | boolean | – | True on the first call for complete or step-by-step instructions. |
| limit | integer | – | Number of ranked matching articles to return (1-10). |
| query | string | yes | Search terms |
| Name | Type | Req | Description |
|---|---|---|---|
| results | array | yes | – |
| success | boolean | yes | – |
No examples provided.
send_report_to_accounting ~360
Preview then post an owner's report to accounting. Step 1: provider/reportId, optional mode/mappings, NO confirm. Reads live report/destination, enforces Omit/Personal/split/date/currency rules and Zoho bank-feed checks; returns complete frozen proposal + proposalId, posts nothing. Show complete proposal and ask approval. Step 2: ONLY provider/proposalId/confirm:true, never mappings. Revalidates live state and rejects changed reports/mappings; account-bound proposal only. No client acting. Agent posting: Zoho Books (zoho_books) only. QuickBooks Online/Xero/Wave/FreeAgent cannot yet freeze/revalidate shareReport plans; use their web flows.
| Name | Type | Req | Description |
|---|---|---|---|
| accountMappings | object | – | Step 1 only: ExpenseBot category to live destination account ID overrides. |
| confirm | boolean | – | Step 2 only: true posts the exact staged proposal. No other options may change. |
| forceRepush | boolean | – | Step 1 only: explicitly include disclosed uncertain prior outcomes in the frozen proposal. |
| mode | string | – | Step 1 only (Zoho Books): automatic document treatment, paid expenses, or bills. |
| proposalId | string | – | Step 2 only: proposalId returned by the read-only preview. |
| provider | string | yes | Accounting destination provider. Agent-driven posting is currently available only for Zoho Books. |
| reportId | string | – | Step 1 only: ExpenseBot report ID owned by the signed-in account. |
| reportingTagMappings | object | – | Step 1 only: ExpenseBot tag to live destination reporting-tag option. |
| taxMappings | object | – | Step 1 only: observed tax-rate string to live destination tax ID overrides. |
| Name | Type | Req | Description |
|---|---|---|---|
| confirmationContract | string | – | – |
| confirmationQuestion | string | – | – |
| confirmationRequired | boolean | – | – |
| counts | object | – | – |
| created | integer | – | – |
| expiresAt | string | – | – |
| finalAnswer | string | – | – |
| idempotentReplay | boolean | – | – |
| matchedExisting | integer | – | – |
| omittedExpenses | integer | – | – |
| organization | object | – | – |
| phase | string | yes | – |
| proposalId | string | yes | – |
| provider | string | yes | – |
| reconciliationRequired | boolean | – | – |
| reportId | string | – | – |
| responseGuidance | string | – | – |
| skippedAlreadyPushed | integer | – | – |
| success | boolean | yes | – |
| units | array | – | – |
No examples provided.
share_report ~129
Share one existing expense report with user-named recipients. No server preview: shares and emails on call. Default to reviewer: they can open and edit that report's Google Sheet, inspect receipts, comment, approve, or request changes, but cannot act for the owner or use accounting integrations. Use accountant only when the user explicitly asks for ongoing accounting access; it creates the established accountant relationship and broader report-management workflow.
| Name | Type | Req | Description |
|---|---|---|---|
| recipientRole | string | – | Use reviewer for report-only approval. Use accountant only for explicit ongoing accountant access. |
| recipients | array | yes | – |
| reportId | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| finalAnswer | string | – | – |
| message | string | yes | – |
| recipientRole | string | yes | – |
| responseGuidance | string | – | – |
| sharedWith | array | yes | – |
| success | boolean | yes | – |
No examples provided.
submit_receipt ~447
Process receipt images/PDFs, including 'log this', 'save this receipt', 'expense this', 'add this to my expenses' or a shared receipt/invoice photo. Starts on call (no server preview); AI extracts vendor, amount, date, tax and category (usually 1–3 minutes; longer for PDFs/batches); poll get_last_receipt_result with the returned submissionId. Mixed images/PDFs work. Required for PDFs; use this flow for large files/batches: call filesToUpload for EVERY file; PUT each ONE AT A TIME to signed URLs, report file/count progress, then call ONCE with all uploadRefs as one batch, never once per file. photo accepts one ChatGPT image/PDF; photoBase64 only for one small image without file references. note maps to Notes L, tag to Tag K; batch defaults apply to all files and uploadRefs items may override.
| Name | Type | Req | Description |
|---|---|---|---|
| filename | string | – | Optional filename (e.g., 'lunch_receipt.jpg') |
| filesToUpload | array | – | Every file the user provided, in one call. Returns signedUrl + uploadRef per file; upload each, then call with uploadRefs. |
| mimeType | string | – | MIME type of the file (default: image/jpeg) |
| note | string | – | Batch-level note for every file; a file may override it. Stored in the Notes column (L). |
| photo | object | – | Single attached receipt image or PDF supplied by ChatGPT. For multiple files or large files, use filesToUpload and uploadRefs instead. |
| photoBase64 | string | – | Legacy fallback for MCP clients that send one small image as complete base64 data. ChatGPT should use photo or uploadRefs instead. |
| tag | string | – | Batch-level project or client tag for every row; a file may override it. Stored in the Tag column (K). |
| uploadRef | string | – | Single-file shorthand for uploadRefs. Use uploadRefs when there is more than one file. |
| uploadRefs | array | – | Every uploadRef from the filesToUpload step, as ONE batch. If any file fails validation nothing is processed. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object | – | – |
| fileCount | integer | – | – |
| files | array | – | – |
| message | string | – | – |
| reviewExpensesUrl | string | – | – |
| spreadsheetUrl | string|null | – | – |
| status | string | – | – |
| statusCode | integer | – | – |
| submissionId | string | – | – |
| success | boolean | yes | – |
No examples provided.
trace_document ~202
Read a receipt/invoice/forwarded email/Gmail receipt/PDF's lineage timeline: missing, skipped, income-routed, deduped or duplicate-removed documents. Not Gmail scan-job status/progress/completion (running/queued/finished/stuck): use get_scan_status; a scan is not a document.
| Name | Type | Req | Description |
|---|---|---|---|
| days | integer | – | How many days back to search. |
| limit | integer | – | Maximum lineage events to return. |
| messageId | string | – | Gmail message ID if known. |
| outcome | string | – | Optional processing outcome filter. |
| query | string | – | Merchant, sender, subject, invoice number, or phrase to search for, e.g. 'Blue Rocket', 'Driversnote', 'Uber receipt'. |
| receiptId | string | – | ExpenseBot receipt/invoice ID if known, e.g. IR-123, RO-abc, RR-456. |
| threadId | string | – | Gmail thread ID if known. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object | yes | – |
| message | string | yes | – |
| success | boolean | yes | – |
| type | string | yes | – |
No examples provided.
update_expense ~319
Update a single existing expense row's category, tag, merchant or business purpose (e.g. 'recategorize expense X to Meals', 'tag it Client – Acme'). Identify it only by the exact expenseId from search_expenses (the full Receipt ID from Column Q); never a date, displayed number or sheet row number. Two-phase: calls with confirm omitted/false return a current→proposed preview and change nothing; after user confirmation, confirm:true applies it. If the expense is not found, search once for a current exact expenseId; never retry the same stale ID. If a business-purpose update exceeds the Notes capacity, stop and send the user to https://www.expensebot.ai/review-expenses?source=mcp. fields.paidWith edits only the optional Paid with bookkeeping label (no status/settlement change; blank clears it); reuse expectedPaidWith from the preview on confirm. Amounts, dates and raw notes require Review Expenses. Does not create or delete rows. Same change on several rows or attendees: correct_expenses; leave rows out: omit_expenses.
| Name | Type | Req | Description |
|---|---|---|---|
| confirm | boolean | – | Omit or false = preview only (no write). Must be exactly true to apply the change. |
| expectedPaidWith | object | – | – |
| expenseId | string | yes | Exact full Receipt ID from Column Q, returned as expenseId by search_expenses. |
| fields | object | yes | Partial update object. Include one or more of these optional keys; omit every field that should remain unchanged. |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object | yes | – |
| finalAnswer | string | – | – |
| message | string | yes | – |
| responseGuidance | string | – | – |
| success | boolean | yes | – |
No examples provided.
whatif_afford ~123
Can I afford $X/month? Recomputes the user's Safe Monthly Draw (how much they can safely pay themselves) with an added recurring monthly cost, and returns a yes/tight/no verdict plus the before/after numbers. Use for questions like 'can I afford a $500/mo hire' or 'what if I add a $200/mo software subscription'. Requires at least 3 months of income history — otherwise returns insufficient_data rather than a guess.
| Name | Type | Req | Description |
|---|---|---|---|
| deltaMonthly | number | yes | The new recurring monthly cost being considered, in the user's home currency |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object | – | Scenario assumptions, evidence and outcome. |
| message | string | – | Narrative; absent without template/evidence. |
| success | boolean | yes | – |
No examples provided.
whatif_client ~154
What if a client pays late or leaves? mode='late30' shifts that client's OPEN invoice amounts out of the near-term expectation mode='gone' removes that client's trailing monthly income contribution and recomputes Safe Draw against the reduced baseline. Use for questions like 'what if Acme Corp pays 30 days late' or 'what happens if I lose my biggest client'. Client identity is matched against the Income tab's tag/source/description fields — best effort, not a guaranteed match.
| Name | Type | Req | Description |
|---|---|---|---|
| clientName | string | yes | The client's name as it appears on invoices or income rows |
| mode | string | yes | 'late30' = shift open invoices 30 days late; 'gone' = client stops paying entirely |
| Name | Type | Req | Description |
|---|---|---|---|
| data | object | – | Scenario assumptions, evidence and outcome. |
| message | string | – | Narrative; absent without template/evidence. |
| success | boolean | yes | – |
No examples provided.
whatif_tax_setaside ~65
What should I set aside for taxes? Returns the monthly tax set-aside estimate already computed for Safe Monthly Draw. Flat-rate estimate (default 30%) against trailing income minus recurring + variable spend. Use for 'how much should I set aside for taxes this month'.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| data | object | – | Scenario assumptions, evidence and outcome. |
| message | string | – | Narrative; absent without template/evidence. |
| success | boolean | yes | – |
No examples provided.
How do I install the ExpenseBot MCP server?
ExpenseBot is a hosted endpoint at https://mcp.expensebot.ai/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · mcp.expensebot.ai
claude mcp add --transport http totesmagotes-mcp-server-auth 'https://mcp.expensebot.ai/mcp'
What is the ExpenseBot MCP server?
ExpenseBot is an MCP server listed in the public MCP registry as io.github.TotesMagotes/mcp-server-auth. Receipt ingestion, Gmail capture, expense analysis, and reviewed reports for AI-agent workflows. This page covers its hosted endpoint (https://mcp.expensebot.ai/mcp).
Is the ExpenseBot MCP server safe to use?
ExpenseBot scores 75 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the ExpenseBot MCP server expose?
ExpenseBot exposes 65 tools: get_setup_status, complete_setup, search_expenses, get_spending_summary, get_deep_analytics, and 60 more. Their descriptions and schemas cost roughly 13,081 tokens of context every time the server is loaded.
Does the ExpenseBot MCP server require authentication?
No. We connected to ExpenseBot without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.
Is the ExpenseBot MCP server still maintained?
ExpenseBot is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.