Why these exist
Several connectors can appear in one client at once — a live business tenant, a test tenant, the platform connector — and they are indistinguishable by tool name. create_invoice looks identical on all of them. A write lands in whichever tenant the connection is bound to.
These two parameters turn "I assumed the right connector" into an assertion the server checks.
expected_tenant — assert the tenant you meant
Available on every tool. Pass the tenant's name exactly as it appears in meta.tenant.name, or its UUID.
propose_send_invoice({
invoice_id: "…",
expected_tenant: "Example Facilities Pty Ltd"
})
If the connector resolves to a different tenant, the call fails and does nothing:
code: expected_tenant_mismatch
When it is mandatory
A tenant can require it on every write by enabling mcp.writes_require_expected_tenant. On such a tenant, omitting it fails before anything happens:
code: expected_tenant_required
detail: This tenant requires expected_tenant on all write calls
(mcp.writes_require_expected_tenant is enabled). Pass
expected_tenant with the tenant name or UUID to confirm
intent, or disable the setting.
This is a first-call surprise for any integration. If you are writing a client or an agent loop, pass expected_tenant on every write from the start — it costs nothing on tenants that do not require it, and it is the difference between a caught mistake and a silent one.
Reads are unaffected.
target_tenant_id — platform PATs calling tenant tools
The platform connector can act across tenants. When it calls a tenant-scoped tool, it must name the tenant explicitly:
error: Platform PAT must include target_tenant_id when calling a
tenant tool. Use list_all_tenants to discover tenant ids.
Discover the ids with list_all_tenants. Tenant-PAT callers omit the parameter entirely — their tenant is inferred from the session, and passing it is neither needed nor accepted.
The route validates and strips target_tenant_id before the handler runs, so handler behaviour is identical either way.
The orientation habit that avoids both
Call get_session_context when you first connect. It returns the active tenant's name, id and mode (LIVE, TEST, or PLATFORM). Every tool response also carries meta.tenant with the same three fields.
Check meta.tenant.mode before any write. LIVE means real client data.
Error reference
| Code | Cause | Fix |
|---|---|---|
expected_tenant_required | Tenant requires the assertion; call omitted it | Add expected_tenant |
expected_tenant_mismatch | The assertion did not match the resolved tenant | You are on the wrong connector |
(message, no code) Platform PAT must include target_tenant_id | Platform connector calling a tenant tool | Add target_tenant_id, or use the tenant connector |