zoho-bookkeeper-mcp
Provides integration with Zoho Books for bookkeeping workflows, including full CRUD operations for journals, expenses, bills, and invoices; file attachments with multipart upload support; chart of accounts management; bank account integration; contact management; and OAuth 2.0 authentication with automatic token refresh.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@zoho-bookkeeper-mcp Create a new expense for office supplies"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Zoho Bookkeeper MCP Server
A Model Context Protocol (MCP) server for Zoho Books integration, designed for bookkeeping workflows with AI agents.
Why This Exists
The official Zoho MCP service (zohomcp.com) has limitations:
Cannot upload file attachments - The MCP schema incorrectly maps binary file parameters as query strings
Too many tools - 100+ tools exhaust AI tool limits quickly
Difficult control over tool selection - The mcp.zoho.com interface is troublesome and cannot be used by agents
This custom MCP server provides:
Proper multipart/form-data file uploads for attachments
Curated set of 49 tools for bookkeeping workflows
Auto-refreshing OAuth tokens (1-hour lifetime with 5-minute buffer)
Both stdio (CLI) and HTTP stream transports
Related MCP server: Zoho CRM + Books MCP Server
Features
Full CRUD operations for journals, expenses, bills, and invoices
File attachments with proper multipart upload support (PDF, images, Office documents)
Chart of accounts management and transaction queries
Bank account integration and transaction listing
Contact management for customers and vendors
OAuth 2.0 with automatic token refresh
Health checks for container orchestration
Available Tools (49 total)
Category | Tools | Description |
Organizations | 2 | List orgs, get org details |
Chart of Accounts | 4 | List/get/create accounts, list transactions |
Journals | 9 | Full CRUD + publish + attachments |
Expenses | 6 | Full CRUD + receipt attachments |
Bills | 6 | Full CRUD + attachments |
Invoices | 5 | List/get + attachments |
Contacts | 2 | List/get customers and vendors |
Vendors | 4 | Vendor-specific list/get/create/update workflows |
Bank Accounts | 11 | List accounts/transactions + matching + categorization workflows |
Prerequisites
Node.js 20+
Zoho Books account with API access
Zoho OAuth 2.0 credentials (see Configuration)
Installation
Option 1: Run with npx (Recommended for Desktop Agents)
npx zoho-bookkeeper-mcpOption 2: Install globally
npm install -g zoho-bookkeeper-mcp
zoho-bookkeeper-mcpOption 3: Docker
docker build -t zoho-bookkeeper-mcp .
docker run -p 8004:8004 \
-e ZOHO_CLIENT_ID=your_client_id \
-e ZOHO_CLIENT_SECRET=your_client_secret \
-e ZOHO_REFRESH_TOKEN=your_refresh_token \
zoho-bookkeeper-mcpOption 4: From source
git clone https://github.com/bu5hm4nn/zoho-bookkeeper-mcp.git
cd zoho-bookkeeper-mcp
pnpm install
pnpm buildConfiguration
Run the interactive setup:
pnpm setupThis will guide you through:
Creating a Zoho Self-Client application
Entering your Client ID and Secret
Generating and exchanging an authorization code
Saving credentials to
.env
Manual Configuration
If you prefer manual setup, copy .env.example to .env and follow the Zoho OAuth Documentation to obtain:
ZOHO_CLIENT_ID- from Zoho API ConsoleZOHO_CLIENT_SECRET- from Zoho API ConsoleZOHO_REFRESH_TOKEN- obtained via OAuth authorization code flow with scopeZohoBooks.fullaccess.all
Environment Variables
The .env file should contain:
# Required
ZOHO_CLIENT_ID=1000.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ZOHO_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ZOHO_REFRESH_TOKEN=1000.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Optional
ZOHO_API_URL=https://www.zohoapis.com/books/v3 # Default (US datacenter)
ZOHO_ORGANIZATION_ID=123456789 # Default org ID (optional)
PORT=8004 # HTTP server port
HOST=0.0.0.0 # HTTP server hostRegional API URLs:
US (default):
https://www.zohoapis.com/books/v3EU:
https://www.zohoapis.eu/books/v3IN:
https://www.zohoapis.in/books/v3AU:
https://www.zohoapis.com.au/books/v3
Integration with Chat Agents
Claude Desktop
Add to your Claude Desktop configuration (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"zoho-bookkeeper": {
"command": "npx",
"args": ["zoho-bookkeeper-mcp"],
"env": {
"ZOHO_CLIENT_ID": "your_client_id",
"ZOHO_CLIENT_SECRET": "your_client_secret",
"ZOHO_REFRESH_TOKEN": "your_refresh_token"
}
}
}
}Or if installed globally:
{
"mcpServers": {
"zoho-bookkeeper": {
"command": "zoho-bookkeeper-mcp",
"env": {
"ZOHO_CLIENT_ID": "your_client_id",
"ZOHO_CLIENT_SECRET": "your_client_secret",
"ZOHO_REFRESH_TOKEN": "your_refresh_token"
}
}
}
}LibreChat
Add to your librechat.yaml:
mcpServers:
zoho-bookkeeper:
type: streamable-http
url: http://mcp-zoho-bookkeeper:8004/mcp
timeout: 30000And to your docker-compose.yml:
services:
mcp-zoho-bookkeeper:
build:
context: ./path/to/zoho-bookkeeper-mcp
container_name: mcp-zoho-bookkeeper
restart: unless-stopped
environment:
PORT: 8004
ZOHO_CLIENT_ID: ${ZOHO_CLIENT_ID}
ZOHO_CLIENT_SECRET: ${ZOHO_CLIENT_SECRET}
ZOHO_REFRESH_TOKEN: ${ZOHO_REFRESH_TOKEN}
ports:
- "8004:8004"
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8004/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30sGeneric MCP Client (HTTP)
Start the HTTP server:
# Using pnpm
pnpm serve
# Or directly
node dist/server.jsConnect to http://localhost:8004/mcp using streamable-http transport.
Generic MCP Client (stdio)
# Using pnpm
pnpm start
# Or directly
node dist/bin.jsUsage Examples
Get Organization ID (Required First Step)
Most tools require an organization_id. Get it first:
Use the list_organizations tool to get your Zoho organization IDCreate a Journal Entry
Create a journal entry dated 2025-01-15 with:
- Debit Office Supplies (account_id: 123456) for $150
- Credit Business Checking (account_id: 789012) for $150
Reference: "Office supplies purchase"Attach a Receipt
Upload the file /path/to/receipt.pdf to journal 4567890123456List Recent Expenses
List all expenses from the last 30 daysDevelopment
Setup
git clone https://github.com/bu5hm4nn/zoho-bookkeeper-mcp.git
cd zoho-bookkeeper-mcp
pnpm installCommands
pnpm build # Build TypeScript to dist/
pnpm dev # Run with hot reload (HTTP server)
pnpm serve:dev # Same as dev
pnpm start # Run stdio transport
pnpm serve # Run HTTP server
pnpm test # Run all tests
pnpm test:unit # Run unit tests only
pnpm test:watch # Run tests in watch mode
pnpm test:coverage # Run tests with coverage
pnpm lint # Check for linting errors
pnpm lint:fix # Fix linting errors
pnpm format # Format code with Prettier
pnpm format:check # Check formattingProject Structure
zoho-bookkeeper-mcp/
├── src/
│ ├── index.ts # Main MCP server setup
│ ├── server.ts # HTTP server entry point
│ ├── bin.ts # CLI entry point (stdio)
│ ├── config.ts # Configuration management
│ ├── api/
│ │ ├── client.ts # Zoho API client helpers
│ │ └── types.ts # TypeScript type definitions
│ ├── auth/
│ │ └── oauth.ts # OAuth token management
│ ├── tools/
│ │ ├── organizations.ts
│ │ ├── chart-of-accounts.ts
│ │ ├── journals.ts
│ │ ├── expenses.ts
│ │ ├── bills.ts
│ │ ├── invoices.ts
│ │ ├── contacts.ts
│ │ └── bank-accounts.ts
│ ├── utils/
│ │ ├── errors.ts
│ │ ├── mime-types.ts
│ │ └── response-parser.ts
│ └── __tests__/ # Test files
├── dist/ # Compiled JavaScript
├── Dockerfile
├── package.json
└── tsconfig.jsonAPI Endpoints
When running as HTTP server:
Endpoint | Description |
| Health check (returns JSON status) |
| MCP protocol endpoint (streamable-http) |
Troubleshooting
"Invalid OAuth token" errors
Verify your refresh token is valid
Check that your Zoho app has the
ZohoBooks.fullaccess.allscopeEnsure the correct regional API URL is set
"Organization not found" errors
Use
list_organizationsfirst to get valid org IDsSet
ZOHO_ORGANIZATION_IDenv var for default org
Attachment upload fails
Verify the file path is accessible to the server
Check file type is supported (PDF, PNG, JPG, GIF, DOC, DOCX, XLS, XLSX)
Ensure file size is within Zoho's limits
Rate limiting
This server uses ~3k tokens per request vs ~30k for the hosted Zoho MCP (100+ tools). If you still hit rate limits, add delays between requests.
Tech Stack
Runtime: Node.js 20+
Framework: FastMCP
Language: TypeScript
Auth: OAuth 2.0 with refresh token flow
Build: tsup
Testing: Vitest
Linting: ESLint + Prettier
License
MIT License - see LICENSE for details.
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
Related Projects
Model Context Protocol - The protocol specification
FastMCP - The MCP framework used by this server
Zoho Books API - Official Zoho Books API documentation
Available Tools
49 toolsadd_bill_attachmentA
Upload a file attachment to a bill. Supported file types: PDF, PNG, JPG, JPEG, GIF, DOC, DOCX, XLS, XLSX. Use this to attach vendor invoices or supporting documents.
Inputs: bill_id (required), file_path (required), organization_id.
add_expense_receiptA
Upload a receipt attachment to an expense. Supported file types: PDF, PNG, JPG, JPEG, GIF, DOC, DOCX, XLS, XLSX. Use this to attach scanned receipts or invoice images. Files must be in allowed directories and under 10MB.
Inputs: expense_id (required), file_path (required), organization_id.
add_invoice_attachmentA
Upload a file attachment to an invoice. Supported file types: PDF, PNG, JPG, JPEG, GIF, DOC, DOCX, XLS, XLSX. Use this to attach supporting documents to invoices.
Inputs: invoice_id (required), file_path (required), organization_id.
add_journal_attachmentA
Upload a file attachment to a journal entry. Supported file types: PDF, PNG, JPG, JPEG, GIF, DOC, DOCX, XLS, XLSX. Use this to attach invoices, receipts, or supporting documents to journal entries. Files must be in allowed directories and under 10MB.
Inputs: journal_id (required), file_path (required), organization_id.
categorize_bank_transaction_as_customer_paymentA
Categorize an uncategorized bank transaction as a customer payment. Use this when the bank line represents receipt of payment for one or more invoices. Prefer matching when the bank line should be linked to an existing Zoho transaction, and use manual journals only for exception cases that cannot be matched or categorized cleanly.
Inputs: transaction_id (required), customer_id (required), invoices (required), amount (required), +8 more.
categorize_bank_transaction_as_expenseA
Categorize an uncategorized bank transaction as an expense. Use this for routine spending that should become a new expense record. Prefer matching when the bank line should be linked to an existing Zoho transaction, and use manual journals only for exception cases that cannot be matched or categorized cleanly.
Inputs: transaction_id (required), account_id (required), paid_through_account_id (required), date (required), +8 more.
categorize_bank_transaction_as_vendor_paymentA
Categorize an uncategorized bank transaction as a vendor payment. Use this when the bank line represents payment of one or more vendor bills. Prefer matching when the bank line should be linked to an existing Zoho transaction, and use manual journals only for exception cases that cannot be matched or categorized cleanly.
Inputs: transaction_id (required), vendor_id (required), bills (required), amount (required), +8 more.
categorize_bank_transaction_genericA
Categorize an uncategorized bank transaction into a general Zoho bank transaction. Use this for deposits, transfers, owner contributions/drawings, interest income, other income, sales without invoices, expense refunds, sales returns, and similar bank-native bookkeeping flows. Prefer matching or expense/vendor/customer payment categorization when those are a better fit than a generic bank transaction.
Inputs: transaction_id (required), transaction_type (required), from_account_id (required), to_account_id (required), +9 more.
create_accountA
Create a new account in the chart of accounts. Account types: income, expense, cost_of_goods_sold, other_income, other_expense, asset (bank, other_current_asset, fixed_asset, other_asset, cash, accounts_receivable), liability (other_current_liability, credit_card, long_term_liability, other_liability, accounts_payable), equity (equity, retained_earnings).
Inputs: account_name (required), account_type (required), organization_id, account_code, +3 more.
create_billA
Create a new bill (accounts payable). Use list_contacts to find vendor_id values. Use list_accounts to find account_id values for line items.
Inputs: vendor_id (required), date (required), line_items (required), organization_id, +4 more.
create_expenseA
Create a new expense record. Requires account_id (expense account) and paid_through_account_id (payment account). Use list_accounts to find valid account IDs.
Inputs: account_id (required), paid_through_account_id (required), date (required), amount (required), +6 more.
create_journalA
Create a new manual journal entry. Line items must balance (total debits = total credits). Use list_accounts to find valid account_id values.
Inputs: journal_date (required), line_items (required), organization_id, reference_number, +1 more.
create_vendorA
Create a new vendor contact. Use this when expense, bill, or vendor-payment workflows need a vendor_id that does not exist yet in Zoho Books.
Inputs: organization_id, contact_name, display_name, company_name, +6 more.
delete_bill_attachmentC
Delete attachment from a bill. Removes the file association from the bill.
Inputs: bill_id (required), organization_id.
delete_expense_receiptA
Delete receipt/attachment from an expense. Removes the file association from the expense.
Inputs: expense_id (required), organization_id.
delete_invoice_attachmentA
Delete attachment from an invoice. Removes the file association from the invoice.
Inputs: invoice_id (required), organization_id.
delete_journalA
Delete a journal entry. This action cannot be undone. The journal will be permanently removed.
Inputs: journal_id (required), organization_id.
delete_journal_attachmentA
Delete attachment from a journal entry. Removes the file association from the journal.
Inputs: journal_id (required), organization_id.
get_accountARead-only
Get detailed information about a specific account. Returns account details including balance, currency, and parent account info.
Inputs: account_id (required), organization_id.
get_bank_accountARead-only
Get detailed information about a specific bank account. Returns full bank account details including routing number and balance.
Inputs: account_id (required), organization_id.
get_bank_transaction_matchesARead-only
Get candidate Zoho transactions that can be matched to an uncategorized bank transaction. Use this before match_bank_transaction to inspect possible matches. Zoho may return direct bank transactions and also invoices, bills, or credit notes that can be reconciled via derived payment/refund entries.
Inputs: account_id (required), transaction_id (required), organization_id, transaction_type, +8 more.
get_billARead-only
Get detailed information about a specific bill. Returns full bill details including line items and vendor info.
Inputs: bill_id (required), organization_id.
get_bill_attachmentARead-only
Get attachment information for a bill. Returns details about any files attached to the bill.
Inputs: bill_id (required), organization_id.
get_contactARead-only
Get detailed information about a specific contact. Returns full contact details including payment terms and currency settings.
Inputs: contact_id (required), organization_id.
get_expenseARead-only
Get detailed information about a specific expense. Returns full expense details including account, vendor, and billable status.
Inputs: expense_id (required), organization_id.
get_expense_receiptARead-only
Get receipt/attachment information for an expense. Returns details about any files attached to the expense.
Inputs: expense_id (required), organization_id.
get_invoiceARead-only
Get detailed information about a specific invoice. Returns full invoice details including line items and customer info.
Inputs: invoice_id (required), organization_id.
get_invoice_attachmentARead-only
Get attachment information for an invoice. Returns details about any files attached to the invoice.
Inputs: invoice_id (required), organization_id.
get_journalARead-only
Get detailed information about a specific journal entry. Returns full journal details including all line items.
Inputs: journal_id (required), organization_id.
get_journal_attachmentARead-only
Get attachment information for a journal entry. Returns details about any files attached to the journal.
Inputs: journal_id (required), organization_id.
get_organizationARead-only
Get detailed information about a specific organization. Returns full organization details including address, contact info, and settings.
Inputs: organization_id.
get_vendorARead-only
Get detailed information about a specific vendor. Use this to confirm a vendor_id before creating expenses, bills, or vendor-payment categorizations.
Inputs: vendor_id (required), organization_id.
list_accountsARead-only
List all accounts in the chart of accounts. Supports filtering by account type (e.g., income, expense, asset, liability, equity). Use this to find account_id values for journal entries and transactions.
Inputs: organization_id, filter_by, sort_column.
list_account_transactionsARead-only
List transactions for a specific account. Returns all transactions (journals, invoices, bills, etc.) affecting this account. Useful for account reconciliation and analysis.
Inputs: account_id (required), organization_id, date_start, date_end, +1 more.
list_bank_accountsARead-only
List all bank accounts in Zoho Books. Returns bank account details with name, type, and balance. These are the accounts linked in Zoho Books, not live bank data.
Inputs: organization_id, filter_by, sort_column.
list_bank_transactionsARead-only
List bank transactions in Zoho Books. Returns transactions recorded in Zoho Books for bank reconciliation. These are transactions imported/entered in Zoho, not live bank feeds. Bank transaction status is a reconciliation status and is separate from journal creation.
Inputs: account_id (required), organization_id, date_start, date_end, +4 more.
list_billsARead-only
List all bills (accounts payable). Supports filtering by date, vendor, and status. Returns bill details with vendor, amount, and due date.
Inputs: organization_id, date_start, date_end, vendor_id, +4 more.
list_contactsARead-only
List all contacts (customers and vendors). Supports filtering by contact type (customer or vendor). Use this to find contact_id values for bills, invoices, and expenses.
Inputs: organization_id, contact_type, status, search_text, +3 more.
list_expensesBRead-only
List all expenses. Supports filtering by date, status, and customer. Returns expense details with account, amount, and vendor info.
Inputs: organization_id, date_start, date_end, status, +5 more.
list_invoicesARead-only
List all customer invoices (accounts receivable). Supports filtering by date, customer, and status. Returns invoice details with customer, amount, and due date.
Inputs: organization_id, date_start, date_end, customer_id, +4 more.
list_journalsARead-only
List all manual journal entries. Returns journal entries with date, reference number, and total. Use date filters to narrow down results.
Inputs: organization_id, date_start, date_end, sort_column, +2 more.
list_organizationsARead-only
List all Zoho organizations the user has access to. Use this tool first to get organization_id for all other tools. Returns organization name, ID, currency, and timezone.
Inputs: no named parameters.
list_vendorsARead-only
List vendor contacts only. Use this to find vendor_id values for expenses, bills, and vendor-payment bank categorization workflows.
Inputs: organization_id, status, search_text, sort_column, +2 more.
match_bank_transactionA
Match an uncategorized bank transaction to one or more existing Zoho transactions. Use get_bank_transaction_matches first to inspect candidates. This updates bank reconciliation status; creating a journal alone does not mark imported bank transactions as matched.
Inputs: account_id (required), transaction_id (required), transactions_to_be_matched (required), organization_id.
publish_journalA
Publish (mark as posted) a draft journal entry. Published journals are finalized and affect account balances.
Inputs: journal_id (required), organization_id.
uncategorize_bank_transactionA
Uncategorize a previously categorized bank transaction and return it to uncategorized status. Use this to reverse an incorrect categorization and reprocess the bank line correctly. After uncategorizing, decide whether the bank line should be matched to an existing Zoho transaction, recategorized, or handled with a manual journal only in exception cases.
Inputs: account_id (required), transaction_id (required), organization_id.
unmatch_bank_transactionA
Unmatch a previously matched bank transaction and return it to uncategorized status. Use this when the wrong Zoho transaction was reconciled to a statement line.
Inputs: account_id (required), transaction_id (required), organization_id.
update_journalA
Update an existing journal entry. Can update date, reference, notes, and line items. Line items must still balance after update.
Inputs: journal_id (required), organization_id, journal_date, reference_number, +2 more.
update_vendorA
Update an existing vendor contact. Use this to correct or enrich vendor details needed for expenses, bills, and vendor-payment workflows.
Inputs: vendor_id (required), organization_id, contact_name, display_name, +7 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 49 tools
Each tool targets a distinct entity and action, with clear separation even for similar operations like categorizing bank transactions. Attachment tools are differentiated by entity type.
All tool names follow a consistent verb_noun pattern in snake_case, using standard verbs like create, list, get, update, delete, add, categorize, match.
With 49 tools, the count is high but justified given the comprehensive coverage required for Zoho Books' accounting operations. The tools are well-scoped and non-redundant.
Basic CRUD is present for most entities, but missing update operations for bills, invoices, expenses, and accounts, and no delete for those entities. Bank reconciliation tools are thorough.
Maintenance
Related MCP Connectors
Hosted MCP server connecting AI assistants to 9,000+ apps and 40,000+ actions via Zapier.
AI for Tally Prime and Tally ERP 9. Hosted MCP server to ask your accounts in any language.
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceAn MCP server that enables AI agents to interact with QuickBooks Online accounts to manage invoices, customers, payments, and financial reports. It provides 20 tools to automate accounting workflows and retrieve financial data through natural language interfaces.-
- AlicenseCqualityDmaintenanceA unified MCP server that integrates Zoho CRM and Zoho Books, enabling AI assistants to manage CRM records, Books customers/invoices, synchronize data, and search across both systems.1004MIT
- AlicenseNot gradedqualityAmaintenanceMCP server enabling AI assistants to manage invoices, contacts, products, and other accounting data through the Bukku API.9MIT
- AlicenseBqualityDmaintenanceAn enhanced MCP server for Zoho Projects API integration, enabling AI assistants to manage projects, tasks, issues, milestones, comments, attachments, and more with automatic OAuth token refresh.39MIT