zoho-books-mcp

zoho-books-mcp

A safety-gated MCP server for Zoho Books that enables AI agents to perform general-ledger writes, bank-feed categorization, and receipt attachments not exposed by Zoho's native connector, with hard guardrails preventing unauthorized actions on live data.

Category
访问服务器

README

zoho-books-mcp

A local, safety-gated Model Context Protocol server for Zoho Books — it gives an AI agent the general-ledger writes, bank-feed categorization, and receipt attachment that Zoho's native connector doesn't expose, with hard guardrails so it can't run wild on your live books.

⚠️ This lets an AI create, update, and (optionally) delete real records in your live accounting. It ships read-only by default — every write is off until you deliberately turn it on. Read the Safety model before enabling anything, and supervise your agent.

Unofficial — not affiliated with, endorsed by, or sponsored by Zoho Corporation. "Zoho" and "Zoho Books" are trademarks of their respective owner. This is an independent community tool that talks to the public Zoho Books API using your own credentials.


Human-written note

Neither QBO nor Xero expose live bank feeds via their APIs, and by all indications never will. This is directly contradictory to their AI-native marketing posture, and functionally useless to an autonomous bookkeeping agent responsible for monitoring an email inbox for invoices and receipts, booking them against a bank feed, and maintaining the ledger. Zoho does expose this, but their native MCP and Claude connectors are equally impotent, with respect to their tool calls and permission gates; they can't create accounts, post certain transactions, or delete stuff. It seems to me, as of July 2026, that they want their connectors to do data analysis and modeling, where I want my agents to actually do my books.

You could get the same bank feed data straight from Plaid or Yodlee, but that's another subscription to pay for, another MCP to manage, and another set of credentials to care about. Yuck. This MCP expands the capabilities of the agent to basically whatever the Zoho API allows, while keeping write permissions toggled off by default and routing everything through an inference-level approval gate. It's incredibly useful, but powerful enough to be dangerous, if you're irresponsible or lazy. Use this tool intelligently.

On file uploads: Zoho, like most accounting software, lets you attach documents to transactions, like invoices or receipts. When you give your bookkeeping agent that document, it wants to convert it to base64 or binary and pipe it through the API, which blows your context window. The solution is serverside, so your agent can pass POSTs straight from your Google Drive or Dropbox or whatever; this requires OAuth and possibly GCP-esque configuration, and is not included in this repo. In other words: if you want your agent to do the document-attaching for you, you'll need to configure its access to your cloud drive yourself.

Cheers, and happy accounting. Steven

Why this exists

We built this for our own AI bookkeeper, then cleaned it up to share. The short version:

Autonomous bookkeeping lives or dies on API access to the bank feed — the stream of real bank activity an agent must see in order to categorize and reconcile it. In our experience (as of 2026), Xero and QuickBooks Online don't expose that feed through their public APIs: you can push and pull transactions, but you can't reach the live bank feed itself, which leaves an agent blind to the one thing it most needs to act on.

Zoho Books does expose it — its bank feeds are Plaid-sourced and reachable via the API — which makes it the one mainstream option an agent can drive end-to-end. The catch was the tooling around it: the native connectors we tried couldn't post journals, build the chart of accounts, categorize feed lines, or attach source docs. So we wrote a thin, guarded server that does — straight against Zoho's public v3 API, no third-party SDK, no broker. Your credentials stay on your machine and leave only as ordinary HTTPS calls to Zoho.

What it's for: running behind a hosted AI-employee agent (e.g. Openclaw or Hermes), ideally on a VPS, under strict permission gates and human supervision. It ships read-only by default for exactly that reason.

A word of caution: this is genuinely useful and genuinely powerful — enough to make a real mess of real financial records if you point it at production with the gates open and walk away. Don't. Keep writes off until you trust your setup, scope the Zoho user's role tightly, and watch what your agent does. Treated with that respect it's a capable teammate; treated carelessly it's a footgun.

Shared freely by Operamatix, LLC as a contribution to the broader agentic-bookkeeping community.

Features

  • Verb-split passthrough — zoho_read / zoho_write / zoho_delete reach any Zoho Books v3 endpoint.
  • Guarded GL wrappers — manual journals (balance-enforced) and chart-of-accounts creation.
  • Bank-feed workflow — categorize an uncategorized feed line in place, or match it to existing transactions. (Includes the endpoints and request bodies Zoho's docs don't render — see Bank-feed categorization.)
  • Attachments — upload receipts / source docs to expenses, bills, and journals (by base64 or local file path).
  • Safety-first — every mutating action sits behind an env flag that is off by default and enforced in code.

Safety model

The guardrails are hard floors enforced in the server — not suggestions the model can talk its way past:

Control Default Effect
ZOHO_ALLOW_WRITES false All create/update refuse until set to "true".
ZOHO_ALLOW_DELETE false All DELETE refuse until set to "true".
Balanced journals always on zoho_create_journal refuses to post unless total debits == total credits.
Verbatim errors always on Zoho's error response is surfaced as-is — writes fail loud, never silently.

Recommended posture: keep ZOHO_ALLOW_WRITES=false while you learn the tool; enable writes once you trust your agent and prompts; leave ZOHO_ALLOW_DELETE=false unless you have a specific need. Zoho also enforces the role of the user your credentials belong to, on top of these flags — scope that user to the minimum the agent needs.

Requirements

  • Node.js ≥ 20
  • A Zoho Books organization and API credentials (below)

Setup

1. Get Zoho credentials (Self Client / client-credentials)

  1. Go to the Zoho API Console → Self Client.
  2. Generate a grant token with a Zoho Books scope (e.g. ZohoBooks.fullaccess.all, or something narrower).
  3. Exchange the grant token for a refresh token — a standard OAuth authorization_code POST to https://accounts.zoho.com/oauth/v2/token. Keep the refresh_token.
  4. Note your organization_id (Zoho Books → Settings, or GET /organizations).

The credentials operate as the Zoho user who created the Self Client, so create it under the account/role you want the agent to act as. (Non-US data centers: use the matching accounts.zoho.* / zohoapis.* domains — see env vars.)

2. Install

npm install

3. Configure your MCP client

Example Claude Desktop claude_desktop_config.json entry. Use an absolute node path — desktop apps launch MCP servers with a minimal PATH, so a bare node won't resolve:

"zoho-books": {
  "command": "/absolute/path/to/node",
  "args": ["/absolute/path/to/zoho-books-mcp/zoho-books-mcp.mjs"],
  "env": {
    "ZOHO_CLIENT_ID": "...",
    "ZOHO_CLIENT_SECRET": "...",
    "ZOHO_REFRESH_TOKEN": "...",
    "ZOHO_ORGANIZATION_ID": "...",
    "ZOHO_ALLOW_WRITES": "false"
  }
}

See .env.example for every variable.

Tools

Tool Action Gate
zoho_read GET any endpoint always on
zoho_write POST/PUT any endpoint ZOHO_ALLOW_WRITES
zoho_delete DELETE any endpoint ZOHO_ALLOW_DELETE
zoho_create_journal manual journal (balance-enforced) ZOHO_ALLOW_WRITES
zoho_create_account chart-of-accounts account ZOHO_ALLOW_WRITES
zoho_categorize_bank_txn categorize an uncategorized feed line ZOHO_ALLOW_WRITES
zoho_match_bank_txn match a feed line to existing transactions ZOHO_ALLOW_WRITES
zoho_attach_document upload a receipt/doc (base64 or path) ZOHO_ALLOW_WRITES

Bank-feed categorization

Zoho's Banking API docs don't fully render the request bodies for categorizing an uncategorized transaction, so here is what this server confirmed against the live API:

  • Route (note the singular uncategorized): POST /banktransactions/uncategorized/{transaction_id}/categorize, or .../categorize/{expenses|customerpayments|vendorpayments} for module types.
  • A deposit / owner contribution is a from/to model, not a flat account field:
    { "transaction_type": "deposit",
      "from_account_id": "<offset, e.g. equity>",   // credited
      "to_account_id":   "<bank account>",          // debited
      "amount": 500, "date": "2026-06-30" }
    
  • An expense (money out): use categorize_as: "expenses" with account_id (the expense account), paid_through_account_id (the bank), amount, and date.

The zoho_categorize_bank_txn wrapper handles this for you: pass offset_account_id and it maps to the correct field per type, auto-deriving amount/date/bank from the feed line.

Confirmed vs. inferred

This server was validated against a live US Zoho Books organization. Some behavior is confirmed, some inferred — treat inferred rows as "probably right, not yet verified," and remember every write can be reviewed in Zoho:

Area Status
Auth, read, write, delete, journals, accounts, contacts, expenses ✅ confirmed
Categorize: deposit / owner_contribution (from/to model) ✅ confirmed
Categorize: expenses, vendorpayments ✅ confirmed
Attach: expense receipt (field receipt), journal (field attachment) ✅ confirmed (live round-trip)
Attach: bill (field attachment) ⚠️ inferred — same pattern, untested
Categorize: money-OUT directions (owner_drawings, transfer_fund, …) ⚠️ inferred — pass explicit from_account_id / to_account_id
Non-US data centers ⚠️ untested — set ZOHO_ACCOUNTS_DOMAIN / ZOHO_API_DOMAIN

Environment variables

Variable Required Default Notes
ZOHO_CLIENT_ID ✅ — Self Client id
ZOHO_CLIENT_SECRET ✅ — Self Client secret
ZOHO_REFRESH_TOKEN ✅ — long-lived refresh token
ZOHO_ORGANIZATION_ID recommended — auto-added to every call
ZOHO_ALLOW_WRITES false "true" permits create/update
ZOHO_ALLOW_DELETE false "true" permits DELETE
ZOHO_ACCOUNTS_DOMAIN https://accounts.zoho.com change for non-US DC
ZOHO_API_DOMAIN https://www.zohoapis.com change for non-US DC

Testing

npm install
npm test

The smoke test spawns the server with dummy credentials and asserts the tool surface plus that every guard trips before any network call — so it never touches Zoho.

License

MIT. Provided as-is, without warranty — you are responsible for what your agent does to your books. Test with ZOHO_ALLOW_WRITES=false first.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选