Authoring MCP tools for verification data sources
When an operator attaches one of your MCP tools as a lookup tool in the workspace’s Identity and Verification settings, the platform uses it as a verification data source: it reads the fields your tool returns and verifies callers against them. This page describes the contract your tool needs to meet.
The contract in one paragraph
Section titled “The contract in one paragraph”The platform calls your tool with one argument the operator designates, carrying a value the platform resolved server-side: the email address the current thread arrived from, the number the current call arrived from, or the value the caller gave the tool that triggered verification (an order number, for example). The fields an operator can bind a question to come from your tool’s declared outputSchema; a tool without one can still be bound, but the operator has to type the field path by hand and a wrong path only surfaces at runtime as a skipped question. At verification time the caller’s reply is graded server-side against the field value. Return a small set of clearly labelled, unambiguous, recently-knowable facts about the contact; structured, named fields are what an operator can bind a question to.
Three data categories
Section titled “Three data categories”The operator tags your tool with one of three categories when attaching it. The category determines when the platform prefers your tool over others (NIST §5.3.2 ordering: transaction history, then account state, then customer profile).
transaction_history
Section titled “transaction_history”Returns recent events: orders placed, payments made, refunds issued, deliveries, support interactions. Strongest verification signal because an attacker rarely knows what the caller did in the last 30 days.
Good response shape:
{ "items": [ { "id": "ord_abc", "type": "order", "amount": 12.50, "currency": "EUR", "ordered_at": "2026-04-12T10:00:00Z", "delivered_at": null, "items": [{ "sku": "SKU-123", "name": "Blue widget", "quantity": 2 }] }, { "id": "ord_xyz", "type": "order", "amount": 47.00, "currency": "EUR", "ordered_at": "2026-04-05T14:00:00Z", "delivered_at": "2026-04-08T11:00:00Z", "items": [...] } ], "as_of": "2026-05-13T09:00:00Z"}These fields support verification questions like “what is the most recent order you placed?”, “roughly how much was your last order?”, or “what date did your last order arrive?”. All three are derivable from the response.
account_state
Section titled “account_state”Returns the current state of the caller’s account: balance, active subscriptions, last login, current credit. Medium-strength signal.
Good response shape:
{ "balance": { "amount": 142.10, "currency": "EUR" }, "active_subscriptions": [{ "name": "Premium", "renews_at": "2026-06-01" }], "last_login_at": "2026-05-12T22:30:00Z", "as_of": "2026-05-13T09:00:00Z"}These fields support questions like “what is your account currency?”, “do you have a subscription that renews next month?”, or “when did you last log in?”. The first is trivial; the others are recall-friendly without being guessable.
customer_profile
Section titled “customer_profile”Returns longer-lived demographic fields: date of birth, postal address, mother’s maiden name (yes, really), preferred language. Weakest signal because open-source research often surfaces these.
Good response shape:
{ "first_name": "Alex", "last_name": "Smith", "date_of_birth": "1985-07-14", "postal_address": { "line1": "Hauptstrasse 12", "city": "Berlin", "postcode": "10115", "country": "DE" }, "preferred_language": "de"}These fields support questions like “what is the postal code on file?” or “what is your preferred language for communication?”. Use sparingly; pair with at least one stronger category for meaningful confidence.
Tool arguments
Section titled “Tool arguments”The operator binds each question to one argument of your tool and picks where its value comes from:
| Source | Value sent |
|---|---|
| The thread’s email address | the sender address of the current conversation |
| The call’s number | the caller number of the current call, E.164 |
| A value the caller gave | the argument the caller supplied to the tool that triggered verification, for example an order number |
The argument name is yours; the designation is validated against your declared inputSchema, so the platform never sends an argument name your tool did not declare. tenantId and workspaceId are always present alongside it (mcp-hub injects them).
{ "order_id": "ORD-4521", "tenantId": "...", "workspaceId": "..." }Return shape guidance
Section titled “Return shape guidance”Return the smallest payload that meaningfully answers the questions a caller can recall. Avoid:
- Raw IDs without human-readable labels. The caller does not know what
ord_abc123defis, and it makes a poor verification question. Pair every ID with a name, date, or amount. - Hundred-item lists. Three to five items is the sweet spot. If your underlying system can return more, paginate or limit.
- Sensitive values that should never be read back. Do not include the caller’s IBAN, full card number, or government ID number in a lookup tool’s response. The platform’s rejection-language guidelines suppress most of this, but a value can be surfaced unintentionally if it looks like the answer to the question.
Risk classification
Section titled “Risk classification”The operator separately sets a risk classification on your tool in the MCP hub:
read: public information.read_pii: returns personal data (GDPR Art. 4(1)). Platform floor for this classification isidentified.write: state-changing. Platform floor isidentified.destructive: irreversible or financially material. Platform floor ishigh-assurance.
A lookup tool is typically read_pii because it returns the caller’s personal information. On the agent lane the platform will not call it under anonymous; verification and contact-resolution reads reach it through the server-side reader lane described in the next section. The contract for the contact-resolution half is on The customer lookup contract.
The verification reader lane
Section titled “The verification reader lane”To resolve the chicken-and-egg problem (the caller needs verifying, but a read_pii tool requires identified), verification reads run on a server-side reader lane that satisfies the assurance gate. Three properties matter to you:
- The lane is scoped to attached tools only. The read is allow-listed to the tools the operator attached as verification data sources in this workspace. A call to any other tool on the lane is refused before it reaches your server.
- The lane only reads. A tool classified
writeordestructiveis refused on the lane, and the lane never carries an idempotency key, because a verification read must be free of side effects. - The lane is logged. Every use writes a
verification_agent_context_usedidentity event with the tool name. Auditors can review these.
Your tool does not need to know whether it was called on the lane; the lookup result is read the same way. Everything above is enforced on the platform side, and the field value your tool returns is graded server-side and never reaches a language model.
Testing your tool
Section titled “Testing your tool”Use the MCP hub testing surface (in the dashboard, open your connection and choose Test) to invoke your tool with sample arguments and inspect the response shape.