How Rutter Connect works

How it works

This page walks the architecture top to bottom. Read it once before wiring Rutter Connect into a real product so the security review goes faster.

Rutter Connect MCP request flow: AI agent talks to Rutter Connect over JSON-RPC; Rutter Connect routes calls to the Rutter unified API which fans out to accounting and commerce platforms.

What MCP is

Model Context Protocol is an open spec from Anthropic that lets an LLM call tools on a remote server using a standard JSON-RPC interface. Instead of bolting custom function-calling into every app, the model speaks one protocol and the server advertises its tools, schemas, and results.

A naive MCP server typically has to solve six things:

  • Auth — proving the user is who they say they are, and binding the session to the right tenant.
  • Tool discovery & schemas — advertising what tools exist and their argument shapes.
  • Normalization — when one MCP fronts many backends (e.g. QuickBooks vs. Xero), the model shouldn't see platform quirks.
  • Rate limits & abuse — the model can call tools in a loop; the server has to throttle.
  • Audit & compliance — someone needs to know what the model did on a user's behalf.
  • Write safety — read calls are forgiving; mutations (post a bill, refund an order) are not.

Rutter Connect solves all six.

What Rutter Connect adds

Pre-bound connections — no re-auth in chat

Merchants link their platforms once via Rutter Link in your dashboard. When a chat starts, Rutter Connect silently binds those existing connections into the MCP session, so the agent never has to interrupt the conversation with a Link flow.

Rutter dashboard showing the Rutter Connect tab with the MCP endpoint, bearer token, and the connections that will auto-bind into a session.

Unified schema

A Bill looks the same whether the source is QuickBooks or Xero. A Product looks the same on Shopify or Amazon. Your prompts stay simple. The canonical per-platform support matrix lives at the Coverage Explorer.

Verb-prefixed tool catalog

About 93 tools, grouped by domain:

  • Read — list_*, get_*, search_* across customers, vendors, accounts, items, invoices, bills, journal entries, products, orders, payouts.
  • Write — create_*, update_*, delete_*, plus apply_invoice_credit, archive_employee.
  • Analytics — get_cash_position, get_13_week_forecast, get_ar_aging_summary, get_late_payment_prediction, get_ap_optimization, get_financial_action, and a dozen more.
  • Reports — get_income_statement, get_revenue (GL-backed, not invoice sums).
  • Image extraction — process_financial_image, process_and_create_from_image (drop a receipt or invoice PDF, post it as a bill).

Server roles

  • rutter-poweruser — the end-user data surface. Accounting + commerce tools, plumbing, analytics. This is what your agents talk to.
  • rutter-sysadmin — the operator surface. Read-only list_connections and get_connection_health for ops dashboards.

Transports

  • stdio — for Claude Desktop and any MCP client that spawns a local process.
  • Streamable HTTP — for hosted agents and remote clients. Each initialize mints a fresh session pinned to a generated session id; tool handlers run under AsyncLocalStorage so concurrent sessions don't bleed state.

Connection model: dual slots

A single SessionStore holds two independent active connections:

1
interface SessionStore {
2
activeAccounting: RutterConnection | null;
3
activeCommerce: RutterConnection | null;
4
connectionMap: Map<string, RutterConnection>; // history of every connection bound this session
5
}
  • Accounting tools resolve tokens from activeAccounting.
  • Commerce tools resolve tokens from activeCommerce.
  • Re-authing replaces only the slot for that domain — the other slot stays intact.

The login flow:

1
login_to_rutter(domain="accounting") → pick QBO/Xero/NetSuite in Link → fills accounting slot
2
login_to_rutter(domain="commerce") → pick Shopify/Amazon in Link → fills commerce slot
3
get_active_connection → inspect both slots
login_to_rutter tool call alongside the Rutter Link platform picker showing QuickBooks Online selected.

The login_to_rutter response includes:

FieldMeaning
domainDomain of the platform actually picked.
requested_domainWhat the caller asked for (null if unspecified).
domain_mismatchSet if the user picked a platform in the other domain. The slot is still filled; the agent should surface the mismatch and offer a retry.
replaced_previousTrue if a prior connection in that slot was replaced.
slots{ accounting, commerce } snapshot after the bind.
next_stepContext-aware hint (e.g. suggest connecting the other domain).

Auth model

Every Rutter call uses HTTP Basic auth (RUTTER_CLIENT_ID:RUTTER_CLIENT_SECRET) plus a per-connection access_token. There is no fallback to a default access token — that prevents cross-tenant leaks. Every response includes a connection { company_name, connection_id, platform } envelope so the agent can attribute results.

Write safety: where the gate sits

Rutter Connect treats reads as forgiving and mutations as not. The gate fires before the call leaves the server:

  1. MCP annotations — every write tool is tagged readOnlyHint: false, with destructiveHint: true for delete/void. Hosts that honor annotations bucket tools automatically.
  2. Description prefixes — [Accounting · Write], [Commerce · Delete], etc. for clients that don't.
  3. Confirmation step — the agent summarizes the action ("Post a $2,140 bill to QuickBooks?") and waits for the user to click Approve before the write fires.
  4. Envelope wrapping — POST/PATCH bodies are wrapped as { "<resource>": { ... } }. Flat bodies fail closed with 400.
  5. Structured failure — operations Rutter or the platform can't do return { "success": false, "error": "operation_not_supported" | "platform_unsupported", "suggestion": "…" } instead of a raw stack trace.
  6. Balanced-entry validation — create_journal_entry and update_journal_entry enforce sum(debits) === sum(credits) client-side before the call leaves the server.
  7. Source URL deep links — for QBO and Xero, write responses include a source_url so the user can verify the posted record in the platform UI.
Sample chat showing a tool call result followed by a write-confirmation gate that the user must approve before the bill is posted.

Audit & observability

Every tool call is captured: arguments, result, latency, the merchant it ran for, errors. Read args are stored hashed; write args are stored encrypted with the merchant id as AAD so they're recoverable for incident review. Webhooks fan events out to your own pipeline.

The sysadmin server exposes two read-only tools — list_connections and get_connection_health — that surface this same data to ops dashboards.

What's next

  • Quickstart — wire it up against a sandbox merchant.
  • Use cases — pick the integration shape that matches your product.