Amiqus MCP server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Amiqus MCP serverWhere is Martin McFly's onboarding? Which steps are still open?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Amiqus MCP server
An MCP server that lets Claude, ChatGPT and other MCP clients read an Amiqus ID account (client onboarding with identity, AML, right-to-work and criminal-record checks): clients, records and their steps, check results, templates, case status counts and webhooks, and (when enabled) create records. It is built from Amiqus's public developer documentation and its published OpenAPI 3.1 spec, and nothing else.
Once it's connected, someone on the team can ask things like:
"Where is Martin McFly's onboarding? Which steps are still open?"
"Which records are waiting on check results, and who created them?"
"Did the photo ID check on record 983500 pass? What needed consideration?"
"How many cases need action from us this month?"
"Which record templates are enabled, and what steps does 'Identity verification' send?"
With writes enabled: "Send Jennifer Parker the Identity verification template."
Tools
Tool | What it does | API calls |
| Clients with name, decision status, reference, retention date and timestamps. Filters: fuzzy |
|
| One client. |
|
| Every record sent to one client, with its steps. |
|
| Records across the team. Filters: |
|
| One record with its steps. By default the steps are fetched with |
|
| One check with its response expanded: overall result, and per report the status, result and verification breakdown. |
|
| Record templates (preset steps, notification, message, reminders, assignees), email templates or document templates; |
|
| Count of cases per status, with |
|
| Webhook subscriptions: URL (origin and path), events, enabled flag. Never the signing secret. |
|
| Creates a record for an existing client from a record template ( |
|
Not covered on purpose: the user and team endpoints, client addresses, organisations, assignees, forms and form templates, files and downloads (/records/{id}/download, /clients/{id}/files/{fileId}/download, /clients/{id}/forms/{reference}/download), documents and attachments, credits, cases and case items, step reviews (writing), SDK tokens, webhook creation, and every update, archive, expire and delete endpoint. This server never downloads a file.
Related MCP server: Yardstick ATS MCP Server
Setup
Requires Node 18 or later.
npm install
npm run buildYou need a personal access token for your Amiqus team. Amiqus's authentication guide says a token carries the permissions of the user who created it, is limited to the team active when it was created, expires after one year and can be revoked by the user; the API accepts it as a Bearer token. Amiqus also documents an OAuth2 authorization-code flow (/oauth/authorize, /oauth/token); this server does not implement it.
Claude Desktop: add this to claude_desktop_config.json:
{
"mcpServers": {
"amiqus": {
"command": "node",
"args": ["/absolute/path/to/amiqus-mcp/dist/index.js"],
"env": { "AMIQUS_ACCESS_TOKEN": "your-token" }
}
}
}Claude Code:
claude mcp add amiqus -e AMIQUS_ACCESS_TOKEN=your-token -- node /absolute/path/to/amiqus-mcp/dist/index.jsVariable | Required | Meaning |
| yes | A personal access token, sent as |
| no |
|
| no | Defaults to |
Safety defaults
Read-only unless
AMIQUS_ALLOW_WRITES=true. Read tools carry the MCPreadOnlyHintannotation;create_recordis marked as a non-destructive, non-idempotent write. There are no cancel, archive, expire or delete tools.This is identity data, so the default output is names and states, not personal details. Client names, references, statuses, dates and IDs are returned by default. Only returned when a tool is called with
include_contact_details=true: a client's email address, landline, mobile, date of birth and National Insurance number; a record's contact email and itsperform_url(the spec calls it "the unique URL to complete the record steps in a browser", so whoever has it can submit identity documents as the client; the default output only says whether one exists); and, inside a check response, the data read from the identity document (document_data: names, date of birth, gender, document numbers, issue and expiry dates, MRZ lines, nationality, place of birth, and thenfcchip data when the chip was read), the eVisa report'snameandreference, and any bare date in a check response (the eVisa'sstarts_atandexpires_at, say; a date without a time of day is the shape of a date of birth, so it is redacted by default, while timestamps are kept). The verification breakdown (which checks wereclearorconsider, with scores) is returned by default: its entries named after fields (first_name,date_of_birth,document_numbers,mrz) are verdicts about those fields, not the values, and only the verdict parts of such an entry come back (result,status,type, nested verdicts, the reason'stype, scores); anything else stored next to the verdict is withheld.Never returned, with or without
include_contact_details: identity-document images, selfies and motion captures, eVisa PDFs and any other attachment inside a check response (replaced by a placeholder and a count); the attachments of document steps (only a count); a form's answers (only the field count); a webhook's signing secret; and the query string of a webhook delivery URL (which may carry a token; the output flags that it was removed). The server never calls a download endpoint.In free text (references, step preferences such as a document request's title and instructions, review messages, template names, descriptions, messages and content, eVisa conditions, error messages from Amiqus) these are replaced by default: email addresses (
[email redacted]), phone-number-like sequences ([phone redacted]), dates without a time of day such as1968-06-12,12/06/1968,12.06.1968,12 June 1968orJune 12th, 1968([date redacted]), UK postcodes ([postcode redacted]), National Insurance numbers ([NI number redacted]) and NHS numbers, ten digits in 3-3-4 groups whose last digit passes the modulus-11 check ([NHS number redacted]). All of these are heuristics. The phone match covers international numbers written with+or00, UK numbers with a bracketed area code, and UK-style0…numbers of 9 to 11 digits with spaces, dots or hyphens; other digit strings starting with0may be caught too, and one ten-digit number in eleven passes the NHS check. Not caught: a street address written as words (12 High Street; its postcode is), a year-month (2026-08) and a date glued to letters. Left alone on purpose: numeric IDs, UUIDs, timestamps (2026-08-22T09:00:00Z), version numbers and hyphenated references such asMCFLY-1955orREF-2026-08-22. Template text has noinclude_contact_detailsswitch and is always redacted. Values nested more than 20 levels deep are replaced by a placeholder.The check-response scrubbing is generic because the spec marks check responses as beta ("available data may be incomplete or differ from the specification") and documents only the Photo ID response in full. It works by key name: a key matching this list is withheld unless its value is a
{result: …}verdict:name/names,first_name,last_name,middle_name,full_name,complete_name,surname,forename(s),given_name(s),holder,date_of_birth,dob,birth…(birth_date,birthday),gender,sex,nationality,place_of_birth,document_data,document_number(s),mrz,address,street,city,town,county,postcode/post_code/postal_code,zip,line1/line_1,email,phone,mobile,landline,telephone,national_insurance_number,ni,ni_number,nhs…(nhs_number,nhs_no),pin,pin_number,share_code,reference,passport,passport_number,licence_number/license_number,issuing_date,issue_date,date_of_expiry,expiry,expiry_date,personal_details,applicant,account_number,sort_code,iban,card_number,personal_number,id_number,certificate_number,identifier,nfc, each matched as a whole word within an underscore-separated key, after splitting camelCase and lower-casing (dateOfBirth,DocumentNumberandaddress_line_1match;document_typedoes not). Anything else in a check response is returned, with the free-text redaction above applied to every string, so a personal value under a key that is not on the list would come back with its dates, postcodes and contact details redacted but its words (a name, a street) intact. Any key that looks like a file (media,attachment(s),image(s),pdf,selfie,video,photo) is always withheld.IDs are checked before any call is made: every ID this server sends is a positive whole number (the spec types them as integers). The
expandvalues sent are the documented ones (check,reviewon steps,responseon a check), comma-separated as the expandable-properties guide shows. Filter values are the spec's enums;assignee/assigned_totake a user ID orfalseas documented. A date or date-time given tocase_status_summaryis sent asYYYY-MM-DDTHH:MM:SSZ, the form in the data-formats guide: a date alone becomesT00:00:00Z(start) orT23:59:59Z(end), missing seconds become:00, a time without a zone is taken as UTC, an offset such as+01:00is converted to UTC and fractions of a second are dropped; an impossible calendar date (2026-02-30,2026-13-01) or time of day is refused before any call.create_recordsends exactly the two documented request shapes (the spec's "Template" and "Manual" variants) and refuses a mix of them locally. Steps are passed through as given; their types and preferences are the API's, and the API's 422 field errors (steps.0.type: The selected type is invalid.) are passed on.Rate limits, as documented in Amiqus's rate-limits guide: every response carries
X-RateLimit-LimitandX-RateLimit-Remaining(the guide's example limit is 200, and "rate limits may differ depending on the endpoint"); once exhausted, requests get a 429 withRetry-After(seconds until the limit resets) andX-RateLimit-Reset; one limit is shared by every token of a user on a team. The window length is not documented. Requests are spaced 250 ms apart (the tests measure at least 240 ms between consecutive requests on an open connection). A 429 is retried at most twice for any method, includingPOST /records, on the assumption that a rate-limited request was not processed (see Status). The retry waits forRetry-After(whole or fractional seconds, or an HTTP-date; 2 s then 4 s when the header is absent or unreadable). Each wait is capped at 10 seconds so a tool call stays under the MCP client's default 60-second request timeout: if Amiqus asks for a longer wait the call gives up at once and the message says how long to wait. The final 429 message quotesX-RateLimit-LimitandRetry-After.502, 503 and 504 are retried the same way for
GETonly; when all three attempts fail the error says the service may be unavailable or in maintenance (the status-codes guide describes 503 as maintenance) and to try again in a few minutes, without the gateway's HTML. APOST /recordsis never retried after a gateway error, because the record may already have been created and the client emailed; the error tells the assistant to check withlist_recordsorlist_client_recordsfirst. Amiqus documents no idempotency key, so there is nothing to send that would make a repeat safe.A 200 whose body is not JSON (a proxy or a login page in the way) is reported as an error naming
AMIQUS_BASE_URL, never as an empty list. A rejected token produces a message that says which variable to fix and never echoes the token; a 403 says the token's user may lack permission or the feature (cases, for example) may not be enabled for the team; a 404 names the path; a 422 lists Amiqus's field errors.
Tests
npm testThe test suite:
Validates every fixture record against the schemas in Amiqus's published OpenAPI 3.1 spec, with Ajv 2020-12: clients (
Clientplus the/clientsstatus enum), records (Record), every step (RecordSteps), checks (Check, including the documented Photo IDCheckResponsewith document, facial-similarity and eVisa reports), step reviews (StepReview), record, email and document templates, webhooks and the case status aggregate. Negative controls confirm the schemas reject a string ID, an undeclared key, an unknown status and a malformedlinksobject. The spec is downloaded fromdevelopers.amiqus.co/aqid/openapi.jsontospec.jsonon the first run.Starts a local mock of the API under
/api/v2that serves those fixtures with the documentedpage/limitpagination (PaginatedListwithlinks.next/previouscarrying the current query parameters,links: nullfor a single page, 422 for a limit above 100, and on request pages capped below the requested limit or responses withoutlinks), Bearer-token 401s in theErrorshape, the spec's default 404 texts (Client not found,Record not found,Check not found), 422 field-error maps (including the guide's "expand parameter must be one of" case), theX-RateLimit-*headers,expand=check,reviewon steps andexpand=responseon checks (with a collapsedtrue/nullresponse otherwise, and no nested expansion, as the guide says), andPOST /recordsin both documented shapes (the spec's own request examples are posted and answered with aRecord). The mock's list, detail, created and error responses are validated against the spec's response schemas. The firstGET /templates/recordsis answered with a 429.Starts the built server and drives it over stdio with the official MCP client: 33 checks covering every tool, tool annotations, paging by
page/limitacross two pages of 100 and stopping whenlinks.nextis null, whole-pagemax_resultswithnext_page(and the short last page fetched whentotalsays it fits), paging through short pages when the API caps the page size (with the stop rule using the applied page size and the throttle's 250 ms spacing measured between requests on an open connection), paging bycurrent_page/total_pageswhen a response has nolinks, every documented filter oflist_clients,list_records,list_templates,list_webhooksandcase_status_summarypassed through with the documented parameter names and values (includingassignee=false,created_byrather than the deprecatedcreator, and seven date/date-time input forms each sent asYYYY-MM-DDTHH:MM:SSZwhile nine malformed or impossible ones are refused with the intended message and no request), the default redaction and its opt-in for client contact details, a record's email and perform URL, step preferences, review messages and check responses (verdicts kept,document_data, eVisa name/reference and bare dates withheld, images and files never returned even on request), the 'not yet available' and pending check responses, the 429 retry waiting forRetry-Afterin the seconds, fractional-seconds and HTTP-date forms, giving up after three attempts on a persistent 429 and at once on aRetry-Afterabove the cap, a 429 onPOST /recordsretried once, a 502 and a 504 retried forGETand a 502 never forPOST /records, aGETfailing three times with 503 reported with advice and without the gateway HTML, a 403 reported with the permissions hint and the email, phone, postcode, date, NI and NHS number in Amiqus's own message redacted, a 200 with a non-JSON body reported as an error, thePOST /recordsbodies validated against the spec's request schema and its Template and Manual branches, the local refusal of mixed or incomplete create requests and the pass-through of 422 field errors, ID validation before any call, the 401 and 404 messages, the write gate with the variable unset and set tofalse, a base URL with credentials refused at start-up, that every request used the Bearer token, asked for JSON and matched a documented method and path, and, directly on the formatter, the reduction of an expanded document step to counts and a form to its field count, the 20-level nesting placeholder, the withholding of values stored next to a verdict under a personal-data key (with the documented Photo ID breakdown unchanged), the key spellings and camelCase forms on the list above, NFC chip data withheld by default and returned on request, and the free-text patterns with their intended non-matches (shapes the server never requests, so the mock never serves them).
The suite makes 106 requests to the mock and takes about 35 seconds; it never contacts Amiqus except to download the spec.
Status
This is a working prototype. It has not yet been run against the live API, because it was built without an Amiqus account (there is no self-serve trial; the getting-started guide says to contact Amiqus for a sandbox). Everything below is taken from the published documentation and should be confirmed on a real account, sandbox first:
Authentication end to end with a personal access token, the body of a real 401 (the spec gives only
{error}), and whether a token limited to one team sees exactly that team's data.Pagination: that
links.nextis null on the last page andlinksnull on a single page as the guide says (the server also treatscurrent_pagebelowtotal_pagesas "more pages", so a response withoutlinksis still paged, and it sizes the next page from the response'slimitandtotal), whatlimitandpagevalues outside 1..100 and 1.. answer (the mock answers 422), whether any endpoint used here has a page limit below 100 (the guide says some may), and thattotal,total_pages,current_pageandlimitare always filled.The default sort order of
GET /clients("ID order" per the parameter description) andGET /records("created_at order"), and the exact semantics of thesearch(fuzzy) andreference(exact) filters.assignee=falseonGET /recordsandassigned_to=falseon the aggregate: the spec types them as integer-or-false; the server sends the literalfalseas a query string.The
expandparameter: thatexpand=check,reviewonGET /records/{id}/stepsandexpand=responseonGET /checks/{id}are accepted with a comma-separated list, what the expandedreviewlooks like on a step that has never been reviewed (the spec saysnull) and on one that cannot be (false), and whether an embedded check'sresponseis collapsed totrue/null.The shape of check responses on a live account. The spec marks them as beta and documents only the Photo ID response (
check_response.photo_id) in detail, and its examples label that checktype: "identity"while theCheck.typeenum also hasphoto_id; other types come back ascheck_response.other. Which fields carry personal data in the responses of watchlist, criminal-record, credit and other checks is unknown, which is why the scrubbing is by key name and generic. Confirm on real responses that nothing personal slips through by default.Which fields the live API fills:
national_insurance_numberandis_declaration_requiredare "available where feature enabled on team only";perform_urlisfalsewhen nothing can be submitted;deletion_datemay be null.GET /aggregates/case-statuson a team without cases (the spec says cases "may not be enabled for all teams"; the server reports a 403 with that hint) and the exact meaning ofstart_date/end_date("statuses updated on or after/before").POST /records: that a record created from a template withassignees: falsereally gets no assignees, what the created record'sstepslook like for document and form steps (the mock resolves a{template}preference to a title and instructions, as the spec's 201 example does), and whether a 429 onPOST /recordscan ever arrive after the record was created (the server retries a 429 once on the assumption that it was not processed).The wording of Amiqus's error messages and whether any of them echo request data; the texts here are placeholders (the 404 texts are the spec's defaults), and the server redacts contact details from them regardless.
The date-time format on the wire: the data-formats guide says RFC 3339 with
Z, which is what the fixtures use and whatajv-formatsrequires.How many requests per second the API tolerates within its limit; the window is not documented, so the 250 ms spacing is a guess on the polite side.
Going to production
This version runs locally over stdio, with the account holder's own personal access token. For customers to connect from claude.ai or ChatGPT without handling tokens, the next step is a remote server (Streamable HTTP) behind Amiqus's own OAuth2 authorization-code flow, hosted by Amiqus, and then a listing in the Claude and ChatGPT connector directories.
Licence
MIT. Built by Alexandru Dragoș (alexandru.dragos96@gmail.com) with an AI agent (Claude) working under his direction.
Available Tools
9 toolscase_status_summaryCase status summaryARead-onlyIdempotent
How many cases are in each status (awaiting_response, action_required, reviewed_pending_decision, approved, rejected, on_hold; pending is deprecated), optionally for one assignee or unassigned cases, for statuses updated in a date range, and active or archived cases. Uses GET /aggregates/case-status. The spec notes cases may not be enabled for all teams; a 403 then says so.
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | Only statuses updated on or before this date/time (`end_date`) (ISO 8601 date or date-time, sent to the API as YYYY-MM-DDTHH:MM:SSZ: a date alone means the end of that day in UTC, a time without a zone is taken as UTC, an offset is converted to UTC, fractions of a second are dropped) | |
| start_date | No | Only statuses updated on or after this date/time (`start_date`) (ISO 8601 date or date-time, sent to the API as YYYY-MM-DDTHH:MM:SSZ: a date alone means the start of that day in UTC, a time without a zone is taken as UTC, an offset is converted to UTC, fractions of a second are dropped) | |
| visibility | No | Only active or only archived cases (`visibility`; both by default) | |
| assigned_to | No | Only cases assigned to this team member ID, or false for unassigned cases (`assigned_to`) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, idempotentHint, destructiveHint=false), and the description usefully adds the backing endpoint (GET /aggregates/case-status), the deprecation of the 'pending' status, and the 403 behavior when cases are not enabled for a team. That is genuine operational context beyond structured fields, though no rate-limit or pagination detail is given.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core purpose followed by optional scoping and an edge-case note; nothing is repetitive. The long parenthetical status list and filter enumeration make it dense, but each clause carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must convey the return shape, and 'how many cases are in each status' does so adequately for a count-by-status aggregate. Combined with the 403 caveat and status vocabulary, an agent has enough to call and interpret it, though the exact response structure is not spelled out.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the schema already documents all four parameters, including the assigned_to=false meaning for unassigned and the date precision rules. The description largely restates those filters; its only added semantic is that 'pending' is deprecated, which is modest value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific aggregation verb and resource ('How many cases are in each status') and enumerates the exact status vocabulary, so an agent knows this returns counts, not a case list. It is clearly distinguishable from siblings like list_records or get_check, which return entities rather than aggregates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description spells out the optional scoping dimensions (single assignee, unassigned, status-update date range, active vs archived), which implicitly tells the agent when this tool applies. It does not, however, name an alternative or state when not to use it, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_checkGet check resultARead-onlyIdempotent
One check by ID (from a record's check steps) with its type, status and, when Amiqus has one, the response: overall result and each report's status, result and verification breakdown (which verifications were clear or need consideration). Uses GET /checks/{id}?expand=response. The spec marks check responses as beta and documents the Photo ID response in detail; other types may come back as 'not yet available'. Identity-document data read from the document (names, date of birth, document numbers, MRZ) and the eVisa report's name and reference only with include_contact_details; the document images, selfie and PDF are never returned.
| Name | Required | Description | Default |
|---|---|---|---|
| check_id | Yes | Check ID (a positive whole number) | |
| include_contact_details | No | Include the identity-document data extracted by the check and the eVisa report's name and reference (never the images or files). Off by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial beyond that: the endpoint used (GET /checks/{id}?expand=response), beta status of responses, type-specific availability, and exactly which sensitive fields appear only with include_contact_details while images/selfie/PDF are never returned.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single dense paragraph that front-loads the purpose and then layers endpoint, beta caveat, and privacy behavior. Every clause carries information, though the run-on structure and heavy parentheticals could be broken up for easier scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully carries the burden of describing return shape (type, status, response, per-report status/result, verification breakdown) and data-access caveats, so an agent knows what it will receive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented, and the description's mention of include_contact_details largely mirrors the schema text. The privacy framing adds mild value but no syntax or format detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource ('one check by ID'), its origin ('from a record's check steps'), and the payload returned (type, status, response with per-report status/result and verification breakdown). This clearly separates it from siblings like get_record or get_client.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It establishes the context that check IDs come from a record's check steps, implying get_record precedes this call, and notes that responses are beta so other check types may return 'not yet available'. It lacks an explicit when-not or named alternative, but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_clientGet clientARead-onlyIdempotent
One client by ID: name, decision status, reference, whether archived, retention (deletion) date and timestamps. Uses GET /clients/{id}. Contact details, date of birth and National Insurance number only with include_contact_details.
| Name | Required | Description | Default |
|---|---|---|---|
| client_id | Yes | Client ID (a positive whole number) | |
| include_contact_details | No | Include the client's email address, landline, mobile, date of birth and National Insurance number. Off by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, idempotent, non-destructive and openWorld, so the safety profile is done. The description adds genuinely useful context beyond that: the underlying endpoint (GET /clients/{id}) and, importantly, that sensitive PII (email, landline, mobile, DOB, NIN) is withheld unless include_contact_details is set. It does not say what happens for an unknown ID.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core purpose and ending on the parameter caveat. The field enumeration is information-dense rather than padding, and nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of describing the return shape, and it does so adequately by listing the returned fields. For a simple two-parameter read tool with strong annotations this is nearly complete; only error behavior for a missing/invalid ID is unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are fully documented in the schema, including the exact fields gated by include_contact_details. The description restates that the contact fields are conditional but adds no format, range, or default nuance beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (fetch one client by ID) and enumerates the returned fields (name, decision status, reference, archived flag, retention date, timestamps), so the agent knows exactly what it gets. It separates itself from list_clients by the singular 'One client by ID', though it never names that sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: you need a known client_id and want a single client rather than a list. The description does give real conditional guidance for include_contact_details ('only with'), which is the closest thing to explicit when-to-use. It offers no exclusions or named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recordGet recordARead-onlyIdempotent
One record by ID with its steps. By default the steps are fetched with their check and latest review expanded (GET /records/{id} then GET /records/{id}/steps?expand=check,review), so each check step shows the check's status (pending, submitted, accepted, rejected, refer, failed, paused) and whether a team member has reviewed it. Use get_check for a result breakdown. The record's contact email and perform URL only with include_contact_details.
| Name | Required | Description | Default |
|---|---|---|---|
| record_id | Yes | Record ID (a positive whole number) | |
| include_step_details | No | Also call GET /records/{id}/steps?expand=check,review so each step carries its check status and latest review. Off gives the record's own step list (IDs only). | |
| include_contact_details | No | Include the record's contact email and perform URL, and stop redacting emails, phone numbers, dates, postcodes and NI/NHS numbers in names, references, step preferences and review messages. Off by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower; the description nonetheless adds real behavioral content — the two underlying API calls, default expansion, and the significant redaction behavior (emails, phone numbers, dates, postcodes, NI/NHS numbers) that changes only with include_contact_details. It does not mention pagination or latency cost of the extra call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then progressively discloses mechanics. Dense but nearly every clause carries information (the status enum list, the alternative routing, the redaction trigger). Slightly overlong in the embedded API path detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description does the work of describing the return shape (steps with check status and latest review). It covers the main toggles and the routing to get_check, leaving only minor gaps like error behavior for missing IDs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already documents all three parameters thoroughly, including defaults. The description restates the default expansion and the contact-detail/de-redaction effect, which reinforces but adds little syntax or edge-case meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('One record by ID with its steps') and immediately scopes it against siblings by explaining what the default expansion yields. An agent can distinguish this from list_records and get_check without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative explicitly ('Use get_check for a result breakdown'), which routes the agent away from this tool for detailed check analysis. It lacks an explicit when-not-to-use statement for the collection-level siblings (list_records), but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_client_recordsRecords for a clientARead-onlyIdempotent
Every record (onboarding request) sent to one client, with status, the steps it contains (type, completion, cost, check/document/form IDs) and dates. Uses GET /clients/{id}/records. The record's contact email and perform URL only with include_contact_details.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | API page number to start from (1-based, as documented; use next_page from a previous call) | |
| client_id | Yes | Client ID (a positive whole number) | |
| max_results | No | Most records to return in this call; whole API pages only (up to 100 per page), so fewer may come back with a next_page to continue from | |
| include_contact_details | No | Include each record's contact email and perform URL, and stop redacting emails, phone numbers, dates, postcodes and NI/NHS numbers in names, references and step preferences. Off by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds the GET endpoint and notes that contact email and perform URL appear only with include_contact_details, but the redaction semantics it gestures at are already spelled out in the schema, so net new behavioral insight is modest.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences: what it returns, the endpoint, and the one opt-in caveat. Front-loaded with the resource, no filler, though the raw endpoint string is of limited value to an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully sketches the return shape (status, contained steps with type/completion/cost/IDs, dates) and flags the redaction toggle. Pagination mechanics live in the schema, so coverage is adequate for a read-only list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents page, max_results, client_id and include_contact_details in detail. The description only re-summarizes the include_contact_details effect (contact email, perform URL) without adding syntax or defaults beyond the schema; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource ('every record / onboarding request sent to one client') and enumerates the returned fields, so the agent knows it's the per-client variant. It doesn't explicitly name the sibling list_records, but the 'one client' scoping implicitly differentiates it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the scoping phrase 'sent to one client' — use it when you have a client_id. There is no explicit when-to-use/when-not or reference to list_records as the alternative for unscoped record listing, so the agent must infer the boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_clientsList clientsARead-onlyIdempotent
Clients (the people being onboarded) with name, decision status (pending/approved/rejected, or none yet), reference, retention date and timestamps. Filter by a fuzzy search on names, reference and organisation name; by status; active or archived; assignee; exact reference; deletion-date bucket; and sort by name or date. Uses GET /clients. Emails, phone numbers, dates of birth and National Insurance numbers only with include_contact_details.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | API page number to start from (1-based, as documented; use next_page from a previous call) | |
| search | No | Case-insensitive fuzzy search on first, middle and last name, reference and organisation name (API parameter `search`) | |
| status | No | Only clients with this decision status (`status`) | |
| sort_by | No | Sort field (`sort_by`; ID order by default) | |
| assignee | No | Only clients assigned to this team member's user ID (`assignee`) | |
| order_by | No | Sort direction (API parameter `order_by`; ascending by default) | |
| reference | No | Exact, case-insensitive match on the client reference (`reference`) | |
| visibility | No | Only active or only archived clients (`visibility`; both by default) | |
| max_results | No | Most records to return in this call; whole API pages only (up to 100 per page), so fewer may come back with a next_page to continue from | |
| deletion_date | No | Only clients whose deletion date is in this bucket (`deletion_date`) | |
| include_contact_details | No | Include each client's email address, landline, mobile, date of birth and National Insurance number, and stop redacting emails, phone numbers, dates, postcodes and NI/NHS numbers typed into names and references. Off by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint, so the safety profile is covered. The description adds genuinely useful disclosure not in the annotations: contact data (emails, phones, DOB, NI numbers) is gated behind include_contact_details and otherwise redacted, and it names the underlying endpoint GET /clients. It doesn't discuss paging behavior in prose (that lives in max_results), which keeps it below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero filler, front-loaded with what a client is and what is returned, then filters, then the sensitive-data caveat. The middle filter sentence is dense but each clause maps to a real parameter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully enumerates returned fields and the sensitive-data gate, which is the main completeness burden for an 11-param list tool. Pagination semantics and continuation via next_page are left entirely to the schema, so the definition is near-complete rather than fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with 11 well-documented parameters, so the schema does the heavy lifting and the baseline of 3 applies. The prose recap of the filter surface adds confirmation but no syntax or format detail beyond the schema, and its 'sort by name or date' phrasing is looser than the schema's six-value sort_by enum.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names the verb (list) and resource (clients) and disambiguates the resource with the parenthetical 'the people being onboarded', which separates it from list_records and list_client_records. It also enumerates the returned fields (name, decision status, reference, retention date, timestamps), so an agent knows exactly what this collection contains.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states the usable filter and sort surface (fuzzy search, status, visibility, assignee, exact reference, deletion-date bucket, sort order), which tells the agent when this tool can answer a query. It stops short of naming the single-client alternative (get_client) or the condition that selects it, so it reads as strong context without explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_recordsList recordsARead-onlyIdempotent
Records (onboarding requests) across the team, each with status, the client's name and ID, its steps and dates. Filter by status, active/archived, creator, assignee (or unassigned), and the client's visibility; sort by client name or date. Uses GET /records.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | API page number to start from (1-based, as documented; use next_page from a previous call) | |
| status | No | Only records with this status (`status`) | |
| sort_by | No | Sort field (`sort_by`; created_at by default) | |
| assignee | No | Only records assigned to this team member's user ID, or false for unassigned records only (`assignee`) | |
| order_by | No | Sort direction (API parameter `order_by`; ascending by default) | |
| created_by | No | Only records created by this team member's user ID (`created_by`) | |
| visibility | No | Only active or only archived records (`visibility`; both by default) | |
| max_results | No | Most records to return in this call; whole API pages only (up to 100 per page), so fewer may come back with a next_page to continue from | |
| client_visibility | No | Only records whose client is active, or archived (`client_visibility`) | |
| include_contact_details | No | Include each record's contact email and perform URL, and stop redacting emails, phone numbers, dates, postcodes and NI/NHS numbers in names, references and step preferences. Off by default. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds the underlying endpoint (GET /records) and hints at cross-team scope, but says nothing about pagination behavior, rate limits, auth requirements, or how the default redaction of contact data interacts with list output.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences, front-loaded with what the tool returns before moving to filters/sorting and then the endpoint. Every sentence carries information, though the endpoint mention is marginally useful to an agent that never sees HTTP directly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description does the work of summarizing record contents (status, client name/ID, steps, dates) and enumerating filter/sort axes, which is enough for correct invocation. The main omission is routing guidance against the record-related siblings, plus pagination expectations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all ten parameters are already documented in the schema, including the non-obvious pagination/redaction semantics on max_results and include_contact_details. The description merely restates which filters exist and adds no format or behavioral detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and resource (records, clarified as onboarding requests), and describes the shape of each returned record (status, client name/ID, steps, dates). 'Across the team' gives partial differentiation from the sibling list_client_records, which is client-scoped, but the distinction is never made explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The filter and sort dimensions are enumerated, which implies when the tool is useful, but there is no explicit when-to-use vs alternatives guidance — nothing tells the agent to prefer list_client_records for a single client or get_record for a single record, despite both being siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_templatesList templatesARead-onlyIdempotent
Templates on the team: record templates (the preset steps, notification, message, reminders and assignees a create_record from that template would use; GET /templates/records), email templates (GET /templates/emails) or document templates (GET /templates/documents). Optionally only enabled or only disabled ones.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Which template list | records |
| page | No | API page number to start from (1-based, as documented; use next_page from a previous call) | |
| enabled | No | Only enabled (true) or only disabled (false) templates (API parameter `enabled`; both by default) | |
| max_results | No | Most records to return in this call; whole API pages only (up to 100 per page), so fewer may come back with a next_page to continue from |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), so the bar is lower; the description still adds real semantic value by explaining what a record template actually contains (preset steps, notification, message, reminders, assignees). It stops short of describing pagination behavior, which the schema covers instead.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that names the resource first and then triages the kinds with endpoints. The nested parenthetical for record templates is dense but each clause carries information, so no trimming is obvious.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only listing tool with full schema coverage and no output schema, the description supplies the semantic context an agent needs to pick the right 'kind'. Nothing critical is missing, though it never says what the returned template objects look like or how they relate to create_record beyond the record case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3; every parameter is already documented in the schema, including paging and max_results limits. The description only marginally enriches meaning by explaining that 'enabled' yields only enabled or only disabled lists, which the schema also states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Templates on the team') and enumerates the three template kinds with their backing endpoints (GET /templates/records, /emails, /documents). An agent can immediately tell this apart from the sibling list_records/list_clients/list_webhooks tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the enumeration of kinds and the enabled/disabled scoping option, but there is no explicit guidance on when to choose this tool over list_records or get_record, nor any stated prerequisites. Adequate but leaves the agent to infer route selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_webhooksList webhooksARead-onlyIdempotent
Webhook subscriptions on the team: delivery URL (origin and path only), subscribed events, enabled flag and dates. The signing secret is never returned. Uses GET /webhooks.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | API page number to start from (1-based, as documented; use next_page from a previous call) | |
| enabled | No | Only enabled (true) or only disabled (false) webhooks (API parameter `enabled`; both by default) | |
| max_results | No | Most records to return in this call; whole API pages only (up to 100 per page), so fewer may come back with a next_page to continue from |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/non-destructive, and the description adds meaningful context beyond them: the signing secret is never returned, and the delivery URL is truncated to origin and path. That is real behavioral disclosure about redaction and response shape, though nothing is said about pagination or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler; the returned-field summary is front-loaded and the redaction caveat follows immediately. Every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list endpoint with full annotation coverage and a fully documented schema, the description covers what the tool returns and the key security caveat. Pagination is handled in the schema, so little is missing; only the lack of guidance on filtering behavior keeps it from 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so page, enabled and max_results are already fully documented by the schema. The description adds no parameter-level meaning, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb ('List') plus resource ('webhook subscriptions on the team'), and it enumerates the returned fields (delivery URL, subscribed events, enabled flag, dates). It does not explicitly distinguish itself from the many sibling list_* tools, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no prerequisites, and no pointer to an alternative or companion tool (e.g. a get_webhook for a single subscription). The only operational note, 'Uses GET /webhooks', is an implementation detail rather than usage direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.1.0- First observed
case_status_summary - First observed
get_check - First observed
get_client - First observed
get_record - First observed
list_client_records - First observed
list_clients - First observed
list_records - First observed
list_templates - First observed
list_webhooks
TDQS
Scored across 9 tools
Each tool has a clearly distinct scope: list_clients/get_client target clients, list_records/list_client_records are differentiated by team-wide vs single-client scope, and get_record/get_check target distinct resources. The list vs get pairs are unambiguous, and the descriptions explicitly clarify boundaries.
Most tools follow a clean verb_noun pattern (list_clients, get_client, list_records, get_record, get_check, list_templates, list_webhooks). The lone outlier case_status_summary uses a noun-phrase convention, a minor deviation from the otherwise consistent scheme.
Nine tools is well-scoped for an onboarding domain, covering clients, records, checks, templates, aggregates and webhooks without redundancy. Each tool earns its place and none feels filler.
The read surface is broad and coherent, but the server is entirely read-only: there is no create_client, create_record, or decision/approval action despite the domain centering on onboarding workflows and the templates description referencing create_record. These notable missing write operations limit end-to-end lifecycle coverage.
Maintenance
Related MCP Connectors
Connect any AI agent to 1,000+ apps and 27,000+ actions through one remote MCP server (OAuth).
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Let AI agents query data and act across all your business apps via MCP.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceExposes identity, tools, workflows, guardrails, and evaluation as MCP tools — so any AI agent can read and write your ecosystem programmatically.3 npmMIT
- AlicenseNot gradedqualityCmaintenanceA hosted, OAuth-authenticated MCP endpoint exposing 176 tools that let AI assistants read and write jobs, candidates, applications, interviews, scorecards, prospects, talent pools, and imports within an organization's own applicant tracking data, scoped to the signed-in user's existing permissions.MIT
- AlicenseNot gradedqualityAmaintenanceEnables existing apps to expose their users and data to external AI agents via MCP with OAuth 2.1 authentication and scoped tools.313 npmMIT
- AlicenseAqualityCmaintenanceIt enables MCP clients such as Claude and ChatGPT to read an estate agency's Dezrez Rezi CRM data, including properties and their timelines, people, groups, and offers. It is read-only and applies privacy redactions by default.10MIT