Amiqus MCP server
Read Amiqus ID onboarding data via MCP, and optionally create records when writes are enabled.
List and filter clients (fuzzy search, status, visibility, assignee, exact reference, deletion-date bucket, sorting, paging).
Get one client by ID, including name, status, reference, retention date and timestamps.
List every record for a client, with status, steps, IDs and dates.
List records across the team, filtering by status, visibility, creator, assignee/unassigned and client visibility.
Get one record by ID, optionally with its steps expanded to include check status and latest review.
Get one check by ID with its expanded response: overall result and per-report verification breakdown; identity-document data only with
include_contact_details.List record, email or document templates, optionally filtered by enabled/disabled.
Summarize case status counts, optionally by assignee/unassigned, date range and visibility.
List webhook subscriptions (URL origin/path, events, enabled flag; signing secret never returned).
Create a record from a template or explicit step list only when
AMIQUS_ALLOW_WRITES=true; mixed or incomplete create requests are refused locally.Safety defaults: read-only unless writes enabled, personal data redacted unless opted in, no file downloads, ID/date validation, and rate-limit/gateway retry handling.
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 server Where 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: Timesheet Portal 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 one request waits at most 20 seconds in all; a tool call that makes several requests (pages, lookups) can still run past the MCP client's default 60-second request timeout. Past the cap: 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.
Inputs: end_date, start_date, visibility, assigned_to.
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.
Inputs: check_id (required), include_contact_details.
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.
Inputs: client_id (required), include_contact_details.
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.
Inputs: record_id (required), include_step_details, include_contact_details.
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.
Inputs: client_id (required), page, max_results, include_contact_details.
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.
Inputs: page, search, status, sort_by, +7 more.
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.
Inputs: page, status, sort_by, assignee, +6 more.
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.
Inputs: kind, page, enabled, max_results.
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.
Inputs: page, enabled, max_results.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
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
Build and run AI workflows, agents, data tables and 1000+ API integrations from any MCP client.
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
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read NewZapp account details, campaign reports, open heatmaps, contact groups and contact counts, and to search contacts with personal data withheld by default; when writes are enabled, it can also create and update contacts.MIT
- AlicenseAqualityCmaintenanceEnables MCP clients such as Claude and ChatGPT to read a Timesheet Portal account, including timesheet time and cost reports, invoices, leave bookings and balances, projects or jobs, clients, users and cost centres, across both the Standard and Recruitment editions. It is read-only, with personal and pay data withheld unless explicitly requested.8MIT
- AlicenseAqualityCmaintenanceLets MCP clients such as Claude and ChatGPT read a WorkMobile account's jobs, job types, forms, submitted form records, approvals and mobile users, and, when writes are enabled, create and allocate jobs and approve or reject records.10MIT
- AlicenseNot gradedqualityCmaintenanceLets Claude, ChatGPT and other MCP clients read events and their sessions, attendances (bookings), forms, form responses, contacts, labels and campaigns from a Gecko student recruitment CRM, and, when writes are enabled, register a contact for an event or add a label to a contact. It is read-only by default and keeps contact data minimization rules.MIT