Zoho CRM MCP Server
Provides tools for interacting with Zoho CRM's REST API v8, enabling AI agents to manage records, modules, fields, users, workflows, bulk operations, attachments, notes, and more. Supports CRUD operations, scoped session mode, and OAuth 2.0 authentication.
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 CRM MCP Servercreate a new lead named John Doe from Acme Corp"
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 CRM MCP Server (FastAPI + FastMCP)
A production-grade Model Context Protocol (MCP) server built with FastAPI + FastMCP that gives Claude and other AI clients complete, authenticated access to the Zoho CRM REST API v8 โ from reading records to designing modules and authoring workflow automation.
211 MCP tools covering records, COQL, schema design, workflow rules and their actions, webhooks, bulk/mass operations, tags, notes, email, security settings, and bulk import/export โ plus a dashboard and report engine, function authoring and attachment to workflow rules, org hierarchy tools, and teamspaces โ and a generic zoho_api_request escape hatch for anything Zoho exposes that has no dedicated tool.
๐ Key Features
FastAPI Web Framework: High-performance, production-ready ASGI app powered by Uvicorn.
Dual Transport: Runs as a Streamable HTTP MCP server (for remote/cloud hosting) and as a STDIO MCP server (for local Claude Desktop).
Full OAuth 2.0 Lifecycle: Automatic code exchange, browser redirect handler (
/auth/callback), encrypted token storage, and a background loop that keeps the token fresh while the server runs.Chat-Configurable Credentials: Supply a Zoho Client ID/Secret from chat (
set_zoho_credentials, or inline onget_auth_url/exchange_auth_code) instead of.envโ useful for switching Zoho accounts without restarting.Dashboard Report Home Page:
/serves a live dashboard โ record counts per module, workflow and function inventory, org chart, teamspaces, pinned reports, and the activity feed โ all backed byGET /api/dashboard/summary. Panels load concurrently and fail independently, so one missing OAuth scope never blanks the page.Report Engine: Save report definitions (
list,count,summarywith count/sum/avg/min/max and group-by) that compile to COQL and run against live CRM data. Pin one to the dashboard, re-run it on demand, or export it to CSV. Zoho has no Reports API, so this is the working substitute.Function Authoring (v8 Functions API): Create, read, update, publish, and delete Deluge/Java/NodeJS/Python functions, and download their source.
Functions Attached to Workflows:
functionsis a first-class workflow action type, so a function can be wired into a rule as an instant or scheduled action โ and detached again โ without touching the Zoho UI.Org Hierarchy: Role and user-reporting trees assembled from Zoho's flat lists, with an ASCII org chart, subordinate/manager lookups, and the writes that reparent a role or reassign a manager.
Teamspaces: Group modules and people into named teamspaces, optionally projected onto a real CRM user group so the same roster drives sharing and assignment in Zoho.
Complete Automation Authoring: Build workflow rules end to end โ create field-update, email-notification, task, and webhook actions, then wire them into a rule with triggers and criteria.
Schema Design: Create custom modules (with the profiles Zoho mandates), fields, global picklists, layouts, and sales pipelines.
Scoped Session Mode: ID-based safety filter (
activate_scope) restricting operations to specific record IDs.Human-In-The-Loop Approvals: Destructive actions queue a pending request instead of executing. Toggle with
ZOHO_REQUIRE_APPROVAL.Structured Activity Logging: Every auth event, API call, and approval decision logged as JSON, retrievable via
get_logs()/GET /logs.Encrypted Token Storage: OAuth tokens encrypted at rest (Fernet/AES), never plaintext.
Resilient Network Client: Pooled
httpxclient with automatic 401 refresh-and-retry, clamped 429 backoff, exponential 5xx retry, an outbound rate limiter, and partial-failure detection on Zoho's per-record responses.Multi-Account Isolation: Each Zoho
client_idis an isolated tenant - its own tokens, scope, approval queue, reports, and teamspaces - resolved per MCP session or per REST header. Concurrent callers on different accounts cannot read or write each other's org.Automated Test Suite: 93
pytesttests covering the HTTP surface, tool registration, request-payload shapes, client guards, the COQL report compiler, hierarchy tree assembly, teamspace rostering, and function-to-workflow attachment.
Related MCP server: Zoho CRM MCP Server
๐ Repository Structure
zoho-crm-mcp/
โโโ server.py # FastAPI app + all FastMCP tool definitions & REST endpoints
โโโ auth_manager.py # OAuth 2.0 flow, scopes & token refresh
โโโ zoho_client.py # Async HTTP client for Zoho CRM API v8 (193 methods)
โโโ models.py # Pydantic state & validation models
โโโ token_store.py # Encrypted (Fernet) token persistence
โโโ approval_manager.py # HITL approval queue for high-risk actions
โโโ activity_log.py # Structured JSON activity logger
โโโ dashboard.py # Dashboard aggregation (concurrent, per-panel errors)
โโโ report_store.py # Report definitions + COQL compiler, runner & CSV export
โโโ hierarchy.py # Role/user tree assembly and hierarchy mutations
โโโ teamspace_store.py # Teamspace registry + CRM user-group projection
โโโ web_ui.py # The dashboard home page (no CDN, no build step)
โโโ tenancy.py # Per-account isolation: tenant registry, ContextVar, proxies
โโโ test_server.py # pytest suite
โโโ requirements.txt # Dependencies
โโโ .env.example # Environment configuration template
โโโ pyproject.toml # Package metadata
โโโ README.mdโ๏ธ Setup & Installation
1. Prerequisites
Python 3.10+
A Zoho CRM API Console app (Zoho API Console)
Client Type: Server-based Applications
Redirect URI:
http://localhost:8000/auth/callback(or your deployment callback URL)
2. Environment Setup
cp .env.example .envMinimum configuration:
ZOHO_CLIENT_ID=1000.xxxxxxx
ZOHO_CLIENT_SECRET=xxxxxxx
ZOHO_REDIRECT_URI=http://localhost:8000/auth/callback
ZOHO_DATA_CENTER=com
PORT=8000See .env.example for every supported variable, including the approval gate, OAuth scope override, rate limit, and timeout settings.
Working with more than one Zoho account?
ZOHO_CLIENT_ID/ZOHO_CLIENT_SECRETare optional. Leave them blank and ask Claude to callset_zoho_credentials(client_id, client_secret, redirect_uri?, data_center?), or passclient_id/client_secretdirectly toget_auth_url/exchange_auth_code. Switchingclient_idclears tokens saved for the previous account, avoiding Zoho'sinvalid_clienterror from reusing a refresh token issued to a different app.
3. Install Dependencies
pip install -r requirements.txt๐ Running & Deploying
Option A: Local FastAPI Web Server
python server.pyOr with Uvicorn directly:
uvicorn server:app --host 0.0.0.0 --port 8000Once running:
Web Dashboard: http://localhost:8000/
Swagger Docs: http://localhost:8000/docs
Health Check: http://localhost:8000/health
MCP Endpoint:
http://localhost:8000/mcp/
The MCP endpoint is served at the mount root, so the path is
/mcp/โ not/mcp/mcp. Keep the trailing slash:/mcpanswers with a 307 redirect, which not every MCP client follows correctly on a POST.
Option B: Local STDIO
python server.py --stdioOption C: Cloud Deployment (Render, Railway, Docker, AWS, Heroku)
Start Command:
uvicorn server:app --host 0.0.0.0 --port $PORTHealth Check Path:
/healthEnvironment Variables: set
ZOHO_CLIENT_ID,ZOHO_CLIENT_SECRET,ZOHO_REDIRECT_URI,ZOHO_DATA_CENTER, andZOHO_TOKEN_ENCRYPTION_KEY(so tokens survive restarts on ephemeral filesystems).
Live deployment
Dashboard | |
Health | |
MCP endpoint |
|
Staying authenticated on an ephemeral host. Render wipes the filesystem on every
deploy and restart, taking ~/.zoho_crm_tokens.json with it โ and the Fernet key at
~/.zoho_crm_mcp.key is regenerated on each boot, so even a surviving token file could
not be decrypted. Set both of these in the host's environment and the server
re-authenticates itself instead of asking for tokens again:
ZOHO_REFRESH_TOKENโ picked up on cold boot, so a fresh access token is minted automatically. Refresh tokens do not expire unless revoked.ZOHO_TOKEN_ENCRYPTION_KEYโ a stable Fernet key, so the cached access token survives too. Generate one with:python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
Token refresh itself is automatic and needs no configuration: get_valid_access_token()
renews anything expiring within 5 minutes, and a background loop re-checks every
ZOHO_TOKEN_REFRESH_INTERVAL seconds (default 120).
๐ฅ๏ธ Claude Desktop Integration
Mode 1: HTTP / Remote MCP Connection
Local:
{
"mcpServers": {
"zoho-crm": {
"url": "http://localhost:8000/mcp/"
}
}
}Deployed:
{
"mcpServers": {
"zoho-crm": {
"url": "https://zoho-crm-mcp-07t7.onrender.com/mcp/"
}
}
}The server has no MCP-level authentication, so leave any "OAuth Client ID" field in the
connector settings blank. The Zoho OAuth inside the server authenticates it to Zoho; it
does not gate the MCP endpoint. Pointing a client at the wrong path (/mcp/mcp) returns
404, which some clients report as a misleading sign-in or registration failure rather than
as a bad URL.
Mode 2: Local STDIO Connection
{
"mcpServers": {
"zoho-crm": {
"command": "python",
"args": ["C:/Users/Lenovo/Desktop/zoho MCP/server.py", "--stdio"],
"env": {
"ZOHO_CLIENT_ID": "1000.YOUR_CLIENT_ID",
"ZOHO_CLIENT_SECRET": "YOUR_CLIENT_SECRET",
"ZOHO_REDIRECT_URI": "http://localhost:8000/auth/callback",
"ZOHO_DATA_CENTER": "com"
}
}
}
}๐ First-Run OAuth Flow
Start the server:
python server.pyOpen
http://localhost:8000/auth/url, or ask Claude to runget_auth_url().Open the returned URL, sign in to Zoho CRM, click Accept.
Zoho redirects to
/auth/callback?code=...; the server exchanges the code and saves encrypted tokens to~/.zoho_crm_tokens.json.
๐งฉ Building Automation: The Workflow Recipe
Zoho models a workflow rule as a trigger plus conditions, where each condition points at pre-created action objects. Build them in that order:
1. get_workflow_configurations(module="Leads")
-> see which triggers, comparators, and action types this org supports
2. create_field_update_action(
name="Mark as Hot", module="Leads",
field_api_name="Rating", value="Hot")
-> returns the action id
3. create_workflow(
name="Hot Lead Router",
module="Leads",
execute_when={"type": "create_or_edit"},
conditions=[{
"sequence_number": 1,
"criteria_details": {"criteria": {"group_operator": "and", "group": [
{"comparator": "equal",
"field": {"api_name": "Lead_Source"},
"value": "Web Form"}]}},
"instant_actions": {"actions": [
{"id": "<action id from step 2>", "type": "field_updates"}]}}])
4. activate_workflow(workflow_id="...")The same pattern applies with create_email_notification_action, create_automation_task, and create_webhook as the action source.
๐ Dashboard & Report Home Page
GET / is a live dashboard, not a status card. It shows record counts per module, the
workflow and function inventory (broken down by runtime and category), the org chart,
teamspaces, every pinned report, and the recent activity feed โ with an in-page report
runner for ad-hoc queries.
Panels are fetched concurrently and each carries its own error, so a missing OAuth scope costs you one panel rather than the whole page. The same payload is available as JSON:
curl localhost:8000/api/dashboard/summary
curl "localhost:8000/api/dashboard/summary?modules=Deals,Leads&include_hierarchy=false"From an MCP client:
get_dashboard_summary() # everything
get_module_record_counts(["Deals", "Leads"]) # just the countsReports
A report is a definition stored on this server that compiles to COQL and runs against live CRM data. Three shapes:
# 1. list โ rows of fields
create_report(name="Big open deals", module="Deals", type="list",
fields=["Deal_Name", "Stage", "Amount"],
criteria="(Amount > 50000) and (Stage != 'Closed Won')",
sort_by="Amount", sort_order="desc")
# 2. count โ how many match
create_report(name="Web leads", module="Leads", type="count",
criteria="(Lead_Source = 'Web Form')")
# 3. summary โ aggregate, grouped; pinned to the dashboard home page
create_report(name="Pipeline by stage", module="Deals", type="summary",
group_by=["Stage"],
aggregates=[{"function": "sum", "field": "Amount", "alias": "pipeline"}],
pinned=True)
run_report("Pipeline by stage") # by name or id
run_adhoc_report(module="Deals", type="count") # iterate without saving
export_report("Pipeline by stage", save_to="./pipeline.csv")Aggregates take count, sum, avg, min, and max; alias is the column name you
get back. criteria is a COQL where clause, and omitting it matches every record. Rows
cap at 2000 per report โ use bulk_read_create_job for a full export.
create_dashboard_widget(...) is the same thing pinned in one step.
โก Functions, and Attaching Them to Workflows
v8 exposes a real Functions API, so functions are authored over the wire. Deluge source goes inline; Java, NodeJS, and Python ship as a ZIP and then need publishing.
get_function_runtimes() # what this org allows, and what's deprecated
get_function_categories() # 'Automation' is the workflow-callable one
create_function(
name="Flag big deal",
api_name="flag_big_deal",
category="Automation",
runtime="Deluge 1.0",
code='''void automation.flag_big_deal(Map deal)
{
// Deluge body
}''')
get_function_code("flag_big_deal") # read it back
update_function("flag_big_deal", code="...") # Deluge auto-publishes
publish_function("nightly_sync") # Java/NodeJS/Python draftsapi_name, runtime, and category are immutable in Zoho โ to change any of them,
create a new function.
functions is a first-class workflow action type, so a function can be wired straight
into a rule:
# instant: runs the moment the rule fires
attach_function_to_workflow(workflow_id="...", function="flag_big_deal", module="Deals")
# scheduled: runs two days later
attach_function_to_workflow(workflow_id="...", function="flag_big_deal", module="Deals",
scheduled_after={"period": "days", "unit": 2})
list_workflow_actions(workflow_id="...", module="Deals")
detach_function_from_workflow(workflow_id="...", function="flag_big_deal", module="Deals")A rule's actions hang off its conditions, so attaching one is read-modify-write on the
target condition โ existing actions on that condition are preserved. condition_sequence
picks which condition (default 1). attach_action_to_workflow does the same for the other
action types: pass action_id for an existing field update, email notification, task, or
webhook, or details for an inline action like add_tags or create_record. Check
get_workflow_configurations(module=...) first โ a trigger only accepts certain actions.
๐ข Hierarchy & Teamspaces
Hierarchy
Zoho returns roles and users as flat lists with reporting_to pointers and no tree
endpoint, so these tools assemble one:
get_hierarchy_preference() # Role_Hierarchy or Reporting_Hierarchy (read-only in Zoho)
get_role_hierarchy() # nested tree + an ASCII org chart + depth
get_user_hierarchy() # same, from each user's reporting_to
get_subordinates("4876...001", of="user", deep=True) # + the managers above themBoth trees come with an ascii org chart, which is what an AI client can actually read
back:
CEO
โโโ VP Sales
โ โโโ Manager EU
โ โ โโโ AE Berlin
โ โ โโโ AE Paris
โ โโโ Manager US
โโโ VP MarketingA role whose parent is outside your permission scope still appears, listed under
orphans rather than silently dropped. The mutations are real Zoho writes:
create_role_under(name="Manager EU", parent_role_id="...")
set_role_parent(role_id="...", parent_role_id="...") # moves the whole subtree
set_user_manager(user_id="...", manager_user_id="...") # omit to clear
assign_user_role(user_id="...", role_id="...")Teamspaces
Teamspaces group modules and people. Zoho's REST API has no teamspaces endpoint, so the roster lives on this server โ and can be projected onto a real CRM user group, which is Zoho's own way to name a set of people for sharing and assignment:
create_teamspace(
name="EMEA Sales",
modules=["Deals", "Contacts"],
members=["4876...001", {"user_id": "4876...002", "role": "viewer"}],
lead_user_id="4876...001",
create_crm_user_group=True) # also creates the Zoho user group
add_teamspace_members("EMEA Sales", [{"user_id": "...", "role": "member"}])
set_teamspace_modules("EMEA Sales", add=["Tasks"], remove=["Contacts"])
sync_teamspace_to_crm("EMEA Sales") # push the roster onto the linked group
get_user_teamspaces("4876...001")Member roles are lead, member, or viewer. If the CRM user group can't be created
(a duplicate name, say), the teamspace is still kept and the response says the CRM-side
binding failed โ the registry is the source of truth, the group is its projection.
The underlying Zoho user groups are also directly addressable: get_user_groups,
create_user_group, update_user_group, delete_user_group,
get_user_group_associations.
๐ REST Surface
Beyond the MCP endpoint, the dashboard's data is plain JSON:
Endpoint | Purpose |
| The whole dashboard ( |
| Record counts per module |
| Workflow rules, limits, and the function inventory |
| List and save report definitions |
| Run an ad-hoc definition |
| One saved report |
| Hierarchy model and trees |
| Subordinates ( |
| List and create teamspaces |
| One teamspace ( |
| The org's functions |
| Every action attached to a rule |
| Resident accounts and their state, credentials masked |
Every endpoint accepts an X-Zoho-Client-Id header to select which account it acts for.
๐ฅ Multi-Account Isolation (Tenancy)
This server is safe to share between many Zoho accounts and many AI clients at
once. Each Zoho client_id is a tenant with its own tokens, scope, approval
queue, reports, and teamspaces. Concurrent callers using different credentials
cannot read or write each other's org.
How a caller picks its account
MCP clients โ call set_zoho_credentials once; that session is bound to the
account for its lifetime, and every later tool call routes there automatically:
set_zoho_credentials(client_id="1000.AAAA", client_secret="...")
get_tenant_info() # confirm which account you are pointed at
create_record(...) # goes to 1000.AAAA, whatever other sessions are doingREST callers โ send the account's client_id as a header:
curl localhost:8000/api/reports -H 'X-Zoho-Client-Id: 1000.AAAA'
curl localhost:8000/tenants # resident accounts, credentials maskedResolution order, first match wins: an explicit binding on the current task โ
the calling MCP session's binding โ the X-Zoho-Client-Id header โ the .env
account. A deployment that never calls set_zoho_credentials behaves exactly as
a single-account server, on the same file paths as before.
What is isolated, and why each one matters
Per tenant | Why |
| Otherwise a second caller's credentials overwrite the first's mid-request, and calls execute against the wrong org |
| Its |
Rate limiter | One account's burst would otherwise throttle all the others |
| A scope activated by one account would filter and block another's records |
Approval queue | Approvals are per-account, and a queued action executes pinned to the tenant that raised it |
Reports & teamspaces | Definitions reference one org's modules and users |
Activity log reads | One shared audit trail, tagged per tenant; reads are filtered to the caller ( |
How the isolation works
The current tenant lives in a contextvars.ContextVar. ContextVars are copied
per asyncio task, so two interleaved requests each see their own value โ
isolation by construction rather than by locking. The module-level names
(zoho_client, auth_manager, โฆ) are thin proxies that resolve the calling
task's tenant on every attribute access, which is why all 211 tool bodies are
unchanged.
OAuth needed one extra step: a browser callback carries no session, so
get_auth_url puts the tenant key in the OAuth state parameter and
/auth/callback reads it back to store the tokens against the right account.
Operating notes
Tenant state lives under
ZOHO_STATE_DIR(default~/.zoho_crm_mcp/tenants/<hash>/), one directory per account, named by a hash of the client_id rather than the client_id itself. The.envaccount keeps the original home-directory paths.Residency is capped by
ZOHO_MAX_TENANTS(default 250); idle tenants past the cap have their connection pools closed by the background loop. Tenants still bound to a live session are never evicted.Token refresh runs per tenant inside that tenant's context, so a refresh can never write one account's token into another's store.
get_tenant_info()reports which account a session resolved to and how. Worth calling before anything destructive.
๐ฏ Scoped Session Mode (Safety Filter)
Restrict every operation to specific record IDs:
Activate:
activate_scope(module="Deals", record_ids=["4153...001", "4153...002"])REST:
POST /scope/activatewith{"module": "Leads", "record_ids": ["123", "456"]}Deactivate:
deactivate_scope()orPOST /scope/deactivate
While active, reads on that module are filtered to those IDs, and writes to any other ID are refused with OUT_OF_SCOPE.
โ Human-In-The-Loop (HITL) Approvals
By default, destructive actions queue a pending request and return a request_id instead of running:
delete_record, bulk_update_records, bulk_delete_records, mass_update_records, mass_delete_records, change_owner, mass_change_owner, merge_records, delete_workflow, delete_workflows, execute_blueprint, update_layout, activate_layout, delete_layout, delete_field, delete_user, delete_tag, bulk_write_create_job.
Review:
list_pending_approvals()orGET /approvalsApprove & execute:
approve_action(request_id="...")orPOST /approvals/{id}/approveReject & discard:
reject_action(request_id="...")orPOST /approvals/{id}/rejectDisable the gate entirely: set
ZOHO_REQUIRE_APPROVAL=falseso these tools execute immediately.
Every request, approval, and rejection is written to the activity log.
๐ Activity Logging
Auth events, outbound Zoho API calls, function executions, and approval decisions are recorded as {timestamp, action, status, details} entries โ held in memory and appended to ~/.zoho_crm_mcp_activity.log.jsonl.
Retrieve:
get_logs(limit=50, action=None, status=None)orGET /logs
๐ Token Security
Tokens are encrypted at rest (Fernet/AES) in
~/.zoho_crm_tokens.json.The key is auto-generated into
~/.zoho_crm_mcp.keyon first run (user-only permissions on POSIX), or set explicitly viaZOHO_TOKEN_ENCRYPTION_KEYfor a stable key across container restarts.Tokens are tagged with the
client_idthat issued them and discarded on mismatch, which prevents Zoho'sinvalid_clienterror after switching accounts.Outbound calls are self-throttled (
ZOHO_RATE_LIMIT_PER_SEC, default 10/sec) on top of 429/5xx backoff.
๐งช Testing
pytest -vCovers the HTTP surface (/health, /, /auth/*, /scope/*, /approvals/*, /logs, /api/*), registration of all 211 MCP tools plus a regression guard that the original 167 are still there, the exact request payloads sent for workflows/modules/notes/calls/webhooks/merges/locks and the Functions API's multipart body, the COQL compiler (including its limit clamp and the mandatory WHERE clause), aggregate-alias relabelling, hierarchy tree assembly (orphans and parent cycles included), per-panel dashboard error isolation, teamspace membership rules, function-to-workflow attach/detach across instant and scheduled actions, and multi-account isolation - including a concurrency test that drives overlapping interleaved calls from many accounts and asserts every request carried its own credentials (the old shared-singleton design failed that on 96 of 100 calls).
Tests run entirely offline โ no Zoho credentials required.
๐ ๏ธ MCP Tool Reference
Category | Tools |
OAuth & Auth |
|
Scoped Mode |
|
Tenancy |
|
HITL & Logging |
|
Escape Hatch |
|
Record CRUD |
|
Bulk (โค100/call) |
|
Mass (async jobs) |
|
Locking & Sharing |
|
Related Records |
|
Query |
|
Metadata & Discovery |
|
Schema Design |
|
Workflow Rules |
|
Workflow Actions |
|
Webhooks |
|
Files |
|
Notes, Calls & Email |
|
Tags |
|
Lead Conversion |
|
Blueprint |
|
Bulk Read/Write |
|
Security & Users |
|
Notifications |
|
Functions (v8 API) |
|
Functions โ Workflows |
|
Workflow Insight |
|
Reports โก |
|
Dashboard โก |
|
Hierarchy โก |
|
Teamspaces โก |
|
User Groups |
|
โ Approval-gated by default. Set ZOHO_REQUIRE_APPROVAL=false to execute immediately.
* Zoho CRM's public REST API has no endpoint for this operation โ blueprint authoring is UI-only. These tools return a clear NOT_SUPPORTED_BY_ZOHO_API message naming a working alternative, rather than failing against a URL that doesn't exist. (Driving records through an existing blueprint does work: get_blueprints / execute_blueprint.)
โก Zoho exposes no Reports, Dashboards, Teamspaces, or hierarchy-tree endpoint, so these features are implemented on this server against real CRM data:
Reports are definitions stored here that compile to COQL (or to
/actions/count) and execute live.get_reports(module=...)also returns that module's Custom Views, which are the closest thing Zoho itself exposes.The dashboard is computed from live figures โ module counts, workflow and function inventory, hierarchy, teamspaces, pinned reports.
Hierarchy tools assemble a tree from
/settings/rolesand/users(Zoho returns flat lists withreporting_topointers); the mutations are real Zoho writes.hierarchy_preferencesis read-only in Zoho's API.Teamspaces are stored here and can be projected onto a real CRM user group (
/settings/user_groups) so the roster is usable inside Zoho.
Definitions persist as JSON beside the token store (~/.zoho_crm_mcp_reports.json, ~/.zoho_crm_mcp_teamspaces.json). On an ephemeral host, mount a disk or accept that they reset on redeploy โ the CRM data they read is never affected.
๐งญ Reaching Anything Not Listed
Zoho's API is larger than any hand-written wrapper. zoho_api_request covers the rest with the same auth, throttling, and retry handling:
zoho_api_request(
method="GET",
endpoint="settings/territories")
zoho_api_request(
method="POST",
endpoint="settings/automation/scoring_rules",
body={"scoring_rules": [{...}]})
zoho_api_request(
method="GET",
endpoint="read/1234567890",
api_root="bulk")api_root selects the URL base: crm โ {domain}/crm/v8 (default), bulk โ {domain}/crm/bulk/v8, root โ {domain}.
This server cannot be deployed
Maintenance
Related MCP Connectors
Search recruiting CRM records, manage candidates, jobs, pipelines, notes and tasks with OAuth.
CRM1The HubSpot MCP Server acts as a bridge that enables AI assistants and Large Language Models to securely interact with HubSpot CRM data through natural conversation, without requiring users to understand complex API structures. It provides read-only access to standard CRM objects (contacts, companies, deals, tickets, products, invoices, and more) and their associations, secured via OAuth 2.0, allowing AI agents to perform tasks like summarizing deals, fetching company updates, and looking up record changes.
- platform7nOAuthtech.p7n
Connect Claude to your Platform7n workspaces โ chat, links, and tasks. One-click OAuth.
xmagnet โ AI-powered B2B CRM for Claude. 35 tools that turn natural-language prompts into real CRM actions: prospect, enrich, score leads, manage deals, scan buying intent, run email campaigns and sequences, build forms and landing pages, refine ICP, and analyze performance โ all directly inside Claude. ๐ ONE-CLICK INSTALL: https://api.xmagnet.ai/claude The install page guides Claude users through 3 steps in under a minute: open Claude Connectors, paste the connector name, paste the server URL, sign in. A reviewer workspace is auto-provisioned on first sign-in with sample contacts, deals, campaigns, and ICP suggestions, so every tool works end-to-end with zero setup. No 2FA. No paid plan required. Free tier exposes all 35 tools. What you can do: โข Prospecting โ search_contacts, search_companies, search_investors, find_contacts_at_companies, enrich_contact, validate_email, find_competitors, company_intelligence โข Pipeline โ get_deals_pipeline, scan_deal_intent, get_ghost_pipeline, create_deal โข Campaigns & sequences โ create_campaign, generate_campaign_content, get_campaign_stats, get_bounce_stats, get_unsub_stats, create_sequence_draft, list_sequences โข Top of funnel โ suggest_icp, get_icp, create_form, list_forms, create_landing_page, list_landing_pages, show_suggestions โข Operations โ analyze_contacts, get_contact_details, update_contact, save_contacts_to_crm, export_contacts, get_dashboard_stats, get_credit_balance Example prompts to try: โข "Find C-suite contacts at fintech companies that raised Series A in the last 6 months." โข "Scan my open deals for buying intent and prioritize follow-ups." โข "Generate a re-engagement campaign for contacts who opened my last newsletter but didn't reply." โข "Show me my deals pipeline by stage with weighted value and win rate." โข "Generate a landing page for my Q2 webinar with a registration form." Built for founders, SDRs, RevOps, and growth teams who want their CRM to take action โ not just store records. Install: https://api.xmagnet.ai/claude ยท Site: https://xmagnet.ai ยท Privacy: https://xmagnet.ai/privacy-policy ยท Terms: https://xmagnet.ai/terms-of-service ยท Support: ashish.sinha@xmagnet.ai
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceConnects Claude to Zoho CRM with read-only access, enabling natural language queries to search records, list modules, retrieve field information, and count records using OAuth authentication.-
- FlicenseNot gradedqualityDmaintenanceEnables read-only interaction with Zoho CRM data through natural language queries, allowing users to search records, list modules, retrieve field information, and count records using secure OAuth authentication.2-
- FlicenseBqualityDmaintenanceExposes Zoho CRM v6 REST API as structured tools for LLM agents via MCP, enabling CRUD operations, search, COQL queries, and more.113-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Zoho CRM data through secure OAuth authentication, supporting comprehensive CRM operations including record management, search, bulk operations, and lead conversion.3MIT