TOMO
BETA Partner connections are in beta and these docs are under review. Anything marked planned is not built yet — we confirm with you what is live before your service goes live.

TOMO MCP Server Specification

Audience: engineering teams running an MCP server that TOMO connects to — one you already have, or one you build from scratch. This is the contract for that server.

TOMO's MCP transport: Streamable HTTP (per the official MCP spec). TOMO's MCP SDK reference: @modelcontextprotocol/sdk TOMO's MCP client is the server-side projector that calls your endpoint. Its behavior is fully specified by this document; partners do not need access to TOMO's source.


Direction of the contract (read first)

This spec describes the MCP server YOU run. TOMO is the client that calls into it. There is no public TOMO MCP endpoint you plug Claude or Cursor into — TOMO is the orchestrator that calls your tools, not the other way around.

   TOMO (the MCP client)                                 Your MCP server
   ─────────────────────                                 ───────────────
   initialize, tools/list   ── MCP JSON-RPC over ──▶     your tools
   tools/call               ── Streamable HTTP   ──▶     (TOMO already calls public MCP
                                                          servers people link with their
                                                          own account)
   CPC ledger               ◀── your HMAC-signed completion POST ──

Inside TOMO, some public APIs are wrapped as in-process tools. None of them is exposed for you to connect to.

Plain-English contract:

Question Answer
Does TOMO have an MCP server you connect to? No. Inside TOMO some public APIs are wrapped as in-process tools; none is exposed for you to connect to.
Do you connect to TOMO's MCP server? No. The reverse: TOMO connects to yours.
Is TOMO an MCP server you can plug into Claude / Cursor? No. TOMO is an MCP client to your server, not a server you can plug into.

This document specifies the surface YOUR MCP server must expose so TOMO's client can probe, list, and call your tools.


Already built an MCP server for Claude or Cursor? Most of the work is done.

MCP is a standardized protocol. The host is always the client, the integrator always runs the server — and this is true for every MCP host: Claude Desktop, Cursor, ChatGPT (via connectors), Continue, and now TOMO.

Host (MCP client) Integrator (runs MCP server)
Claude Desktop filesystem MCP, GitHub MCP, Postgres MCP, your MCP
Cursor same pattern
ChatGPT connectors same pattern
Continue (VS Code) same pattern
TOMO your MCP server

The wire protocol you ship for Claude is the wire protocol TOMO calls — same initialize, same tools/list, same tools/call. You don't have to learn a new protocol direction or write a new server; you just have to register the one you already have.

What's identical to Claude / Cursor

  • MCP transport — Streamable HTTP (per the official spec)
  • Handshake — initialize, at the protocol version the official SDK negotiates
  • Discovery — tools/list returns your tool schemas
  • Invocation — tools/call with JSON-Schema-validated inputs and outputs
  • SDK — @modelcontextprotocol/sdk works as-is

What TOMO adds (because we route real business intents, not developer tools)

Layer What it is Why it exists
Manifest A declarative JSON file mapping your MCP tools to TOMO intent IDs, with pricing range + service area + self-declared TTBS signals TOMO routes by intent, not by tool name. The manifest is how your "tools/list" becomes addressable by mobility.book_intracity_ride, food.order_delivery, etc.
CPC webhook An HMAC-signed POST you make to /api/v1/cpc/mcp_provider/<your_account_id> when an order completes, reporting your NET supplier revenue TOMO charges its platform commission on completed orders only, on your NET revenue (rate per your listing agreement — the same for every business). The webhook is how you tell us the order closed, so TOMO can record its fee — billed to you separately; TOMO never holds the money.
Compliance review One-time check of a live privacy policy URL and the licences your intent needs (for businesses in India: GSTIN, plus FSSAI for food, etc.) TOMO offers only legitimate businesses. Our team's approval gates going live.
TTBS scoring Server-side ranking (Time / Taste / Budget / Safety) across every business serving the same intent Source-blind ranking. No paid placement. Today your rank comes from your declared signals, weighted for the domain and the person asking. (planned: learning from delivered results.)

Bottom line: if your team has shipped an MCP server for any other host, the protocol work is done. What's left is the business contract — declare what you serve, sign your completion webhooks, pass review. That's the integration.


What TOMO probes

Send your MCP server URL with your application at automobnxt.com/business. Today our team runs TOMO's probe:

1. initialize           — protocol handshake
2. tools/list           — discovery: what tools you expose

If the probe fails, the error is recorded and your server stays off until it passes. TOMO makes no test tools/call during the probe. Real tools/call traffic starts only after our team has tested your connection with you and switched it on.


1. initialize

Standard MCP handshake. TOMO sends:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "<negotiated by the official MCP SDK>",
    "capabilities": { "tools": {} },
    "clientInfo": {
      "name": "tomo-mcp-connector",
      "version": "0.1.0"
    }
  }
}

You return:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "<the version you support>",
    "capabilities": {
      "tools": { "listChanged": true }
    },
    "serverInfo": {
      "name": "your-company-mcp",
      "version": "1.0.0"
    }
  }
}

Requirements:

  • protocolVersion — let the official SDK negotiate it
  • capabilities.tools MUST be present (you serve tools)
  • serverInfo.name should clearly identify your company (used in logs + audit)

2. tools/list

The discovery call. TOMO calls this when our team probes your server and keeps the result; it re-checks when we probe again. (planned: an automatic daily re-check.)

Return:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "search_availability",
        "description": "Search hotels matching travel.book_hotel input",
        "inputSchema": {
          "type": "object",
          "required": ["destination", "dates", "party"],
          "properties": {
            "destination": { "type": "object", "properties": {...} },
            "dates":       { "type": "object", "properties": {...} },
            "party":       { "type": "object", "properties": {...} },
            "preferences": { "type": "object", "properties": {...} }
          }
        },
        "_meta": {
          "tomo": {
            "intent":          "travel.book_hotel",
            "domain":          "travel",
            "pricing":         { "min": 500, "max": 50000, "currency": "INR" },
            "service_area":    ["Bangalore", "Hyderabad", "Mumbai"],
            "ttbs_signals":    { "time": 0.6, "taste": 0.8, "budget": 0.5, "safety": 0.7 },
            "availability":    "24x7",
            "widget_type":     "travel_listing_results",
            "completion_callback": "https://www.automobnxt.com/api/v1/cpc/mcp_provider/<your_account_id>"
          }
        }
      }
    ]
  }
}

Required tool fields

Field Required Notes
name yes snake_case verb_noun, e.g. search_availability, book_ride, place_order
description yes One sentence, ≤ 140 chars. Read by our team during review.
inputSchema yes JSON Schema draft 7+. Every required field MUST be in required[].
_meta.tomo yes TOMO-specific extension — intent, domain, price range, signals, widget

_meta.tomo fields TOMO reads

These are exactly the fields TOMO reads today. A tool missing intent or domain is skipped, and tools with no _meta.tomo block are ignored, not errored.

Field Required Type Notes
intent yes string Full ID matching _INTENT_CATALOG.md exactly
domain yes string The intent's namespace, e.g. travel for travel.book_hotel
pricing read {min, max, currency} Your price range; each defaults to 0 / INR
service_area read array Cities or postal codes you serve
ttbs_signals read object Self-rated 0.0-1.0 per axis (time, taste, budget, safety); each defaults to 0.5
availability read string e.g. 24x7; empty = always available
widget_type read string Widget the result renders in (must match the intent's §9)
completion_callback read URL TOMO's CPC webhook URL (always /api/v1/cpc/mcp_provider/<your_account_id>)

Tools required per intent

Each intent spec's §3 lists exactly which tools you must implement. You CANNOT list an intent on TOMO with a partial toolset. Common patterns:

Listing-shape intents (travel, food.delivery, marketplace, etc.):

search_availability   → returns Listing[]
get_listing           → returns ListingDetail
create_booking        → returns BookingRef
cancel_booking        → returns RefundInfo
modify_booking        → returns RevisedBookingInfo

Service-shape intents (lifestyle, auto-services, finance-consultation):

search_providers      → returns Provider[] with available slots
get_provider_detail   → returns ProviderDetail
get_available_slots   → returns Slot[]
book_slot             → returns BookingRef
cancel_booking        → returns RefundInfo
modify_booking        → returns RevisedBookingInfo

Mobility-shape intents:

get_ride_estimates    → returns RideOption[]
book_ride             → returns RideRef
track_ride            → returns RideTrack (live)
cancel_ride           → returns CancellationInfo
update_ride_drop      → returns RevisedFare
rate_ride             → returns Acknowledged
share_trip_status     → returns ShareableURL

Order-shape intents (food.delivery, grocery.delivery, etc.):

search_restaurants_and_dishes  → returns Result[]
get_restaurant_menu            → returns RestaurantMenu
get_dish_detail                → returns DishDetail
compute_cart_total             → returns CartQuote
place_order                    → returns OrderRef
cancel_order                   → returns RefundInfo
track_order                    → returns OrderTrack

Every intent spec specifies the exact tool list. Don't deviate.


3. tools/call — invocation

When a user's intent matches one of your tools, TOMO calls:

{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tools/call",
  "params": {
    "name": "search_availability",
    "arguments": {
      "destination": {...},
      "dates": {...},
      "party": {...},
      "preferences": {...}
    }
  }
}

You return:

{
  "jsonrpc": "2.0",
  "id": 42,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"listings\": [...], \"result_token\": \"...\", \"expires_at\": \"...\"}"
      }
    ]
  }
}

TOMO calls your tool with the arguments your inputSchema declares — nothing is added. It waits up to 30 seconds for a tool call (20 seconds for the probe).

Important:

  • Return JSON-stringified payload as text content. TOMO parses it back.
  • The full response shape is per the intent's §4. Every required field MUST be present.
  • expires_at is YOUR commitment for how long result_token-bound items remain bookable.

Authentication on tools/call

TOMO authenticates with Authorization: Bearer <token>. That is the person's own OAuth 2.1 token, when they linked their account with you using PKCE (dynamic client registration is supported). Tools that need no sign-in are called with no token. mTLS and custom auth headers are not supported.

Reject unauthenticated requests with HTTP 401 + INVALID_AUTH per error code list.


4. Error responses

Use MCP-standard JSON-RPC errors:

{
  "jsonrpc": "2.0",
  "id": 42,
  "error": {
    "code": -32602,
    "message": "Invalid params: destination.country_code must be IN",
    "data": {
      "tomo_error_code": "INVALID_REQUEST",
      "tomo_field": "destination.country_code"
    }
  }
}

The error.data.tomo_error_code MUST be one of the codes in your intent's §10. Free-text errors are forbidden.

Standard JSON-RPC code → TOMO code mapping

JSON-RPC HTTP equivalent TOMO code
-32600 400 INVALID_REQUEST
-32601 404 METHOD_NOT_FOUND
-32602 400 INVALID_REQUEST (params)
-32603 500 INTERNAL_ERROR
-32000 401 INVALID_AUTH
-32001 429 RATE_LIMITED
-32002 503 PARTNER_MAINTENANCE

Plus intent-specific codes from each spec's §10.


5. Streamable HTTP transport

TOMO uses MCP's Streamable HTTP transport:

POST https://your-company.com/mcp
Content-Type: application/json
Accept: application/json, text/event-stream
Authorization: Bearer <partner_token>

<JSON-RPC body>

Your server can return:

  • Content-Type: application/json — single response (most tools)
  • Content-Type: text/event-stream — SSE for long-running tools (track_ride, track_order)

For SSE, send data: <JSON-RPC fragment>\n\n chunks until the response is complete.

Use HTTPS.


6. Concurrency + idempotency

create_* tools (booking, ordering)

If you support an idempotency_key, declare it in your inputSchema — a person may tap twice; return the same booking_ref for the same key, and IDEMPOTENCY_CONFLICT for the same key with a different body. TOMO does not retry your tools, with one exception: for write tools named checkout, book_table or place_food_order, after a failed call TOMO re-reads your orders and retries only if no order landed.

search_* tools

Stateless. Cache up to 60 seconds (or per the intent's §9).

track_* tools

Stateless reads. Heavy rate-limited (≤ 1 every 5-10 seconds per ride/order). Use SSE to push updates if you support it.


7. SLAs

Per intent spec §3. General targets:

Tool kind p50 p95 p99
search_* 600ms 1500ms 3000ms
get_* 300ms 800ms 1500ms
create_* (with payment) 2000ms 5000ms 10000ms
track_* 100ms 400ms 800ms
cancel_* 1000ms 3000ms 5000ms

(planned: automatic latency monitoring — not built yet.) Today, performance problems are handled by our team.


8. Rate limits

(planned: outbound rate limits and back-off.) Today TOMO calls your tools only when a person asks, and does not retry them automatically (except the checked retry for order-placing write tools in §6). If you need a limit, return RATE_LIMITED and tell our team.


9. Local development

Test your MCP locally before registering:

Node.js

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import express from 'express';

const server = new Server(
  { name: 'your-company-mcp', version: '1.0.0' },
  { capabilities: { tools: {} } }
);

server.setRequestHandler('tools/list', async () => ({
  tools: [
    {
      name: 'search_availability',
      description: 'Search hotels',
      inputSchema: { type: 'object', /* ... */ },
      _meta: { tomo: { intent: 'travel.book_hotel', /* ... */ } }
    }
  ]
}));

server.setRequestHandler('tools/call', async (req) => {
  const { name, arguments: args } = req.params;
  if (name === 'search_availability') {
    const result = await yourSearchLogic(args);
    return { content: [{ type: 'text', text: JSON.stringify(result) }] };
  }
});

const app = express();
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
await server.connect(transport);
app.post('/mcp', (req, res) => transport.handleRequest(req, res, req.body));
app.listen(8080);

Python

Use mcp Python SDK with FastAPI.

Go

Implement Streamable HTTP transport directly. JSON-RPC handlers map to tools/list + tools/call.

There are no TOMO starter repos yet — the official MCP SDKs above are all you need.


10. Probe simulation

Before registering, simulate TOMO's probe yourself:

# 1. initialize
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"clientInfo":{"name":"tomo-test","version":"1.0.0"}}}'

# 2. tools/list
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# 3. tools/call (synthetic)
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"search_availability","arguments":{...}}}'

TOMO's probe runs only steps 1 and 2. Step 3 is for your own testing — if all three succeed and return spec-compliant payloads, you're ready to apply.


11. Common mistakes

"Method not found" on tools/list

Your server isn't registering the standard tools/list handler. The MCP SDK does this automatically; if you implement raw JSON-RPC, ensure both tools/list and tools/call handlers are wired.

Our review sends your schema back

You're returning fields TOMO didn't expect (extra), missing fields TOMO required, or using free text where the intent spec demands a controlled vocabulary. Read your intent's §5 carefully — every field is REQUIRED, no optionals.

"Forbidden field detected"

You're emitting one of paid_placement_score, ad_bid, sponsored_rank, etc. Remove them. Our team checks for these fields by hand during review. (planned: an automatic scanner.)

Latency p95 too high

Check downstream calls. TOMO waits up to 30 seconds for a tool call. Use appropriate min-instances if cold starts are an issue.

CORS errors

TOMO's orchestrator calls server-to-server, not browser-to-server. CORS shouldn't matter. If you see CORS errors, you're testing wrong (likely from a browser).


12. Checklist before registering

[ ] HTTPS endpoint
[ ] initialize returns valid handshake
[ ] tools/list returns at least one tool with full _meta.tomo
[ ] Every tool's name maps to a TOMO intent in _INTENT_CATALOG.md
[ ] Every tool's inputSchema matches intent §3 input shape
[ ] Every tool's response (when called) populates ALL fields per intent §4
[ ] No forbidden fields anywhere
[ ] Bearer token auth implemented
[ ] Idempotency on create_* tools
[ ] SLA p95 within spec for each tool
[ ] CPC webhook signing implemented per WEBHOOK_SIGNING.md

Once you tick every item, send your endpoint with your application at automobnxt.com/business.


13. References


Built by AUTOMOBNXT · DPIIT Recognised Startup · 2026.