Docs
What an agent gets when it connects, the limits it runs under, and copy-paste setup for every Claude surface.
Capabilities
What it can and cannot do
10 read-only tools over one Zoho Inventory organization. The limits are enforced by the server, not by the prompt.
Can
- Look up items by id or exact SKU, with price and stock per warehouse location.
- Check stock for several known items in one call: up to 25 item ids or 5 SKUs, such as every line of a cart.
- Fetch a sales order with its line items, packages, tracking numbers and invoices in one call.
- Search customers by name, company, email or phone, and list their sales orders and invoices.
- List invoices by status, customer or due date, with balances in minor units.
- Trace a Razorpay reference (
pay_,order_,rfnd_) to the payment, invoice and sales order it settled. - Report its own connection: organization, data center, plan, requested read scopes, budget left and circuit state.
- Page through lists with an opaque cursor:
limitdefaults to 20, max 100. - Attach
as_ofand azoho_urldeep link to every result so a person can verify it.
Cannot
- Create, edit, cancel or delete anything. It requests only READ scopes, its client issues GET only, and no write tool exists.
- Search sales orders freely. Zoho documents no filters on
/salesorders, so the connector uses bounded fallbacks (customer lookups, packages, at most 3 pages × 200) and says when a scan was partial. - Return unbounded data. Lists stop at 100 rows and every result stays under about 10K tokens.
- Show raw customer email or phone numbers; they come back masked.
- Take instructions from merchant data. Notes and descriptions are wrapped as
untrusted_textso an agent treats them as data. - Use more than its share of the merchant’s Zoho quota (see rate limits below).
Never does
- Mirror merchant data into its own database; only a short-TTL cache keyed by tenant.
- Pass Zoho tokens to an agent, or store a refresh token unencrypted.
- Log tokens, auth codes, client secrets or unmasked contact details.
- Let the public demo touch a real Zoho organization.
Reference
Tools
Server name merchantbridge, so agents see mcp__merchantbridge__zoho_*. Every result uses the same envelope: data, page and meta.
Integrate
Use it from Claude
The demo server needs no key. A connected organization uses the bearer key from the connect flow.
Claude Code
Public demo server (synthetic data, no key):
claude mcp add --transport http mb-demo https://merchantbridge-api.vercel.app/mcp/demoYour own Zoho organization, with the key shown once after connecting:
claude mcp add --transport http merchantbridge https://merchantbridge-api.vercel.app/mcp --header "Authorization: Bearer mb_live_YOUR_KEY"Claude Agent SDK
import { query } from '@anthropic-ai/claude-agent-sdk';
for await (const message of query({
prompt: 'Is CHAI-250 in stock in Bengaluru, and at what price?',
options: {
mcpServers: {
merchantbridge: {
type: 'http',
url: 'https://merchantbridge-api.vercel.app/mcp',
headers: { Authorization: `Bearer ${process.env.MERCHANTBRIDGE_KEY}` },
},
},
allowedTools: ['mcp__merchantbridge__*'],
},
})) {
if (message.type === 'result') console.log(message);
}Tools appear as mcp__merchantbridge__zoho_*. For the demo server, use https://merchantbridge-api.vercel.app/mcp/demo and drop the header.
Claude Messages API (MCP connector)
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: mcp-client-2025-11-20" \
-H "content-type: application/json" \
-d '{
"model": "claude-haiku-4-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Is CHAI-250 in stock in Bengaluru, and at what price?"}],
"mcp_servers": [{
"type": "url",
"url": "https://merchantbridge-api.vercel.app/mcp",
"name": "merchantbridge",
"authorization_token": "mb_live_YOUR_KEY"
}],
"tools": [{"type": "mcp_toolset", "mcp_server_name": "merchantbridge"}]
}'Requires the mcp-client-2025-11-20 beta header and both halves: the mcp_servers entry and an mcp_toolset that names it. The server must be reachable from the public internet, so this does not work against localhost. Replace mb_live_YOUR_KEY with your key.
Claude.ai custom connector
- Open Customize → Connectors → Add custom connector.
- Name it MerchantBridge demo and paste the URL below.
- Leave the OAuth fields empty: the demo server needs no sign-in.
- Enable it in a chat and ask about CHAI-250.
https://merchantbridge-api.vercel.app/mcp/demoDisconnect
Revokes the Zoho refresh token at Zoho, marks the connection revoked and disables the key that made the call. Local revocation happens even if Zoho is unreachable.
curl -X POST https://merchantbridge-api.vercel.app/api/connection/disconnect \
-H "Authorization: Bearer mb_live_YOUR_KEY"Rate governor
Sharing the merchant’s Zoho quota
Zoho limits each organization, not each app, so every agent and integration shares one budget. The governor keeps this connector well inside it. Block duration and daily reset time are undocumented by Zoho; the values below are the connector’s defaults.
- Per minute
- 80 requests per organization, below Zoho’s 100/min hard limit.
- Concurrency
- Leases of 4 in-flight calls on the free plan, 8 on paid plans (Zoho allows 5 / 10).
- Daily share
- At most 50% of the plan’s daily quota, leaving the rest for the merchant’s other integrations.
- Code 44
- Zoho blocked the org for the minute: a 60 s circuit opens and calls fail fast with RATE_LIMITED and retry_after_s.
- Code 45
- Daily quota exhausted: DAILY_QUOTA_EXHAUSTED, never retried until the UTC-midnight reset.
- Code 1070
- Concurrency exceeded: requeued with jittered backoff.
- 5xx / timeout
- Up to two retries, 10 s per attempt; a call queues at most 10 s before RATE_LIMITED.
Security
Security notes
- Two separate credentials: the merchant authorizes Zoho once with OAuth; agents use a per-tenant
mb_live_key that is shown once and stored only as a SHA-256 hash. - Zoho refresh tokens are encrypted with AES-256-GCM; access tokens refresh single-flight, so twenty parallel calls cause one token request.
- Every tool call writes exactly one usage event (tool, status, error code, latency, masked arguments), success or failure.
- Tenant id is part of every database row, cache key and governor key.
- Errors are tool results with
isError: trueand a code, message, retryable flag and hint, so an agent can recover instead of crashing.