ExpenseBot

io.github.TotesMagotesPublished by GitHub account TotesMagotesv0.6.26Updated Oct 27, 2026

Receipt ingestion, Gmail capture, expense analysis, and reviewed reports for AI-agent workflows.

VerifiedStreamable HTTPWeb executableProductivity & WorkflowFinanceBusiness & Commerce

Overview

AI-generated overview

ExpenseBot MCP lets an assistant capture receipts, analyze expenses, income, mileage and P&L, and prepare reviewed expense reports.

What you can do
  • Search, read and summarize expenses, income, mileage, subscriptions and profit and loss, including per-tag P&L and affordability checks
  • Submit receipt photos or PDFs, check processing results, trace documents and scan connected Gmail for receipts
  • Add cash expenses, mileage, income and client advances, with previews and confirmations before writing
  • Create, inspect, export and share expense reports, check and fix compliance, and hand reports to accounting destinations
  • Look up product help, feature support and tax deductibility guidance, and review recent assistant activity
When to use it
Useful for freelancers, contractors and small businesses that keep books in ExpenseBot and want an assistant to log receipts, answer spending and profitability questions, or assemble client and trip reports. Also suited to automation workflows that need receipt intake with duplicate detection and terminal status.
Requirements
Either the hosted remote endpoint with browser sign-in and OAuth consent, or the local npm adapter run with npx, which needs a revocable ExpenseBot token in the EXPENSEBOT_TOKEN environment variable. Gmail features require Gmail connected in ExpenseBot settings; mileage needs a configured rate and unit.
Before you install
Write tools add expenses, mileage, income and report shares to the user's spreadsheet, and accounting posting sends reports to a connected accounting destination; confirm previews before approving. Gmail scanning and receipt upload send email and document content to ExpenseBot's cloud. Keep the token revocable and never paste it into chat, and connect each client's own account rather than sharing one credential.

Installation

In SourceWeft

  1. Open ExpenseBot in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.TotesMagotes%2Fmcp-server-auth/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "expensebot": {
      "type": "http",
      "url": "https://mcp.expensebot.ai/mcp"
    }
  }
}

README

[ExpenseBot logo]

ExpenseBot MCP

Expense management and Gmail receipt capture for AI assistants and automation platforms.

Public installation and discovery metadata for the hosted ExpenseBot Model Context Protocol server.

ExpenseBot gives AI assistants and automation platforms structured access to expense data, Gmail receipt capture, reports, income, mileage, compliance checks, and accounting handoffs. ExpenseBot remains the system that captures and organizes receipts; downstream accounting software remains the source of truth for the books.

Receipt ingestion for agent workflows

ExpenseBot can also be the receipt-intake component inside a larger AI or automation workflow. Your agent owns orchestration, business rules, review policy, and downstream systems; ExpenseBot handles supported receipt intake, extraction, duplicate detection, terminal processing status, and customer-owned evidence in Google Sheets and Drive.

A reliable integration should:

  1. Submit each receipt once and retain the returned submission identifier.
  2. Check that identifier until it reaches an authoritative terminal result.
  3. Branch explicitly on success, duplicate, held-for-review, or error states.
  4. Avoid resubmitting work that is still pending.
  5. Connect each customer's own ExpenseBot account rather than sharing one personal credential across clients.

See the builder integration overview for the workflow contract, architecture boundary, and implementation examples.

Recommended: remote OAuth

Use the hosted Streamable HTTP endpoint in clients that support remote MCP and OAuth:

text
https://mcp.expensebot.ai/mcp

Example mcp.json:

json
{  "mcpServers": {    "expensebot": {      "url": "https://mcp.expensebot.ai/mcp"    }  }}

The client should open ExpenseBot sign-in and consent in the browser. Do not paste an ExpenseBot token into chat.

Local stdio fallback

Clients without remote OAuth support can run the public npm adapter:

text
npx -y @expensebot/mcp-server-auth

Store a revocable ExpenseBot token in the client's EXPENSEBOT_TOKEN environment or secret configuration. Generate and revoke tokens from AI Assistant Tokens.

What agents can do

  • Search and analyze expenses, income, mileage, subscriptions, and profit and loss.
  • Submit receipt images and PDFs and check processing results.
  • Scan connected Gmail accounts for receipts and monitor scan progress.
  • Add cash expenses, mileage, income, and confirmed client advances.
  • Review, correct, categorize, group, and annotate exact expenses with confirmation safeguards.
  • Create, inspect, export, and share reports and continue into client billing.
  • Review credits, refunds, compliance issues, monthly books, and client advance balances.
  • Trace document activity and open the relevant ExpenseBot review UI when a visual workflow is safer.

The live server currently exposes more than 50 tools. Write actions use previews, confirmations, bounded selections, or app handoffs where appropriate.

Useful prompts

  • Scan Gmail for new receipts and tell me what needs attention.
  • Show me my unsubmitted travel expenses from last month.
  • Group my Toronto Uber Eats expenses from this quarter under Client Demo, then create a report without personal expenses and help me bill the client.
  • How much of Client Acme's advance remains?
  • Compare this quarter's spending with the same quarter last year.

Documentation and support

This repository intentionally contains public installation metadata only. The hosted ExpenseBot application and its private source code are not published here.

Source: README.md at commit 948ad05

Tools

61

search_expenses

Search expenses

Search and filter the user's expenses. Returns matching expense rows from their spreadsheet. Filter by category, merchant, date range, amount, or tags. Results are paginated: when hasMore is true, call again with nextCursor and the same filters. Do not split a date range into repeated overlapping searches. Use the optional query parameter for deterministic natural-language recall over merchant, city/location, Notes (including receipt items, delivery source, payer, and Business purpose), Tag, and category. Each matching result includes matchedFields and a short matchReason so you can explain why it was selected. When several rows plausibly match, a disambiguation list is returned; each option carries the exact expenseId. Structured filters (categories, merchants, dateRange, tags, minAmount, maxAmount) combine with the query using AND semantics. Each result includes expenseId, the exact durable Receipt ID required by update_expense.

ParameterstagslimitquerycursordateRangemaxAmountmerchantsminAmountcategorieshasReceiptclientEmail

get_spending_summary

Get spending summary

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. Returns: { message, data: { total, breakdown?, comparison?, sampleMeta? } }.

ParametersquerymetricgroupBydateRangecategoriesclientEmail

get_deep_analytics

Run deep analytics

Run deeper, multi-step analytics on the user's expenses. Use for explanatory questions like 'why did my spending increase' or 'compare Q1 vs Q2'. Takes 10-30 seconds (runs as a background job, polled automatically). Returns: { message, data: { ..., sampleMeta? } } where sampleMeta.isTruncated indicates whether the agent saw the full dataset.

ParametersqueryrequireddateRange

create_report

Create expense report

Create an expense report from a clear date, client, project, trip, category, or merchant request. Tags are ExpenseBot's grouping layer for clients, projects, project codes, and trips; call list_tags when the user's intended group is unclear. For requests such as 'all expenses in August except personal', set excludePersonal=true; this excludes both the Personal tag and Personal expense category, matching ExpenseBot's Report Wizard. Returns the report summary, exact report link, Bill Client link, applied filters, and a prefilled Report Wizard fallback for criteria that need visual review. Reports scoped to an existing client/project/trip group include matching expenses that are not already assigned to another ordinary report. Can optionally share with recipients. If no unreported matches remain, create no duplicate report and explain that the expenses are already in Reports. Terminal results also include role-appropriate accountingHandoffUrls from the server capability matrix and the existing reviewed file-export workflow. Use only the exact destination the user requested; the link opens the reviewed app flow and does not mean an export occurred. Complete the requested report directly; do not call check_compliance, get_report_details, or tax/deductibility tools before or after it unless the user explicitly asks for that separate analysis.

ParameterstagstitledateRangeshareWithcategoriesexcludedTagsrecipientRoleexcludePersonalexcludedCategories

list_reports

List expense reports

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.

ParameterspagelimitfilterclientEmail

request_accounting_integration

Request an accounting integration

Request support for an accounting package only after checking ExpenseBot's reviewed direct and import-file destinations and finding no matching package. Do not use this for a listed or Beta destination, a general compatibility question, or without the exact package name. This is a confirmation-gated write: after the user approves, it creates one deduplicated request bound to the authenticated ExpenseBot account and emails ExpenseBot's internal team. It does not create an integration or make the requested package immediately available. On accepted or previously recorded requests, tell the user ExpenseBot will email them within one week with an update.

ParameterspackageNamerequired

get_report_details

Get report details

Get full details of a specific expense report including all expenses, totals, and compliance status. Use only when the user explicitly asks to inspect an existing report's details. Without checkFreshness:true, returns the stored report only. When explicitly requested together with analysisRequested:true, freshness reads canonical Google Sheets sources with a 5-second bound; if full tax-year replay is unavailable, status is unknown, not current. Never call this as a preflight or follow-up to creating, sharing, or billing from a report; those tools already return the requested result and links.

ParametersreportIdrequiredclientEmailcheckFreshnessanalysisRequestedrequired

share_report

Share expense report

Share one existing expense report after confirmation. 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.

ParametersreportIdrequiredrecipientsrequiredrecipientRole

check_compliance

Check report compliance

Use only when the user explicitly asks to check an existing report for compliance issues such as missing business purpose or policy violations. Creating a report, excluding Personal expenses, sharing a report, or billing a client is not a compliance request; never call this tool automatically as a preflight or follow-up for those workflows.

ParametersreportIdrequiredanalysisRequestedrequired

fix_compliance

Fix compliance issues

Safely correct compliance issues on an exact bounded set of recorded expenses. Use only after the user explicitly asks to fix issues found by check_compliance. Use search_expenses to obtain each full expenseId, then pass those exact identities; never select every report row or infer a business purpose, category, or attendee. This compatibility tool uses the same reviewed workflow as correct_expenses: the first call always prepares a grounded preview and makes no change, even if confirm:true arrives early. Show the exact proposed changes and ask once for approval. Only after explicit approval repeat the same operationId, selection, and change with confirm:true. The confirmed result reports applied/conflicted/failed counts and supports status and Undo. For tags/groups use group_expenses; for unsupported or more than 100-row cleanup open https://www.expensebot.ai/review-expenses?source=mcp.

ParametersundochangestatusconfirmselectionoperationIdrequired

check_tax_deductibility

Check tax deductibility

Use this when the user asks for general deduction guidance for an expense type, such as business meals or home-office expenses. Looks up reference rules using the account's tax-country/home settings and current year. A verified rule may return a percentage and reference; unverified rules return unknown/reviewRequired without a percentage. Read-only: it does not classify saved expenses, prepare a return, or determine the user's actual tax liability. Do not use for tax refunds received as income; use get_income_summary for recorded refunds. General guidance is not a tax professional's determination.

Parametersqueryrequiredcategorymerchant

search_knowledge

Search ExpenseBot knowledge base

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.

ParameterslimitqueryrequiredfullAnswer

submit_receipt

Submit receipt photo or PDF

Submit a photo or PDF of a receipt for processing. Covers requests phrased as 'log this', 'log this receipt', 'save this receipt', 'expense this', or 'add this to my expenses', including when the user simply shares a photo of a receipt or invoice. The receipt image is validated, uploaded to cloud storage, and processed by AI to extract vendor, amount, date, tax, and category. The expense appears in the user's spreadsheet in about 1-3 minutes, and longer for PDFs or large batches. Handles images and PDFs, mixed together in one batch. TO SEND FILES (preferred, and required for PDFs): call this tool with filesToUpload listing every file the user gave you. It returns one signed upload URL per file. Upload them ONE AT A TIME with an HTTP PUT, telling the user which file you just finished and how many remain, then call this tool ONCE with uploadRefs for all of them — that processes the whole set as a single batch, like the ExpenseBot web app. Do not call this tool once per file. Use the photo parameter for one image or PDF attached in ChatGPT. MCP clients that cannot supply file references may use photoBase64 for one small image; use the upload flow for large files or batches. Optional note and tag values use the same receipt metadata path as ExpenseBot's camera, file uploader, and forwarded-email intake. The note is stored in the Notes column (L); the tag is stored in the Tag column (K). Batch defaults apply to every file, and each uploadRefs item may override either value for that file.

ParameterstagnotephotofilenamemimeTypeuploadRefuploadRefsphotoBase64filesToUpload

get_last_receipt_result

Check a submitted receipt outcome

Check the authoritative final outcome of a receipt image/PDF batch submitted with submit_receipt. After submit_receipt returns submissionId, call this tool with that exact ID using the polling interval and time allowance in the submit_receipt response. A small batch allows at least 5 minutes; larger batches allow longer. A pending result is normal and must not trigger a duplicate resubmission. Returns added, duplicate, skipped, held_for_review, or errored verdicts with exact counts and up to 10 processed receipt summaries. A held_for_review file (withheld for missing details or a possible duplicate) was not added; relay the next step in the message. found:false is pending and has no terminal verdict; found:true is terminal. On completion, report the authoritative per-file outcomes. Show spreadsheetUrl and reviewExpensesUrl for rows actually added, not as the destination for held files. For a held file relay only its message's next step (such as Files to review on Add Expenses); do not invent a missing card or direct held uploads to Gmail Action Needed. Unknown outcomes stay unknown; do not blindly resubmit. This is for uploaded receipts; use get_scan_status for Gmail scans. Read-only.

ParameterssubmissionIdwithinSeconds

add_cash_expense

Log cash expense

Add an expense without a receipt, or record money a client provided in advance for expenses. Writes directly to the user's expense spreadsheet after confirmation. For an ordinary expense, call list_categories first and provide a configured Expense Account. For a client advance, set isClientAdvance=true and clientName; ExpenseBot reuses or creates the canonical client group, applies Cash advance received, and stores the amount as a negative expense. Use this only for money supplied by a client before related spending, never for vendor refunds, reimbursements, earned fees, retainers, or generic deposits. Use the Manual expense link from get_spreadsheet_url instead when the user needs a reviewed form for multiple entries, credits/refunds, tax or tip breakdowns, per diem, or incomplete details.

ParameterstaxtipcitydaterequirednotestotalrequiredcategorycurrencymerchantsubtotalclientNameisClientAdvance

parse_expense

Parse expense text

Parse a natural language expense description into structured fields. Does NOT add the expense — just returns the parsed fields for review. Example: "Lunch at Chipotle $15.50 today" → {merchant: "Chipotle", total: 15.50, ...}

Parameterstextrequired

process_gmail_receipts

Process specific Gmail receipts

Process specific Gmail emails as receipts. Pass Gmail message IDs and they'll be converted to PDF, extracted by AI, and added to the user's expense spreadsheet. Max 25 emails per request. Requires Gmail to be connected in ExpenseBot settings.

ParametersemailIdsrequiredaccountEmail

scan_gmail

Scan Gmail for receipts

Trigger a background Gmail scan to discover and process receipt emails from the last ~60 days (default). Runs asynchronously — returns immediately, 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.

ParametersendDatestartDateaccountEmaillookbackDays

add_mileage_entry

Log mileage trip

Log a business mileage trip in ExpenseBot. Useful for realtors, consultants, contractors, and anyone who drives for work. Requires the user to have configured their mileage rate (cents/km or cents/mi) and unit (mi/km) in ExpenseBot Settings. The trip writes a row to their expense spreadsheet with the calculated dollar value. Use the Mileage and travel link from get_spreadsheet_url instead when the user needs Google Maps route calculation, mileage settings, repeated trips, calendar/rideshare import, per diem, or visual review.

ParameterstagcitydaterequirednotespurposerequiredcategorydistancerequiredroundTripdestination

add_income

Log income entry

Log exactly one user-confirmed income payment manually (cash, check, Stripe payout, etc.). Never loop this tool over a statement, export, table, or multi-row list. For two or more payments, use add_income_from_csv for CSV/TSV/text or add_income_from_file for an image/PDF; those tools stage a duplicate-checked preview and require confirmation before writing. Writes to the Income tab of the user's expense spreadsheet. Useful for income that isn't auto-detected from Gmail or Plaid. Call list_income_categories first and use one of its fixed tax categories; an omitted category defaults to Service income and an unknown category is rejected.

ParameterstagdaterequiredfeesnotesamountrequiredsourcerequiredcategorycurrencyreferencedescriptiontaxCollectedpaymentMethodrequired

add_income_from_file

Import income from an image or PDF

Import income from an attached screenshot, image (JPEG, PNG, WebP, HEIC/HEIF), or PDF (payment screenshots, wallet apps, payout or bank statements; max 10 MB). This is a two-step tool. STEP 1: call it with the file and WITHOUT confirm — ExpenseBot parses the file with the same importer as the app's Add Income screen, checks every row against the user's Income tab for duplicates, and returns a preview with a previewId, exact row count, totals by currency, per-row details, duplicate flags, and any rejected rows. NOTHING is saved in step 1; treat the attachment as consent to parse, not consent to write. Show the user the parsed rows and duplicates, then STEP 2: call again with confirm: true and the previewId to write exactly those rows. Only include user-approved changes in step 2 (selectedIndexes, keepBothIndexes, rowEdits, tag, bulkNote). Flagged duplicates are skipped unless the user explicitly asks to keep them (keepBothIndexes). The preview expires after 15 minutes; an expired or unknown previewId never writes. After a successful confirm, show the returned spreadsheetUrl and reviewIncomeUrl. For a visually complex review (mixed income/expense rows, many edits), send the user to the Add Income app link returned by get_spreadsheet_url instead.

ParameterstagphotoconfirmbulkNotemimeTyperowEditspreviewIdphotoBase64paymentMethodkeepBothIndexesselectedIndexes

add_income_from_csv

Import income from a CSV/TSV/text export

Use this to import the user's CSV/TSV/text income export (max 500 KB). Step 1 stages a duplicate-checked previewId without writing Income rows. Show it and obtain approval. Step 2 uses confirm:true and that previewId to write the approved rows/edits; duplicates require explicit keep approval. Unknown or expired previews never write (15-minute expiry). Return spreadsheetUrl and reviewIncomeUrl after success. Accepts user-provided attachments or inline text, not arbitrary web URLs.

ParameterstagconfirmcsvTextbulkNoterowEditspreviewIdcsvContentpaymentMethodkeepBothIndexesselectedIndexes

get_accounting_integration_status

Check accounting integration status

Check whether an accounting destination is connected and read-only setup state for the owner. Returns the selected organization/company/business, stored connection state, rollout state, and the single setup link for connecting or reconnecting the destination. When an existing ExpenseBot report is available, pass reportId so the link opens that exact report's provider setup control instead of the general Reports setup. This is read-only and never posts accounting data. Agent-driven posting is currently available only for Zoho Books (zoho_books); QuickBooks Online (quickbooks), Xero (xero), Wave (wave), and FreeAgent (freeagent, beta) are accepted here for connection/setup status only and report writesAuthorized=false until their canonical planning path is shared.

ParametersproviderrequiredreportId

send_report_to_accounting

Review and send report to accounting

Review and then post an ExpenseBot report to the owner's accounting destination. STEP 1: call with provider, reportId, and optional mode/mappings, without confirm. The server reads the live report and destination, applies Omit/Personal/split/date/currency rules, checks Zoho bank-feed matches, and returns the complete proposal plus proposalId. NOTHING is posted in step 1. Show the complete proposal and ask for approval. STEP 2: call with only provider, proposalId, and confirm:true. The server posts only the frozen, account-bound proposal, revalidates live state, and rejects changed reports or mappings. Never add mapping fields to the confirmation call. Owner accounts only; acting for a client is not supported. Agent-driven posting is currently available only for Zoho Books (zoho_books); QuickBooks Online, Xero, Wave, and FreeAgent are intentionally not accepted by this tool yet because their previews cannot freeze/revalidate the canonical provider plan that shareReport executes. Use those providers' web flows until they satisfy the full push contract.

ParametersmodeconfirmproviderrequiredreportIdproposalIdforceRepushtaxMappingsaccountMappingsreportingTagMappings

get_accounting_push_status

Check accounting push status

Read the authoritative posting and reconciliation status for one ExpenseBot report at an accounting destination. Use after a timeout or uncertain response before considering any retry. Returns status, submission time, posting mode, posted receipt count, any public error, and whether reconciliation is required. Never re-post a completed report or a report marked needs_reconciliation; show that state to the owner instead. This tool is read-only and owner-account only.

ParametersproviderrequiredreportIdrequired

list_categories

List expense categories

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.

Takes no parameters.

list_tags

List tags

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.

Takes no parameters.

get_income_summary

Get income summary

Use this when the user asks about income already recorded in their ExpenseBot Income tab. Read totals; group by source, category, month, payment method or tag; filter by dateRange/incomeTagPrefix. Query supports period comparisons (e.g. 'income YTD by source', 'income this year vs last'). Returns message and data with total and optional breakdown, comparison, sampleMeta. No scanning, imports, mutations, tax returns or liability determination.

ParametersquerygroupBydateRangeincomeTagPrefix

get_pnl

Get profit & loss

Compute Profit & Loss (P&L / net income / margin) by combining the Income tab with expense tabs. Examples: 'am I profitable this year', 'P&L for Q1', 'net income last quarter', 'what's my margin', 'P&L this year vs last' (YoY). Supports period comparison — YoY, MoM, QoQ, same-month-prev-year. Margin renders as multiplier in loss territory ('expenses 5.4× revenue') so the user gets a readable signal instead of '-436.9% margin'. Returns: { message, data: { revenue, expenses, netIncome, margin, comparison?, sampleMeta? } }.

ParametersquerydateRangeclientEmail

get_per_tag_pnl

Get per-tag profit & loss

Per-tag P&L — revenue, cost, profit, and margin grouped by tag (per-client, per-property, per-event, per-realtor-deal). Requires both income AND expense rows to be tagged with matching labels. Common tag-prefix shortcuts: 'Prop –' (rentals), 'Client –' (client billings), 'Wedding –' (events), 'Realtor –' (real estate deals). Examples: 'per-tag P&L this year', 'profit by client', 'profit by property', 'profit on the Smith wedding', 'per-client P&L this year vs last' (YoY). Supports YoY / MoM / QoQ comparison phrasing. Margin renders as multiplier in loss territory. Defaults to year-to-date if no date range given.

ParametersquerydateRangetagPrefix

list_income_categories

List income categories

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.

Takes no parameters.

get_recent_activity

Show recent AI activity

Show what the user (or their AI assistants) has recently done in ExpenseBot via this MCP server: which tools were called, when, with what arguments, and whether they succeeded. This is a log of assistant TOOL CALLS, not the processing history of a document. Useful for questions like 'what did I do this week' or 'which tools has my assistant run', and to give the user transparency into AI-assisted actions. Returns the most recent N entries from the audit log (default 20, max 100).

ParameterslimitactionIdsinceDays

trace_document

Trace what happened to a receipt or invoice

Trace what happened to a specific receipt, invoice, forwarded email, Gmail receipt, or PDF in ExpenseBot processing. Use when the user asks where a document went, why it did not show up, whether it was skipped, routed to income, deduped, or removed as a duplicate. NOT for the status, progress, or completion of a Gmail scan job (running, queued, finished, or stuck) — a scan is not a document; use get_scan_status for that. Returns a read-only timeline from the user's lineage audit trail.

ParametersdayslimitqueryoutcomethreadIdmessageIdreceiptId

get_mileage_summary

Get mileage summary

Mileage analytics — totals, breakdowns by month / client / purpose / category, plus deduction framing (cents-per-mile or cents-per-km × distance, country-aware IRS / CRA rates). Examples: 'mileage this year', 'miles driven for Acme', 'mileage by month', 'mileage deduction estimate', 'business miles last quarter'. Supports YoY / MoM / QoQ comparison phrasing. Returns: { message, data: { totalDistance, deductionEstimate?, breakdown?, comparison?, sampleMeta? } }.

ParametersquerygroupBydateRange

get_subscription_audit

Audit subscriptions

Subscription audit — wraps the Subscription Auditor engine to find recurring charges, duplicates, price increases, and trial-conversion suspects in the user's expenses. Examples: 'recurring subscriptions', 'duplicate subscriptions', 'price increases', 'trial conversions', 'subscriptions over $20/month'. Returns: { message, data: { recurring, duplicates, priceIncreases, trialConversions, totalMonthlyCost, sampleMeta? } }.

ParametersfocusquerydateRange

get_expense_by_id

Get expense by ID

Read one existing expense from the authenticated user's ExpenseBot spreadsheet. Supply the exact expenseId returned by search_expenses (Receipt ID in Column Q), or the user's specified rowNumber. Never invent an identifier. Returns sheetName, rowNumber, headers, values, labeled fields and, when available, reviewExpenseUrl. This tool does not edit, submit, delete, share, or scan anything.

ParametersexpenseIdrowNumber

export_report

Get report export URLs

Get a short-lived direct PDF download for one exact authorized expense report, plus the exact highlighted in-app report link. Use the in-app report for CSV, XLSX, receipt ZIP (when available), comments, invoicing, and other visually reviewed actions. Use list_reports first to find the reportId.

ParametersreportIdrequired

get_spreadsheet_url

Open ExpenseBot workspace links

Return the user's master ExpenseBot Google Sheet plus authenticated ExpenseBot workspace links, each with a label and a description of when to use it. Use this when the user asks to open, view, check, or edit their spreadsheet; review expenses or income; manually scan Gmail; reconcile; connect or manage a bank/credit card; open Automation Hub or General Settings; create or open reports; or asks where a submitted receipt went. Choose and show the one or two links relevant to the request instead of listing the entire catalog. After a receipt submission, prefer Review expenses plus the Google Sheet. After an income write, prefer Review income plus the Sheet. For a Gmail scan or connection request, use the Scan Gmail link, which opens the existing Gmail scanning interface. Bank/card requests use the Reconcile link; configuration requests use the returned Automation Hub or General Settings link. Category, G/L, and account-code requests use Category management; client, project, and trip groups use Group management; questions about what counts as Personal use Personal rules. For client billing setup, use the returned clientBillingHandoffs instead of giving a generic dashboard tour: manageClients creates or manages the client list, tagReadyExpenses opens Review Expenses filtered to blank or default-Business rows, and createClientReport opens report creation by group after expenses have been assigned. Choose the one next step that matches the user's current state. If the user names a client and an exact expense scope and asks the assistant to do the work, use search_expenses and group_expenses instead; show its grounded preview and require explicit confirmation before changing any rows. When the user asks to choose receipt images from Google Photos, use the returned Google Photos link; it opens the existing authenticated picker and handles any required Google consent in ExpenseBot. When they ask where ExpenseBot stores receipt files, return the Drive folder link only when it

Takes no parameters.

check_feature

Check ExpenseBot feature

Check whether ExpenseBot supports a specific feature ('does ExpenseBot support X', 'can it integrate with Y'). Searches the public knowledge base and returns a confidence-scored answer + related questions. Works with or without authentication.

Parametersfeaturerequired

whatif_afford

What-if: can I afford this?

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.

ParametersdeltaMonthlyrequired

whatif_client

What-if: client pays late or leaves

What if a client pays late or leaves? mode='late30' shifts that client's OPEN invoice amounts out of the near-term expectation (they still owe it, it's just not landing this month). 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.

ParametersmoderequiredclientNamerequired

whatif_tax_setaside

What-if: tax set-aside

What should I set aside for taxes? Surfaces the same monthly tax set-aside estimate already computed for Safe Monthly Draw — wiring, not new math. Flat-rate estimate (default 30%) against trailing income minus recurring + variable spend. Use for 'how much should I set aside for taxes this month'.

Takes no parameters.

scan_gmail_years

Scan past years of Gmail

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.

ParametersyearsrequiredaccountEmailconfirmStart

get_scan_status

Check Gmail scan status

Check authoritative Gmail receipt scan status. Returns the active lock and live phase/progress shown in-app, queued or attention-needed periods, completed calendar years, and tax-period statuses with their returned labels and inclusive ISO bounds, plus exclusions and recent outcomes. Use when asked if a scan is running, finished, stuck, or what it is doing. On completion show spreadsheetUrl or reviewExpensesUrl; for setup/reconnection show gmailScanUrl. Read-only.

Takes no parameters.

get_statement_import_status

Check statement import status

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.

ParametersclientEmail

list_client_invoices

List client invoices (AR)

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.

ParameterslimitstatusclientNameclientEmail

get_client_invoice

Get client invoice details

Get the full financial and delivery summary for one issued client invoice, including subtotal, markup, tax, advance applied, balance due, dates, status, source report, and private Google Doc/PDF/DOCX links when available. Provide invoiceId or invoiceNumber — one is required; invoiceNumber is accepted only when it is unique. Read-only.

ParametersinvoiceIdclientEmailinvoiceNumber

prepare_client_invoice

Prepare client invoice

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.

ParameterstaxPctreportIdrequiredtaxLabelissueDaterequiredmarkupPctclientNamerequiredreceiptIdsbillToEmailpaymentTermsclientAddressinvoiceNumberadvanceApplied+2 more

create_client_invoice

Create client invoice

Create the exact invoice previously returned by prepare_client_invoice. This is a confirmed write: it revalidates the report snapshot and client identity, creates a private editable Google Doc plus private PDF and DOCX copies, records the issued invoice, and supersedes an older active invoice for the same report. It does not send email or create an Income row. If tax is positive, confirmTax must be true.

ParametersconfirmTaxoperationIdpreparationIdrequired

mark_client_invoice_paid

Mark client invoice paid

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.

ParameterspaidViapaidDaterequiredinvoiceIdrequiredpaidAmount

get_expense_splits

View expense splits

Show how an expense was split across categories, clients, properties, or business vs personal portions. Returns the single parent payment with its nested allocation lines — split lines are never counted as separate expenses, so totals stay correct. Examples: 'how is that expense split', 'what was the business portion of that bill', 'show the allocation for this receipt'. Read-only — splits are edited in ExpenseBot's Review workspace.

ParameterslimitdateRangeonlySplitreceiptIdclientEmail

get_monthly_books_review

Review monthly books

Month-end summary of the user's books for one calendar month: income recorded, money spent, net, top spending categories and merchants, plus alerts for anything unusual that month. Examples: 'how did last month go', 'close out my books for June', 'monthly review', 'what did I make and spend in May'. Defaults to the last completed month. Figures come from the user's own recorded data; advisory notes are estimates, not tax advice. closeReadiness summarizes current recorded-book checks and Action Needed categories with authenticated app links. Explain unknown coverage and limitations; it does not close books or certify tax completeness.

ParametersperiodclientEmail

list_client_close_readiness

Review client close readiness

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.

Parameterspagelimitperiod

get_credits_refunds

List recorded credits and refunds

List card refunds, cashback/rewards, and statement credits that ExpenseBot has already recorded — either as negative expenses or matched against the original charge. Examples: 'did my refund come through', 'show my statement credits', 'was that return recorded'. Returns the most recent items (default 25, newest first); narrow with dateRange. Read-only: it never scans cards, changes review decisions, or adds rows.

ParameterslimitdateRangeclientEmail

get_client_advance_balances

Check client advance balances

Read the same per-client advance balances shown in ExpenseBot's Client advances section. Use for questions like 'how much of Acme's advance remains?', 'which client floats are still open?', or 'do I owe a client a refund?'. A negative ledger balance means money remains to refund; a positive balance means the client owes the user. Returns the existing app handoff for Refund leftover or Bill Client. Read-only: never records a refund, creates an invoice, or recomputes the ledger in model prose.

ParametersclientNameclientEmail

get_trip_suggestions

Review high-confidence trip suggestions

Show ExpenseBot's current high-confidence Trip Intelligence proposals from Review Expenses. Read-only: never groups, tags, creates reports, or writes to the spreadsheet. Each proposal returns strict YYYY-MM-DD dates, evidence, locations, and the exact Receipt IDs with expected current tags. Do not infer a client/project from geography. When nextAction is present, use exactly its group_expenses params with confirm:false, show the canonical preview, then ask for explicit confirmation before any write. Never send confirm:true from this read result alone. In accountant clientEmail mode this tool can read accepted clients but may return no executable nextAction; hand off to Review Expenses or the owner's own assistant connection to apply.

ParameterslimitclientEmail

group_expenses

Group selected expenses

Group an exact set of recorded expenses for a client, project, trip, job, or other user-named purpose. Examples: 'group my Mexico meals for client Rob', 'put these Vegas expenses under the Vegas project', or 'group these for client Rob and create a report'. The user does not need to know about tags: ExpenseBot resolves the requested name against existing groups and proposes creating one only when needed. Use exact expenseId values returned by search_expenses. A grounded preview is automatic for every bulk request; the user does not need to ask for one. First call with confirm omitted/false, show the returned exact rows, count, totals, proposed group, exclusions, and conflicts, then ask for approval. Only after explicit user approval, repeat the same operationId and selection with confirm:true. A premature confirm:true is converted to preview. When the request includes a report, set createReport:true on that confirmed group_expenses call and use its report result; do not run a separate broader create_report query. For 'without personal expenses', set excludePersonal:true; ExpenseBot removes Personal-tagged and Personal-category rows before preview so their Personal marker is never overwritten. The confirmed operation returns exact report and Bill Client links. Expenses already assigned to another ordinary report are excluded; if none remain, no duplicate report is created and the result links to Reports instead. Keep the user-facing response concise and do not add unsolicited tax or substantiation advice. Do not call check_compliance, get_report_details, or tax/deductibility tools before or after this workflow unless the user explicitly asks for that separate analysis. In user-facing prose call the destination a group, not a tag. Treat preview totals as provisional; after confirmation use only the terminal result's exact count, total, and currency without reconciling it against the preview. A returned Bill Client URL opens the reviewed billing handoff and does not me

ParametersundogroupstatusconfirmselectionoperationIdrequiredreportTitlecreateReportexcludedTagsapproveNewGroupexcludePersonalexcludedCategories

update_expense

Edit an expense's category/tag/merchant

Update a single existing expense row's category, tag, merchant, or business purpose (e.g. 'recategorize expense X to Meals' or 'tag it Client – Acme'). Identify it only by the exact expenseId returned by search_expenses (the full Receipt ID from Column Q). Never use a date, displayed number, or sheet row number as expenseId. Two-phase operation: calls with confirm omitted or false return a preview of the current→proposed change and make no change. After user confirmation, a call with confirm:true applies the proposed change. 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 instead of retrying. Only category/tag/merchant/businessPurpose are editable — amounts, dates, and notes are not editable via the assistant. Does not create or delete rows.

ParametersfieldsrequiredconfirmexpenseIdrequired

correct_expenses

Correct selected expenses

Safely correct the category, business purpose, or explicit attendees on an exact bounded set of recorded expenses. Examples: 'categorize these as Travel', 'add Client kickoff dinner as the business purpose for these meals', or 'add Fred, Rob, and Lamar to last night's business meal'. First use search_expenses to identify the exact rows, then pass their full expenseId values. A grounded preview is automatic: first call with confirm omitted/false, show the exact count and proposed before-to-after changes, and ask once for approval. Only after explicit approval repeat the same operationId, selection, and change with confirm:true. A premature confirm:true is converted to preview. Attendee names must come explicitly from the user; never infer them. attendeeMode add preserves existing attendees, while replace substitutes only the attendee segment. Business purpose and attendees preserve the structured Notes field, including card, description, inbox, and other typed segments. Formula Notes and changes that exceed the Notes limit are skipped safely. The confirmed result reports applied/conflicted/failed counts and supports Undo. This tool does not omit duplicates, change amounts or dates, infer business context, or run broad Calendar matching. For unsupported or more than 100-row cleanup, send the user to https://www.expensebot.ai/review-expenses?source=mcp.

ParametersundochangestatusconfirmselectionoperationIdrequired

fetch

Fetch full item details

Fetch full details for a specific item returned by `search`. The id encodes the item type: • 'expense:<expenseId>' — the durable Column-Q Receipt ID returned by `search`, URL-encoded, e.g. 'expense:RR-123%3A%3Adrive%2Ffile%209'. Never a sheet row number: rows move when the sheet is prepended. • 'report:<reportId>' — the alphanumeric Firestore document id from `search` or `list_reports`, e.g., 'report:FQqDglExofsyyQv7aYy4' • 'kb:<entryId>' — the knowledge-base entry id from `search` Always use the id exactly as returned by `search` or `list_reports` — do not invent or modify the trailing portion. Returns the full text content + metadata for the AI to cite.

Parametersidrequired

Version history

2
  1. v0.6.26LatestOct 2, 2026
  2. v0.6.25Sep 16, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

    Declare a license in the repository or the registry entry.