The Adaptix MCP Tool Broker is the public agent surface for every AdaptixCore tenant. Point Claude, ChatGPT, or a custom MCP client at it and your agent gets a curated, authorization-gated set of domain intents — not raw database access, not a scraped UI, and not a screenshot bot fumbling through the console.
Every tools/list and tools/callis resolved server-side against Core’s authoritative policy resolver. A model can never supply tenant_id, role, is_founder, or permissions — the broker rejects those keys outright. Identity travels inside the verified gateway context, so the prompt cannot forge who is calling.
The broker’s job is to be a good boundary. It exposes the domain intents an operator would want an agent to have — and nothing else. These three columns are the shape of that contract, taken directly from the service’s registry rules.
20 read tools
Claims, eligibility, ERA reconciliation, billing summaries, ePCR chart state and completion gaps, credentials, scheduling, documents, operational analytics, and audit. Each read is scoped by the caller's verified permissions and tenant. A denied tool is entirely absent from tools/list — an unauthorized caller never receives the platform catalog.
5 write tools, approval-only
Claim corrections, outbound messages, and patient statements. Every write is registered as SIDE_EFFECT or HIGH_RISK_SIDE_EFFECT, which forces approval and idempotency. On day one, execution is disabled at the broker: a write resolves to a pending approval and does not run. A human confirms in-app; the prepared payload then executes exactly once, keyed by the approval id.
SECRET, tokens, PHI without policy
SECRET-classified data cannot cross MCP; the registry refuses to load a contract that tries. A possible_phi tool called with PHI policy off is denied by Core with PHI_NOT_PERMITTED (an optional minimize path redacts instead of denying). S2S tokens, provider credentials, and internal secrets are never in prompt scope — they live in the broker's tenant-bound service token.
Every entry below is a fully-declared MCPToolContract in adaptix_contracts.ai.mcp_tools. The registry validates each at load: an incomplete contract, a forbidden-named tool (database.execute, shell.run...), a SECRET-classified tool, or one that points at an unknown service audience is refused — the broker will not start with an unvalidated catalog.
adaptix-billingclaims.searchlivePHISearch active claims with live risk scoring (tier histogram + items), tenant-scoped.
claims.getlivePHIFetch a single claim's live risk profile by claim id.
claims.get_statusliveReturn the current payer claim-status observation for a claim.
claims.get_submission_historytyped-unavailablePHIReturn the submission history for a claim (837 lifecycle).
claims.get_denial_historytyped-unavailablePHIReturn the denial history and CARC/RARC codes for a claim.
adaptix-billingeligibility.get_resulttyped-unavailablePHIReturn the latest 270/271 eligibility result for a patient.
era.get_reconciliation_statustyped-unavailableReturn ERA/835 remittance reconciliation status for a batch or deposit.
adaptix-billingbilling.get_summarytyped-unavailableReturn the tenant billing summary (AR, aging, KPIs).
billing.get_exception_summarytyped-unavailableReturn the tenant billing exception summary (queues, blockers, aging).
adaptix-epcrepcr.get_chart_statuslivePHIReturn the current state of a specific chart (draft, locked, exported, corrected).
epcr.get_completion_gapstyped-unavailablePHIReturn the field-level completion gaps blocking chart lock for a chart.
epcr.get_quality_findingstyped-unavailablePHIReturn the NEMSIS quality-validation findings attached to a chart.
adaptix-workforcecredentials.get_statustyped-unavailableReturn the current credential status for a user (licences, certs, expirations).
credentials.get_expiringtyped-unavailableReturn credentials expiring inside a window (default 90 days) for the tenant.
adaptix-workforcescheduling.get_user_scheduletyped-unavailableReturn the caller's upcoming schedule (windowed, tenant-scoped).
scheduling.get_open_shiftstyped-unavailableReturn open shifts the caller is credentialed and eligible to claim.
adaptix-billingdocuments.get_statustyped-unavailableReturn the delivery status of a generated document (statement, letter, notice).
documents.search_authorizedtyped-unavailableSearch documents the caller is authorized to see, tenant-scoped.
adaptix-coreanalytics.get_operational_summarytyped-unavailableReturn the operational summary (activity KPIs) for the tenant.
audit.search_authorized_activitytyped-unavailableSearch audit activity the caller is authorized to review, tenant-scoped.
SIDE_EFFECTEvery write returns a pending-approval id and does not execute. A human approves in-app; the prepared payload then runs exactly once, keyed by the approval id. Execution is additionally gated by MCP_WRITE_EXECUTION_ENABLED, which is false on day one.
claims.prepare_correctionClaimsPHIDraft a claim correction. Returns the prepared correction and a pending-approval id; does not submit.
claims.submit_correctionClaimsPHISubmit a previously-prepared claim correction after human approval. Idempotent by approval id.
communications.prepare_messageCommunicationsPHIDraft an outbound message. Returns the prepared payload and a pending-approval id; does not send.
communications.send_approved_messageCommunicationsPHISend a previously-prepared, human-approved message. Idempotent by approval id.
documents.prepare_statementDocumentsPrepare a patient statement or billing document. Returns the draft and a pending-approval id; does not deliver.
Every tool discovery and every tool call is resolved against Core’s policy resolver on the server side. The broker’s decision is authoritative — and every failure mode fails closed, so a broken policy path becomes a DENY, never an ALLOW.
POST {CORE_SERVICE_URL}/api/v1/ai/policy/resolve/tool
X-Adaptix-Internal-Secret: <s2s>
-> {
allowed,
decision: ALLOW | DENY | APPROVAL_REQUIRED,
reason_code,
policy_version,
approval_required
}Identity (tenant, user, scopes) comes from the verified gateway context. The resolver trusts user_has_permission computed from the caller’s verified scopes; it never reads role or tenant from tool arguments.
POLICY_UNAVAILABLE)tools/list returns only the tools the caller is authorized to discover. A denied tool is absent from the catalog itself, so an unauthorized caller never learns the tool exists.
A tool call carrying any of these keys is rejected outright with MCP_FORBIDDEN_ARGUMENT before it reaches the resolver.
tenant_idroleis_founderpermissionsapprovalThis is not a filter. It is the shape of the boundary: identity is a property of the caller, not a property of the request.
The broker terminates the MCP protocol at the AWS AgentCore Gateway for your tenant. Your agency’s workspace admin generates the connection credential from Workspace → Integrations → MCP and pastes it into whichever client you use.
Claude Desktop and Claude Code
In Claude Desktop, open Settings → Developer → Model Context Protocoland add a remote server. In Claude Code, run claude mcp add. Point either at your tenant’s broker URL.
{
"mcpServers": {
"adaptixcore": {
"url": "https://mcp.<your-tenant>.adaptixcore.com/mcp",
"auth": { "type": "oauth" }
}
}
}OAuth completes in the browser against your workspace SSO. Claude sees only the tools your seat is authorized to discover.
ChatGPT (Custom Connectors)
In ChatGPT’s Custom Connectors panel, add a new MCP server. Paste the broker URL and complete the OAuth prompt with your workspace SSO. ChatGPT will list only the tools your seat is authorized to see.
Name: AdaptixCore URL: https://mcp.<your-tenant>.adaptixcore.com/mcp Auth: OAuth 2.1 (PKCE) via your workspace SSO Approval: Ask before write tools
Even with “always allow”, writes still return a pending approval — the broker owns that decision, not the client.
Bring your own agent
The broker speaks MCP revision 2025-06-18over Streamable HTTP with SSE. It supports the standard initialize, tools/list, tools/call, and pingmethods. Custom SDKs, LangGraph agents, Autogen, or your own runtime all connect the same way.
GET /mcp -> server info + capabilities
POST /mcp { "method": "tools/list", ... }
POST /mcp { "method": "tools/call", "params": {...} }
POST /mcp { "method": "ping" }Every response carries a provenance envelope: results are marked as data, not instructions. A model that treats returned bytes as a command is on its own — authorization does not consult the payload.
SECRET data never crosses MCP (enforced at registry load and re-asserted per call). A possible_phi tool with PHI policy off is denied by Core with PHI_NOT_PERMITTED. An optional minimize path can redact PHI-looking values instead of denying, when policy allows.
Every result is wrapped with provenance metadata marking it as data, not instructions. Authorization is server-side and never a function of returned bytes; the broker processes exactly the one tool named per request, so returned text cannot trigger another tool call.
ai.mcp.tools_list.* and ai.mcp.tool_call.* audit events, and MCPToolCalls / MCPToolDenied / MCPApprovalRequired / MCPPolicyResolutionFailure metrics. None of them carry PHI, prompts, tool arguments, tool results, or tokens.
The broker holds no domain data. On authorization, it mints a short-lived service token whose tenant and user are inside the token, not spoofable request headers. Domain services verify the token before honoring the call.
If a prospect is going to hand their platform an agent, they deserve to see the seam between what is real and what is not. This is that seam.
What is live in production today
Four read adapters have real, wired implementations against verified domain endpoints: claims.search, claims.get, claims.get_status, epcr.get_chart_status. Every other read tool is registered with a typed-unavailable adapter that returns MCP_TARGET_UNAVAILABLE. The broker never fabricates a result.
What is disabled on day one
Write execution is off by default. A write tool call resolves to a pending approval and does not run. When execution is enabled, writes still require a human approval per call and are idempotent by approval id.
What Core still needs to expose
Core's resolve_external_tool_call logic exists and is unit-tested, but the HTTP route POST /api/v1/ai/policy/resolve/tool is being finalised on Core's main. Until it is wired, the broker resolves every call to DENY. That is the correct fail-closed behaviour; it is not a runtime bug.
What we will not do
We will not ship a MCP surface that pretends to reach data it cannot reach. We will not add a fail-open code path. We will not accept an identity claim the model made about itself. If any of the above ever changes for a specific tenant, it will be a signed, audited configuration change, not a code shortcut.
Bring the client you already use — Claude, ChatGPT, or your own MCP runtime. We’ll issue you a sandbox tenant, connect the broker, and driveclaims.search from your prompt before the call ends.