Encompass ec360 Public Automation MCP Developer Guide
Contents
- What is ecpa-mcp?
- The ECPA policy model
- Getting started
- Connecting & authenticating
- MCP primitives reference
- Tools
- Resources
- Prompts
- End-to-end example
- Errors & troubleshooting
- Support & next steps
1 What is ecpa-mcp?
ecpa-mcp is Encompass Corporation's Model Context Protocol server for the Encompass Public Automation (ECPA) platform. It exposes ECPA capabilities — profile creation, policy execution, entity and document retrieval — as MCP tools, resources, and prompts that any MCP-capable AI client can use.
This guide targets integrators who want their AI client to drive Encompass Public Automation workflows: running KYC screening policies, reading results, pulling evidence documents. It covers connection, authentication, every primitive currently exposed, and a working end-to-end example.
2 The ECPA policy model
This MCP server mirrors the Encompass Public Automation v3.1 REST API surface. Four concepts are enough to read the rest of this guide:
Profile. A persistent record of a subject target entity being screened — a person or organisation under KYC review. Profiles hold collected data, executed policies, and produced documents.
Policy. A Policy is a combination of pre-defined searches and rules, that your Company specifies, to complete the content gathering phase of the KYC process. A policy runs automatically through the searches with minimal user input required. Policies are defined by your Encompass tenant administrators; this server lets you execute them, not author them.
Policy step / sequence / resolution. A policy breaks into sequences of steps. Most steps execute automatically. Some steps resolve based on data returned by upstream sources; a subset require user input (resolve_policy_step) — for example, selecting a match from several candidate search results a data source returned. A policy completes when every step has a resolution.
Documents and the combined PDF. Executing a policy produces documents (data source proof documents, a purchase history, a chart PDF). The server exposes per-document downloads and a "combined PDF" that stitches all policy outputs and other documents from a profile into a single file — the canonical evidence artifact for a compliance record.
For exhaustive reference on data-source-specific fields, entity types, and policy configuration, see the Encompass Public Automation API documentation (same credentials as MCP auth — see §4).
3 Getting started
Prerequisites:
- An MCP-capable AI client — the primary route covered in this guide is Claude (claude.ai or the Claude family of apps) via the Encompass connector in Anthropic's Connector Directory.
- A signed commercial license with Encompass.
- An Encompass-provisioned user account (same credentials you use for the Encompass web UI, API and API documentation).
4 Connecting & authenticating
Connect through the Encompass ec360 Public Automation connector listed in Anthropic's Connector Directory (in claude.ai and the Claude apps). Add the connector and authentication takes the user-interactive route: on first use your client opens a browser to the Encompass Public Automation login; once you sign in, the token is cached and later tool calls reuse it until it expires. No manual configuration is needed — the listed connector carries all connection details.
For integration paths outside the Directory listing — other MCP-capable clients, headless / machine-to-machine agents, prospect-specific sandboxes, or production engagements — Encompass provides the connection details for your integration at the appropriate time; see §11 for how to get in touch.
4.1 Standards-based discovery
MCP clients that implement standards-based OAuth discovery (RFC 9728 + RFC 8414 / OIDC Discovery) instead of using a preconfigured connector can resolve everything they need from this server directly, with no manual audience configuration. A 401 response's WWW-Authenticate header (see §10.1) points at <base-url>/.well-known/oauth-protected-resource; that document's authorization_servers entry points back at this same server rather than at the Auth0 tenant directly. Following it to <base-url>/.well-known/oauth-authorization-server — also served under the /.well-known/openid-configuration spelling that OIDC-only clients probe — resolves authorization_endpoint to this server's own /oauth/authorize, which forwards the browser to the Auth0 login with the correct audience already attached. token_endpoint, revocation_endpoint, and userinfo_endpoint in that same document point at Auth0 directly, since those calls don't need the audience injected on their behalf. The document's issuer is this server's own base URL (or <base-url>/c/<connection>/oauth on a connection-specific route), exactly the identifier advertised in authorization_servers, as RFC 8414 §3.3 requires; tokens themselves are still issued and signed by the Auth0 tenant, whose jwks_uri the document points at.
4.2 Machine-to-machine (M2M) clients
Backend integrations, automated pipelines, and autonomous agents that run without a human at the keyboard authenticate with the OAuth 2.0 client-credentials grant rather than the interactive browser login described above. Once a token is obtained the MCP tool surface is identical; only the way you acquire the bearer token differs.
Each M2M integration is provisioned by Encompass as a dedicated application with its own client_id and client_secret, bound to a specific ECPA user identity (i.e. a service account). Everything the integration does is attributed to that user, so there is no per-request user selection. Because both the credentials and the user mapping are bespoke per integration, Encompass issues them, along with the token endpoint URL, as part of onboarding (see §11).
To obtain a token, make a form-encoded POST to the token endpoint Encompass provides:
POST <token endpoint>
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
client_id=<your client_id>
client_secret=<your client_secret>
audience=<this server's base URL, with a trailing slash>
The response is a standard OAuth token payload. Send its access_token on every MCP request as Authorization: Bearer <access_token>, exactly as the interactive route does. Tokens expire — cache and reuse the token within its expires_in lifetime, and request a fresh one when it lapses. As with the interactive route, verify_auth (see below) confirms the connection is wired correctly; for an M2M client the reported userSub is the client identity rather than a human user.
4.3 Sanity-checking the connection
Call the verify_auth tool. It is a simple diagnostic tool that confirms both authentication with the MCP server and the server's access to your credentials for accessing the Encompass Public Automation REST API.
Successful response:
{
"status": "succeeded",
"userSub": "auth0|<your-auth0-user-id>",
"coreTokenExpiresIn": 3600,
"deployment": "<deployment label, e.g. ecpa-mcp-staging>",
"mcpBaseUrl": "https://<this server's public URL>",
"ecpaApiHost": "<host of the connected ECPA instance>"
}
Failure response:
{
"status": "failed",
"userSub": "auth0|<your-auth0-user-id>",
"deployment": "<deployment label, e.g. ecpa-mcp-staging>",
"mcpBaseUrl": "https://<this server's public URL>",
"ecpaApiHost": "<host of the connected ECPA instance>",
"error": "<message from the CTE failure>"
}
userSub is the Auth0 sub claim. This is not an ECPA user identifier — it is the Auth0 subject, useful for support tickets and not much else. When contacting support about an auth problem, include the full verify_auth payload (including the error field on failures).
deployment, mcpBaseUrl, and ecpaApiHost identify which deployment this connector is talking to. If you have multiple ECPA connectors configured (e.g. staging and production), call verify_auth on each to tell them apart — the same identity also appears in the first line of the server's instructions, and the deployment label as serverInfo.title, so capable clients can distinguish deployments without any tool call.
5 MCP primitives reference
Each entry below begins with a narrative "when to use" paragraph followed by the reference block. Input and output schemas are summaries; for exhaustive field-level shapes — especially for tools whose outputs carry polymorphic or source-specific payloads (get_profile_entities, get_profile_data_sources, get_profile_data_sources_all, get_profile_news, get_profile_purchases, get_profile_audit_trail) — refer to the ECPA v3.1 API documentation. The ECPA API documentation is reachable with the same Encompass credentials used for MCP authentication.
Where a tool returns polymorphism via a type discriminator with per-type dataSourceAttributes or similar open-map payloads, this guide documents the discriminator pattern and the common values; it does not duplicate every type's field list.
5.1 Standard ECPA error envelope
Every ECPA-backed tool (with the exception of verify_auth) surfaces upstream EcpaApiError and EcpaTimeoutError instances the same way:
- The MCP result has
isError: true. - A text-content block in
content[0].textcarries the human-readable message. For most errors this is the upstream message prefixed with"ECPA API error <status>: <detail>"or"ECPA request timed out after Nms: <method> <path>". For upstream 429 errors the text is an imperative wait instruction the LLM honours (see §10.4). - A structured
_metapayload distinguishes the error category for programmatic consumers._meta.erroris one of:'rate_limited'— a rate-limit budget was exhausted (either by the ECPA upstream API or by this server's own rate limiter). Also carriesrule: <string>,retryAfterSeconds: <int>,tool: '<name>'. See §10.4 for handling andrulesemantics.'upstream_error'— other 4xx/5xx from ECPA. Also carriesstatus: <int>,tool: '<name>'.'upstream_timeout'— the request exceeded the client-side timeout. Also carriestool: '<name>'.
- If the upstream response does not match the expected schema, the tool returns
isError: truewith a"upstream response did not match expected schema: …"diagnostic incontent[0].text(no_meta).
Individual entries below reference this as the standard ECPA error envelope rather than repeating it. Tool-specific validation errors (e.g. create_policy_order complaining about missing firstName) are called out inline where they exist; they return plain-text isError: true without _meta.
5.2 Pagination
List-returning tools share the shape documented in the server's instructions block:
Pagination: list-returning tools return
data(array of results) andpagination({ totalItems, nextCursor }). To page forward, call the tool again passing the returned cursor as thecursorargument untilnextCursoris null. Per-item objects are full resources; this server does not yet trim list fields.
All paginated tools accept cursor (opaque string from a previous response's pagination.nextCursor), offset (int, min 0, default 0), and limit (int, 1-100, default 10). When cursor is supplied it supersedes offset/limit and other filters. To page forward, pass the returned cursor until pagination.nextCursor is null. Where an entry says "paginated," assume this shape.
5.3 Value handling
The rule is stated once in the server's instructions block:
Value handling: when you put a value into a tool argument, send exactly the characters the value contains — never HTML-escape it and never percent-encode it. Most free-text fields are matched upstream by a fuzzy, token-based search, so a transformed value does not fail loudly: it silently matches the wrong things, and on an order that wrong match becomes a permanent, billable compliance record. Encoding applies in exactly one place — when a value is being packed into a URI or query-string carrier, such as the
run_policyprompt'sparametersargument or a resource URI's query string — and the field's own description says so where it applies.
- In JSON tool arguments — literal.
companyName,firstName,surname,customerReference, and everylist_*search filter take the characters as they are. This server forwards them unchanged: it does not trim, case-fold, unescape or normalise anything. - In a URI or query-string carrier — encode as that carrier requires. Two places do this, and both say so on the field: the
run_policyprompt'sparametersblob and the filtered-zip resource URI. There&must be%26, and a+in a UTC offset must be%2Bor it decodes to a space. - Never HTML-escape, anywhere. No surface on this server takes
&,'oréas the correct spelling of a value.
Neither spelling errors, which is what makes this worth watching: DEERE & COMPANY returns a page of candidates matching on the token amp, topped by a dormant branch record with no LEI, where DEERE & COMPANY returns a short, clean list. If a search returns nothing, or candidates sharing only a fragment of the name, check the spelling of the value you sent before widening the search.
6 Tools
6.1 Auth
6.2 verify_auth
Verify authentication
When to use. Confirm your connection and auth are wired correctly. Useful as a first call after setting up an MCP client connection, and as a diagnostic when you suspect a token-exchange problem. The failure payload is the recommended attachment when raising a support ticket about auth or token-exchange problems (see §10). Also the canonical way to identify which deployment (environment / ECPA instance) a connector is talking to when several are configured.
Input. None.
Output shape.
{
"status": "succeeded",
"userSub": "<auth0 sub>",
"coreTokenExpiresIn": 3600,
"deployment": "<label>",
"mcpBaseUrl": "<url>",
"ecpaApiHost": "<host>"
}
or on failure:
{
"status": "failed",
"userSub": "<auth0 sub>",
"deployment": "<label>",
"mcpBaseUrl": "<url>",
"ecpaApiHost": "<host>",
"error": "<message>"
}
userSub is the Auth0 sub claim (auth0|<id> for a human; <clientId>@clients for M2M). It is not an ECPA user identifier.
Notable errors. Token-exchange failures surface as status: 'failed' with the exception message in error. The MCP call itself still returns HTTP 200 — the failure is inside the result.
6.3 Profile management
6.4 list_profiles
List profiles
When to use. Discover existing profiles — by name, customer reference, target entity, risk level, owner, date window, or archived state. The standard entry point when you need to locate a profile you don't already have an ID for, or produce a roster for review.
Input schema (summary).
offset,limit— pagination.name,customerReference,targetEntity— case-insensitive substring match (or exact match ifuseExactNameMatch: true).companyIdentifier— include profiles with a matching company identifier.reviewDateStart/reviewDateEnd,createdDateStart/createdDateEnd— ISO-8601 date-time windows.riskStatus/riskStatuses— one ofNOT_APPLICABLE | UNSET | LOW | MEDIUM | HIGH.screeningAlerts— array ofHIGH | MIDDLE | LOW | NONE.status—ACTIVE | INACTIVE.archived— boolean.owner— profile owner email.onlyIncludeProfilesUserHasWorkedOn,includeAllAccountProfiles,quickFilter.sort— comma-separated fields,-prefix for descending (e.g.-dateModified,dateCreated).
Output shape. Paginated (see §5 preamble). data[] items are ProfileSummary — id, customerReference, name, targetEntity, profileLevel, riskLevel, userId, callerReferenceId, dateCreated, dateModified, dateArchived, nextReviewDate, archived, status, activePerspective, plus any additional fields the upstream returns.
Notable errors. Standard ECPA error envelope (see top of section). Watch for large tenants — apply filters and stop paging once you have enough data; do not mass-iterate.
Example.
{ "name": "Acme", "archived": false, "limit": 25 }
6.5 get_profile
Get profile summary
When to use. You already have a
profileId(e.g. fromlist_profiles,create_policy_order, orget_policy_order) and need the full summary — name, customer reference, target entity, risk level, status, dates, active perspective.
Input schema (summary).
profileId(string, required).
Output shape. Single ProfileSummary (see list_profiles). The relationship/ownership chart is available as a separate resource (profile_chart_pdf, see §7).
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da" }
6.6 get_profile_sharing_link
Get profile sharing link
When to use. You want to hand a profile to another Encompass user who already has their own access to this ECPA instance (they may be in a different account). You must already be able to access the profile yourself (same precondition as
get_profile).
Input schema (summary).
profileId(string, required).accessLevel(enum, required) —readOnly(recipient gets a view-only copy) orreadAndWrite(collaborative edit access).
Output shape. { data: { profileId, accessLevel, url } } — url is a link that opens the profile in the ECPA web UI. The recipient must be logged in; the link is not anonymous/public and is long-lived (it does not carry its own expiry).
Notable errors. Standard ECPA error envelope — 401 if you cannot access the profile, 404 if it does not exist.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da", "accessLevel": "readOnly" }
6.7 create_profile
Create profile
When to use. Create a new profile explicitly (e.g. you want to set it up before running any policy). Note:
create_policy_ordercan also create a profile on the fly viacustomerReference.
Input schema (summary).
customerReference(string, required) — unique customer reference describing what this profile is about.name(string, ≤256 chars, optional) — human-readable name; auto-generated fromcustomerReference+ timestamp if omitted.
Output shape. Single ProfileSummary for the newly created profile.
Notable errors. Standard ECPA error envelope.
Example.
{ "customerReference": "CUST-12345", "name": "Acme Holdings Ltd" }
6.8 refresh_profile
Refresh profile
When to use. Re-run a profile's KYC/AML policy over fresh data. Creates a new profile (the source profile is untouched) by re-running the full policy — this may incur new data purchases. The response carries a
callerReferenceIdfor the new policy run: pass it towait_for_policy_completionto monitor progress.
Input schema (summary).
refreshSourceProfileId(string, required) — ID of the existing profile to refresh. The simple case needs nothing else: ECPA re-runs the profile's existing policy (its earliest policy, if it has run several) with inputs derived from the profile.name(string, ≤256 chars, optional) — name for the new profile; copied from the source if omitted.customerReference(string, optional) — copied from the source if omitted. Only honoured for accounts with the customer-reference field enabled.policyIdentifier(string, optional) — run a different policy instead of the profile's own.policyParametersType+ parameter fields (optional) — override the subject inputs. Refresh supports three shapes:CompanyTemplateParameters(companyName,companyIdentifiers,countryCode,subdivision) for any company-shaped policy,PersonTemplateParameters(firstName,surname,middleName,birthDate) for any person-shaped policy, andCompanyWithIdAndRelatedPersonTemplateParametersfor policies declared with exactly that type. Other parameter shapes are rejected with guidance (the refresh API only honours base fields — usecreate_policy_orderwhen full parameter fidelity matters). Policies takingPersonWithIdentifierTemplateParameterscannot be refreshed.
Output shape. Single ProfileSummary for the newly created profile, including callerReferenceId for the policy run it started.
Notable errors. Standard ECPA error envelope; 422 when the profile has never run a policy and no policyIdentifier is supplied.
Example.
{ "refreshSourceProfileId": "64f0a1b2c3d4e5f6a7b8c9d0" }
6.9 archive_profile
Archive/restore profile
When to use. Move a profile into the archived state (
archived: true) or restore a previously archived profile (archived: false). Idempotent.
Input schema (summary).
profileId(string, required).archived(boolean, required) —trueto archive,falseto restore.
Output shape. Single ProfileSummary reflecting the new state.
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da", "archived": true }
6.10 Profile data
6.11 get_profile_data_sources
Get profile data sources
When to use. Inspect the entities collected in a profile together with which upstream data source supplied each attribute (the "selected" values after match-and-merge). Paired with
get_profile_entitieswhen you want to understand provenance.
Input schema (summary).
profileId(required).offset,limit— pagination.perspectiveType— one ofAllOwnership | AllOwnershipAndControl | BeneficialOwnership | BeneficialOwnershipAndControl | BeneficialOwnershipAndControlOfTargetEntity | ControlOnly | Everything.minSharePercent,maxSharePercent,beneficialOwnershipPercent— numeric 0-100.includeExtraData(string).
Output shape. Paginated EntityResource[]. Each entity has an id, a type discriminator (string), and a dataSourceAttributes[] array — each element identifies the orderId, dataSource, serviceIdentifier, dateCreated, documentIds, attributesSourceMapping, and a sourceUrl. Per-type attribute fields are open-map (catchall(unknown)) — refer to the ECPA API documentation for field-level schemas per entity type.
Notable errors. Standard ECPA error envelope.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"perspectiveType": "BeneficialOwnership",
"beneficialOwnershipPercent": 25,
"limit": 50
}
6.12 get_profile_data_sources_all
Get all profile data sources
When to use. Same as
get_profile_data_sources, but also includes the non-selected values from match-and-merge (i.e. values the data-primacy rules rejected). Use when you need to audit why a particular value was chosen over another.
Input schema (summary). Identical to get_profile_data_sources.
Output shape. Same paginated EntityResource[] shape; dataSourceAttributes[].attributesSourceMappingNotSelected is populated with the non-selected values (open-map Record<string, unknown>).
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da", "perspectiveType": "Everything" }
6.13 get_profile_entities
Get profile entities
When to use. Retrieve the merged, post-selection entity graph for a profile (Individuals, organisations, and their relationships). Use this when you want the authoritative view of who-and-what is in the profile without needing per-source provenance.
Input schema (summary). Identical to get_profile_data_sources (profileId, offset, limit, perspectiveType, minSharePercent, maxSharePercent, beneficialOwnershipPercent, includeExtraData).
Output shape. Paginated EntityResource[]. Each entity exposes:
id— entity identifier.type— string discriminator. In practice common values are driven by the upstream data source and include entity-kind discriminators such as individuals/persons, organisations/companies, and other KYC entity types. Treat this field as an open set: common values include but are not limited to the discriminator values the ECPA data source returns.dataSourceAttributes[]— per-source attribute payloads. Per-type fields within each attribute are open-map; consult the ECPA API reference for exhaustive per-type schemas.dateCreated,dateModified.
Notable errors. Standard ECPA error envelope.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"perspectiveType": "AllOwnershipAndControl"
}
6.14 get_profile_news
Get profile news
When to use. Retrieve adverse-media / news items collected for a profile by running a policy that includes a search with a screening data product such as LSEG World-Check One. Filter by review status to show only active items, only discarded items, or everything.
Input schema (summary).
profileId(required).offset,limit— pagination.status—NON_DISCARDED(default),DISCARDED, orALL.
Output shape. Paginated News[] — each item has id, type, entityId, date, title, source, linkToOriginal, linkToSource, snippet, risk, discarded, plus any additional fields the upstream returns.
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da", "status": "NON_DISCARDED" }
6.15 get_profile_purchases
Get profile purchases
When to use. Audit the data-product purchases made against a profile, including associated documents and billed cost. Useful for cost reporting and for locating the
dataProductOrderIdtied to a specific document.
Input schema (summary).
profileId(required).offset,limit— pagination.
Output shape. Paginated PurchaseHistoryResource[] — each entry: id, createdDate, searchCriteria, cost, purchasedBy, serviceName, costLabel, billedBy, dataProductOrderId.
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da" }
6.16 get_profile_audit_trail
Get profile audit trail
When to use. Retrieve the history of actions performed on a profile — creation, edits, policy runs, resolutions, archive/restore. The full, compliance-friendly paper trail. Audit trails can be very large; paginate deliberately.
Input schema (summary).
profileId(required).offset,limit— pagination.
Output shape. Paginated AuditTrailResource[] — each entry: id, type, createdDate, description, profileId, userId, plus any upstream-specific fields (open-map).
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da", "limit": 100 }
6.17 Profile documents
6.18 list_profile_documents
List profile documents
When to use. Search and list the documents attached to a profile (data source PDFs, purchase history, no-match reports, user attachments), filtered by document type, status, data provider, related entity, and created/modified date ranges.
kindandprovidertake profile-specific values — calllist_profile_document_types/list_profile_document_providersfirst and pass a value from their results; do not guess.
Input schema (summary).
profileId(required).offset,limit— pagination.kind— filter to this effective document type. Uselist_profile_document_typesfor the values available on this profile.status—PENDING | READY | ERROR.provider— filter to this data provider (source). Uselist_profile_document_providersfor the values available on this profile.entityId— filter to documents related to this entity id, following the entity merge lineage.dateCreatedStart,dateCreatedEnd— ISO-8601 windows on document creation.dateModifiedStart,dateModifiedEnd— ISO-8601 windows ondateModified(the UI "Date received").includeUserAttachments— boolean; whether to include user-uploaded attachments.includePurchaseHistory— boolean; include the workspace purchase-history document (defaulttrue; setfalseto exclude).includeNoMatchReports— boolean; include no-match reports (defaulttrue; setfalseto exclude).includeScreeningNoMatchReports— boolean; only takes effect whenincludeNoMatchReportsisfalse: defaulttruekeeps no-match reports from screening providers while excluding the rest, setfalseto exclude them all too.
Attachment-exclusion caveat. Setting
kind,status,provider,entityId, or adateModifiedbound excludes file attachments from the result — these are the selecting filters.dateCreatedbounds and theinclude*booleans do not exclude attachments.
Output shape. Paginated DocumentResource[]. Each document carries metadata including id, type, productCode, category, description, documentType, kind, filename, descriptiveFileName, dateProcessedIso, dateModified, documentName, documentAuthority, uploadedByUser, entityId, status (PENDING | READY | ERROR), plus upstream extras. Each document may also carry a trimmed related entity (entity: { id, searchableName }) — full entity details come from get_profile_entities.
Notable errors. Standard ECPA error envelope.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"kind": "PASSPORT",
"status": "READY"
}
Related resources: profile_document_raw (single document bytes), profile_documents_zip / profile_documents_filtered_zip (all / filtered documents bundled). See §7.
6.19 list_profile_document_types
List profile document types
When to use. Discover the distinct document types ('kind' values) present on a profile before filtering documents. Pass a returned kind value as the 'kind' argument to
list_profile_documentsordownload_profile_documents_zipto filter by type.
Input schema (summary).
profileId(required).
Output shape. Unpaginated collection of document types. Each item is { id, type, attributes: { kind, profileId } } — the kind value lives in attributes, not at the top level.
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da" }
6.20 list_profile_document_providers
List profile document providers
When to use. Discover the distinct data providers (document sources) present on a profile before filtering documents. Pass a returned provider value as the 'provider' argument to
list_profile_documentsordownload_profile_documents_zipto filter by source.
Input schema (summary).
profileId(required).
Output shape. Unpaginated collection of document providers. Each item is { id, type, attributes: { provider, profileId } } — the provider value lives in attributes, not at the top level.
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da" }
6.21 get_profile_document
Get profile document
When to use. Read a single document's metadata (filename, type, status, dates) by
documentId. This tool does not return the binary content — fetch that through theprofile_document_rawresource (see §7), using theidandprofileIdfrom this response.
Input schema (summary).
profileId(required).documentId(required).
Output shape. Single DocumentResource (metadata only). The raw bytes are addressable via the MCP resource URI ecpa://profiles/<profileId>/documents/<documentId>/raw (see §7 for the canonical URI form).
Notable errors. Standard ECPA error envelope.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"documentId": "69e589e22ed8ec3a7b36b2c1"
}
6.22 delete_profile_document
Delete profile document
When to use. Permanently delete a user-uploaded document from a profile. Use
list_profile_documentsto find thedocumentIdfirst. Only user-uploaded documents can be deleted — ECPA-generated (system) documents will return an error. This operation is irreversible.
Input schema (summary).
profileId(required).documentId(required) — must be a user-uploaded document.
Output shape. { success: true, documentId } on success.
Notable errors. Standard ECPA error envelope. Attempting to delete a system-generated document returns an error from ECPA.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"documentId": "69e589e22ed8ec3a7b36b2c1"
}
6.23 update_profile_document
Update profile document
When to use. Update a user-uploaded document's metadata or replace its content. Two modes: (1) metadata update — supply at least one of
filename(to rename) orentityId+entityType(to associate with a charted entity); changes apply immediately and the updatedDocumentResourceis returned. (2) Content replacement — setreplaceContent: trueto replace the document bytes; the tool returns a short-lived upload URL envelope (same shape asupload_profile_document) and thedocumentIdis preserved. Only user-uploaded documents can be updated. To perform a metadata-only update, omitreplaceContent.
Input schema (summary).
profileId(required).documentId(required) — must be a user-uploaded document.filename(optional) — new filename; must keep a permitted extension.entityId(optional) — ID of a charted entity to associate with the document.entityType(optional) — type of the associated entity.replaceContent(optional, boolean) — settrueto replace the document bytes (returns an upload URL envelope). Omit to perform a metadata-only update.
entityId and entityType must be supplied together (both or neither). For a metadata-only update, at least one of filename or entityId+entityType is required.
Output shape. Metadata-only path: single DocumentResource (the updated document metadata). Content-replacement path: { upload_url, expires_at, instructions } — see upload_profile_document for the two-step flow.
Notable errors. Standard ECPA error envelope. Returns isError: true if neither filename nor entityId+entityType are supplied for a metadata-only update, or if only one of entityId/entityType is provided.
Example (metadata update).
{
"profileId": "69e589e22ed8ec3a7b2432da",
"documentId": "69e589e22ed8ec3a7b36b2c1",
"filename": "updated-report.pdf"
}
Example (content replacement).
{
"profileId": "69e589e22ed8ec3a7b2432da",
"documentId": "69e589e22ed8ec3a7b36b2c1",
"replaceContent": true
}
6.24 upload_profile_document
Upload profile document
When to use. Upload a new document to a profile. The tool returns a short-lived, single-use upload URL — the file bytes are never passed through the MCP tool call itself. Use
get_upload_statusafter uploading to confirm completion and obtain the newdocumentId.
Input schema (summary).
profileId(required).filename(optional) — desired filename, including extension. If omitted, the filename is taken from the uploaded file.entityId(optional) — ID of a charted entity to associate with the document (requiresentityType).entityType(optional) — type of the associated entity (requiresentityId).
entityId and entityType must be supplied together (both or neither).
Output shape. { upload_url, expires_at, instructions }.
upload_url— single-use HTTPS URL; the file isPOSTed here asmultipart/form-datawith the field namefile.expires_at— ISO-8601 timestamp after which the URL is no longer valid.instructions— guidance text for the calling client on how to complete the upload and poll for status.
Two-step flow. (1) Call upload_profile_document to obtain the upload_url. (2) Send the file bytes to upload_url. Agentic clients with a network sandbox: POST the file as multipart/form-data (field name file) with Accept: application/json to receive the documentId synchronously. Chat clients: open upload_url in a browser to use the upload form. After uploading, call get_upload_status with the upload token (the last path segment of upload_url) to confirm completion. On a 503 response, the server is busy — honour the Retry-After header and retry the same URL. A 4xx is terminal; call this tool again for a fresh URL.
Notable errors. Returns isError: true when only one of entityId/entityType is supplied.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"filename": "kyc-document.pdf"
}
6.25 get_upload_status
Get document upload status
When to use. Check the status of a document upload started with
upload_profile_documentor a content replacement viaupdate_profile_document. Pass the upload token from the upload URL (the last path segment ofupload_url). Only the user who started the upload can query it.
Input schema (summary).
token(required) — the upload token from the upload URL.
Output shape. { state, documentId?, error? }.
state— one ofpending(URL issued, not yet uploaded),in-progress,complete,failed, orunknown(token not found or expired).documentId— present whenstateiscomplete.error— present whenstateisfailedorunknown; a human-readable reason.
Notable errors. Returns isError: true when the token is not found or has expired (state unknown).
Example.
{ "token": "abc123..." }
6.26 Policy execution
6.27 list_policies
List policy definitions
When to use. Search and list the policy definitions available to the caller's tenant — each has a
policyIdentifier(used bycreate_policy_order), apolicyName, apolicyDescription, and apolicyParametersType(the input shape the policy expects, e.g.CompanyTemplateParameters,CompanyWithJurisdictionTemplateParameters, orPersonTemplateParameters— seecreate_policy_orderfor the full list). Filter by identifier, name, description, or parameter type to narrow the catalogue server-side instead of paging the full set.
Input schema (summary).
offset,limit— pagination.identifier,name,description— case-insensitive substring matches onpolicyIdentifier,policyName, andpolicyDescriptionrespectively.parameterType— case-insensitive substring match on the canonical input-type class name (e.g.CompanyTemplate). Note the filter is namedparameterType; the matched value is returned in the response underpolicyParametersType.search— case-insensitive substring match OR'd across identifier, name, and description. Does not coverparameterType— pass that explicitly. Prefer a specific parameter when you know which dimension you're filtering on.
Output shape. Paginated PolicyDefinition[] — policyIdentifier, policyName, policyDescription, policyParametersType, plus upstream extras.
Notable errors. Standard ECPA error envelope.
Example.
{ "name": "sanctions", "limit": 25 }
6.28 list_data_products
List standalone data products
When to use. Search and list the data products this account is entitled to run standalone (paginated) — single KYC/AML searches or reports run without authoring a policy. Each entry has a
serviceIdentifier(the valuecreate_data_product_orderaccepts; the same value is reported asserviceIdentifieron each sequence of a policy order, so a failed sequence can be matched back to the data product to re-run it), a displayname, adataProvider,productCodes, and theparameterTypesit accepts — field descriptors for each type come fromlist_policy_parameter_types. The listing is already entitlement-filtered: absence from it means this account cannot run that product standalone. A listed parameter type that is not amongcreate_data_product_order'spolicyParametersTypeoptions cannot be ordered through this MCP build.
Input schema (summary).
offset,limit— pagination.identifier,name,dataProvider— case-insensitive substring matches onserviceIdentifier,name, anddataProviderrespectively.parameterType— case-insensitive substring match against the entry'sparameterTypes(e.g.CompanyTemplate).search— case-insensitive substring match acrossserviceIdentifier,name, anddataProvidercombined. Does not coverparameterType— pass that explicitly.- Filters are ANDed together and applied server-side before pagination; results are sorted by
serviceIdentifier.
Output shape. Paginated DataProductDefinition[] — serviceIdentifier, name, dataProvider, productCodes, parameterTypes, plus upstream extras.
Notable errors. On a deployment where standalone data products are not yet enabled, the tool returns isError: true with a message explaining the feature has not been rolled out there — this is not an authentication or permission problem, and the call should not be retried. Other failures follow the standard ECPA error envelope.
Example.
{ "dataProvider": "Creditsafe", "limit": 25 }
6.29 list_company_identifier_types
List company identifier types
When to use. Search and list the company identifier types known to the connected ECPA instance — the valid keys for the
companyIdentifiersmap oncreate_policy_orderandrefresh_profile. Small, unpaginated set; call it before constructing acompanyIdentifiersmap rather than guessing keys. The vocabulary is instance-specific and can change at runtime; it is informative only — unknown keys are silently ignored upstream, never rejected.
Input. None.
Output shape. Collection of { identifierType, displayName, description } — identifierType is the raw key to use in the companyIdentifiers map. Two optional top-level fields: on an ECPA instance that predates the vocabulary endpoint the tool returns a non-error result with data: [], vocabularyUnavailable: true, and an explanatory note (order submission is never blocked on vocabulary availability); an instance with no registered types returns data: [] with a note alone.
Notable errors. A pre-DEV-5954 ECPA instance yields the non-error vocabularyUnavailable result described above, not an error. Other failures follow the standard ECPA error envelope.
Example.
{}
6.30 list_policy_parameter_types
List policy parameter types
When to use. Search and list the policy input parameter types registered on the connected ECPA instance — the
policyParametersTypediscriminator values accepted bycreate_policy_orderandcreate_data_product_order— each listed once with its field descriptors (name,type,required). Small, static set per deployment; takes no parameters and is safe to fetch once per session. This reports what the connected ECPA server accepts; the order tools' ownpolicyParametersTypeoptions are the set this MCP build can construct — a type listed here but absent from those options cannot be ordered through MCP.
Input. None.
Output shape. Collection of { name, fields: [{ name, type, required }] } — one entry per registered parameter type.
Notable errors. On a deployment where standalone data products are not yet enabled, the tool returns isError: true with a message explaining the feature has not been rolled out there — this is not an authentication or permission problem, and the call should not be retried. Other failures follow the standard ECPA error envelope.
Example.
{}
6.31 create_policy_order
Create policy order
When to use. Start a KYC/AML screening: pick a
policyIdentifierfromlist_policiesor use a known value, supply the subject (company or person) parameters, and either reuse an existing profile (profileId) or create a new one implicitly (customerReference). Returns acallerReferenceIdused by all follow-up tools.
Input schema (summary).
policyIdentifier(string, required).policyParametersType(required) — must match the policy definition'spolicyParametersType(seelist_policies). One of:CompanyTemplateParameters—companyName(required);companyNumber,countryCode(2-letter ISO),subdivision,companyIdentifiers(optional).CompanyWithJurisdictionTemplateParameters—companyName(required);countryCode,companyNumber,companyIdentifiers(optional).CompanyWithJurisdictionAndAddressTemplateParameters—companyName(required);countryCode,companyNumber,zipCode,townCity,stateTerritory,streetLineAddress,companyIdentifiers(optional).CompanyWithBvDIDAndJurisdictionTemplateParameters—companyName(required);countryCode,companyNumber,bvdId,companyIdentifiers(optional).CompanyWithIdAndRelatedPersonTemplateParameters—companyName(required);companyIdentifier,companyIdentifierType, plus related-personfirstName,surname,middleName,birthDate(optional).VedaasCompanySearchParameters—companyName(required);countryCode,companyNumber,companyNumberType(optional). The scalarcompanyNumberTypeis a closed set, validated on this server — one ofAVID,CIK,INCORPORATED_REGISTERED_NUMBER,LEI,OPERATIONAL_REGISTERED_NUMBER,REGULATORY_ID,SWIFT_BIC,TAX_ID,TICKER_CODE(defaults toAVIDupstream); an unlisted value is rejected before the request is sent.companyIdentifiersis also accepted, and its map keys are a different thing — they are not limited to that closed set; they follow the same runtime-defined rules as for the other company types (seecompanyIdentifiersbelow).companyNumber/companyNumberTypeoverwrite a colliding map entry upstream — supply a given identifier via the map or the scalar pair, not both.PersonTemplateParameters—firstName+surname(required);middleName,birthDate(YYYY-MM-DD,YYYY-MM, orYYYY) optional.PersonAddressTemplateParameters—firstName+surname(required);middleName,birthDate,streetNumber,streetName,locality,country,postcode,addressLine1,addressLine2(optional).PersonWithIdentifierTemplateParameters—personIdentifier(required).
companyIdentifiers (all company types above except CompanyWithIdAndRelatedPersonTemplateParameters) — a map of raw identifier type → value, e.g. {"LEI": "5299000RWD2J46DMCW33"}, pinning the company by one or more registry identifiers. Discover the valid keys for this instance with list_company_identifier_types (common examples: LEI, DNB_DUNS, UK_COMPANY_NUMBER); the set is instance-specific, and unknown or misspelled types are silently ignored upstream (the order then falls back to name-based matching). Distinct from the scalar companyIdentifier/companyIdentifierType pair — supply multiple identifiers via a map not multiple scalar pairs.
- Exactly one of
customerReferenceorprofileIdmust be supplied.
Output shape. Single PolicyOrderResult — callerReferenceId, status (IN_PROGRESS | ACTION_REQUIRED | PAUSED | COMPLETED | MATCHES | NO_MATCHES | NO_RESULTS | RISK_IDENTIFIED | FAILED | ABORTED | UNKNOWN, plus legacy SUCCESS / REFER / USER_SKIPPED, only returned for orders that pre-date the v3.1 policy statuses), policyIdentifier, profileId, policyParameters, dateCreated, dateStarted, dateCompleted, executionSummary (per-sequence status counts — present on any status with a persisted execution tree, grows during the run), and, when recorded, partialFailure (FAILED orders only: whether some data products completed), failureReason and failureCode.
Notable errors. Standard ECPA error envelope, plus tool-level validation errors as plain-text isError: true responses: missing customerReference/profileId, missing companyName for company policies, missing firstName/surname for person policies, missing personIdentifier for PersonWithIdentifierTemplateParameters, companyIdentifiers supplied with an ineligible policyParametersType (the error names the eligible types; for CompanyWithIdAndRelatedPersonTemplateParameters it points at the scalar companyIdentifier/companyIdentifierType pair instead).
Example.
{
"policyIdentifier": "pol_default_kyc",
"policyParametersType": "PersonTemplateParameters",
"firstName": "Jane",
"surname": "Doe",
"birthDate": "1980-05-20",
"customerReference": "CUST-12345"
}
6.32 create_data_product_order
Create standalone data product order
When to use. Run a single data product standalone — one KYC/AML search or report from one provider, without authoring a policy — by supplying a
serviceIdentifierfromlist_data_productsand the subject parameters, against either a new profile (customerReference) or an existing one (profileId). The created order is an ordinary policy order: after calling this, follow the same flow ascreate_policy_order—wait_for_policy_completion, thenget_policy_order/get_policy_sequences/get_policy_step/resolve_policy_stepas needed, including user-input-required resolution.
Input schema (summary).
serviceIdentifier(string, required) — fromlist_data_products; the same value is reported asserviceIdentifieron policy-order sequences.policyParametersType(required) — must be one of the type names the data product'sparameterTypeslists (fromlist_data_products); same options and per-type field rules ascreate_policy_order(see that entry for the full type-by-type field list,companyIdentifiers, andcompanyNumberType).- Exactly one of
customerReferenceorprofileIdmust be supplied.
Output shape. Single DataProductOrderResult — the 201 echo of the create request, with callerReferenceId and profileId assigned by ECPA (callers cannot supply their own callerReferenceId — there is no such input on this tool), plus serviceIdentifier, customerReference, and policyParameters.
Notable errors. Standard ECPA error envelope, plus tool-level validation errors as plain-text isError: true responses (missing customerReference/profileId, missing required parameter fields for the chosen policyParametersType — same messages as create_policy_order). An entitlement failure (HTTP 403) names the missing product(s) the account is not licensed for; a validation failure (HTTP 422) covers an unknown serviceIdentifier or a policyParametersType the product doesn't accept; an unknown profileId returns a not-found error (upstream wording calls profiles "workspaces"). On a deployment where standalone data products are not yet enabled, the tool returns isError: true explaining the feature has not been rolled out there — this is not an authentication or permission problem, and the call should not be retried.
Example.
{
"serviceIdentifier": "ASIC_ABR",
"policyParametersType": "CompanyTemplateParameters",
"companyName": "Telstra",
"customerReference": "CUST-12345"
}
6.33 get_policy_order
Get policy order
When to use. Retrieve the full order detail — status, dates,
profileId, originalpolicyParameters— after a policy has progressed. Typically called afterwait_for_policy_completionreports a terminal state, or whenever you need theprofileIdderived from the order.
Input schema (summary).
callerReferenceId(required) — fromcreate_policy_order.
Output shape. Single PolicyOrderResult (see create_policy_order).
Notable errors. Standard ECPA error envelope.
Example.
{ "callerReferenceId": "69e58759ca1d985769e7e29a" }
6.34 list_policy_orders
List policy orders
When to use. Discover policy orders that have already been created — by
profileId, lifecyclestatus, and/or creation-date window. Useful for resume / recovery flows where you have aprofileIdbut nocallerReferenceId, or for auditing which policies have run against a profile.
Input schema (summary).
offset,limit— pagination.profileId— restrict results to orders run against this profile.status— filter by lifecycle status. A single value (e.g.IN_PROGRESS) or a comma-separated list (e.g.IN_PROGRESS,ACTION_REQUIRED). Recognised values:ABORTED,ACTION_REQUIRED,COMPLETED,FAILED,IN_PROGRESS,MATCHES,NO_MATCHES,NO_RESULTS,PAUSED,RISK_IDENTIFIED(plus legacySUCCESS/REFER, not expected from the ECPA API v3.1 and this MCP server).UNKNOWNandUSER_SKIPPEDappear in results but are not accepted as filter values.dateCreatedStart,dateCreatedEnd— ISO-8601 date-time windows.
Output shape. Paginated PolicyOrderResult[] (per-item fields documented under create_policy_order / get_policy_order: callerReferenceId, status, policyIdentifier, profileId, policyParameters, dateCreated, dateStarted, dateCompleted, executionSummary, and, when recorded, partialFailure, failureReason and failureCode).
Notable errors. Standard ECPA error envelope.
Note on filters. When scoped by profileId the returned set is expected to be small (a single profile is rarely run against many policies), so post-filtering the returned array on a result field such as policyIdentifier is acceptable — but only when profileId is set; it does not license fetching unfiltered orders. Result ordering from the upstream endpoint is unspecified — there is no sort parameter and no documented default order.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da", "limit": 25 }
6.35 get_policy_step
Get policy step
When to use. Drill into a single step — in particular, retrieve
userInputRequired.optionsfor a step whose status isACTION_REQUIRED. The response also carriesautoResolutionPermitted, which governs whether you may select an option yourself or must present the candidates to the user and wait for their choice before callingresolve_policy_step— see that tool's entry for the full permission contract.
Input schema (summary).
callerReferenceId,sequenceId,stepId— all required, sourced fromget_policy_sequences.
Output shape. Single PolicySequenceStep — id, name, sequenceId, status, statusMessage, userInputRequired (with type discriminator SINGLE_ITEM_SELECTION | MULTIPLE_ITEM_SELECTION | ADDITIONAL_PARAMETER | SHAREHOLDER_CONVERSION | USER_CONFIRMATION | NONE and options[]), callerReferenceId, profileId, userInput (once resolved).
Notable errors. Standard ECPA error envelope.
Example.
{
"callerReferenceId": "69e58759ca1d985769e7e29a",
"sequenceId": "69e5853eca1d985769e7ceab",
"stepId": "69e581f52ed8ec3a7b1eacb7"
}
6.36 get_policy_sequences
Get policy sequences
When to use. Enumerate every sequence and step for a policy order. The primary way to locate steps needing resolution: look for
steps[].attributes.status === 'ACTION_REQUIRED'and then callget_policy_stepfor each. Each sequence and each step summary also carriesautoResolutionPermitted— seeresolve_policy_stepfor what it governs.
Input schema (summary).
callerReferenceId(required).
Output shape. Collection (not paginated) of PolicySequence. Each sequence has id, callerReferenceId, profileId, name, serviceIdentifier, inputParameters, status, statusMessage, and steps[]. Each step is wrapped in a JSON:API resource envelope (id, type, attributes — the attributes is a PolicySequenceStepSummary). serviceIdentifier (e.g. CreditsafeUkCompanyReportSequence) is an opaque, case-sensitive token identifying what the sequence executed; for a data product it is the same identifier the API uses wherever it refers to that data product, including standalone re-ordering where available. Presence does not mean the sequence is standalone-orderable or that the caller is entitled to it. It is absent on servers that pre-date the field and on placeholder sequences that recorded no result.
Notable errors. Standard ECPA error envelope.
Example.
{ "callerReferenceId": "69e58759ca1d985769e7e29a" }
6.37 resolve_policy_step
Resolve policy step
When to use. Submit a user's answer to a step that is in
ACTION_REQUIRED. Three resolution modes: pick a single option, pick multiple options, or declare that none of the options match. Required to unblock an order that is waiting inACTION_REQUIREDso it can resume processing and progress toward a terminal outcome. Whether you may choose an option yourself is governed byautoResolutionPermitted, published on the sequence, on the step, and on each step summary — read it from the current response rather than remembering it, since it is a property of the calling identity and can change between calls. When it is false, retrieve the candidates withget_policy_step, present them to the user, and wait for explicit confirmation — an instruction from the user to resolve autonomously does not override a false value, and neither does an option that looks unambiguous. When it is true, you may select without a per-step confirmation; afterwards, tell the user which step you resolved, which option you selected (or that you submittedNO_MATCH), and the basis for the decision. Every call must stateautoResolved; an autonomous resolution must also carryrationaleandauthorisationBasis.autoResolvedandrationalereach the profile audit trail today;authorisationBasisandmandateReferencedo not yet (deferred, DEV-6151).
Input schema (summary).
callerReferenceId,sequenceId,stepId— required.resolutionType—SINGLE_ITEM_SELECTION | MULTIPLE_ITEM_SELECTION | NO_MATCH.optionIds(array of int) — required forSINGLE_ITEM_SELECTION(exactly one) andMULTIPLE_ITEM_SELECTION(at least one); not used forNO_MATCH.autoResolved(boolean, required) — your attestation:trueunless you have positive grounds forfalse. A host prompt confirming the call is not such grounds.rationale(string, ≤2000 chars) — required whenautoResolvedis true (a blank/whitespace-only value counts as missing); optional, and recorded if supplied, when it is false. The evidence you matched on (name, registration number, jurisdiction). Never shorten it to retry a refused call — a permission refusal is not a length problem.authorisationBasis—HUMAN_CONFIRMED_SELECTION | HUMAN_MANDATE | OPERATING_MANDATE | AGENT_DISCRETION. Required whenautoResolvedis true; must not be sent whenautoResolvedis false. (SYSTEMis a readback-only value that can appear on a step you retrieve — a caller must never send it.)mandateReference(string, ≤500 chars, optional) — only valid alongsideauthorisationBasisHUMAN_MANDATEorOPERATING_MANDATE; sending it with any other basis is rejected. It is never required on its own — never send a fabricated reference to satisfy it.
Output shape. On success: { "resolved": true, "callerReferenceId": ..., "sequenceId": ..., "stepId": ... } (no structuredContent — this tool does not have an output schema).
Notable errors. Standard ECPA error envelope, plus tool-level validation: SINGLE_ITEM_SELECTION without exactly one optionId or MULTIPLE_ITEM_SELECTION without at least one optionId returns isError: true with an explanation. The resolutionType must also match the step's userInputRequired.type. A 403 (_meta.error: 'forbidden') means the calling identity was not permitted to perform this resolution — most commonly, an autonomous resolution attempted while autoResolutionPermitted is false. This is a permission failure, distinct from a 422 payload failure: do not retry, even with a shortened or altered rationale — stop and escalate to a human instead. Once the user has chosen, submit their selection with autoResolved: false and no authorisationBasis: the API accepts that call regardless of autoResolutionPermitted, and it is not a retry of the refused call.
Example. The payload below assumes autoResolutionPermitted is true for the calling identity — a permission set at the user and/or account level. Otherwise send the user's own choice with autoResolved: false and no authorisationBasis.
{
"callerReferenceId": "69e58759ca1d985769e7e29a",
"sequenceId": "69e5853eca1d985769e7ceab",
"stepId": "69e581f52ed8ec3a7b1eacb7",
"resolutionType": "SINGLE_ITEM_SELECTION",
"optionIds": [3],
"autoResolved": true,
"rationale": "Company name, registration number, and jurisdiction all match the profile's target entity.",
"authorisationBasis": "AGENT_DISCRETION"
}
6.38 wait_for_policy_completion
Wait for policy completion
When to use. After
create_policy_order(or afterresolve_policy_step), poll until the order reaches a terminal state or requires user input. This is the standard progress-monitoring primitive; prefer it over hand-rollingget_policy_orderpolling.
Input schema (summary).
callerReferenceId(required).maxWaitSeconds(int, 1-180, default 30) — polling window upper bound. Size it to the expected run: a full policy typically takes several minutes, so one call at 120-180 s replaces a chain of short polls. The tool returns no later thanmaxWaitSecondsafter it starts polling.pollIntervalMs(int, 2000-10000, default 3000) — between-check delay.
Output shape. Structured content { status, elapsedSeconds, isTerminal, lastError?, partialFailure?, failureReason?, failureCode? }. status is a policy-order status (IN_PROGRESS | ACTION_REQUIRED | PAUSED | COMPLETED | MATCHES | NO_MATCHES | NO_RESULTS | RISK_IDENTIFIED | FAILED | ABORTED | UNKNOWN, plus legacy SUCCESS / REFER / USER_SKIPPED, only returned for orders that pre-date the v3.1 policy statuses). isTerminal is true for truly terminal statuses; ACTION_REQUIRED returns with isTerminal: false so you know more input is needed, and UNKNOWN returns immediately with isTerminal: false — diagnose via get_policy_order/get_policy_sequences instead of re-polling. On orders carrying recorded failure detail the three failure fields are included; on FAILED orders check partialFailure — when true, completed data products' results remain available. If the window expires without a terminal state, the tool returns the last observed status with isTerminal: false — call again to keep waiting.
Notable errors. Transient EcpaApiError / EcpaTimeoutError during a poll are logged and the loop retries. If the window expires with no successful status read, the last error is surfaced via the standard ECPA error envelope. Per-poll status request timeout is 5 s.
Example.
{ "callerReferenceId": "69e58759ca1d985769e7e29a", "maxWaitSeconds": 30 }
6.39 Combined PDF
6.40 order_combined_pdf
Order combined PDF
When to use. Generate a single PDF combining some-or-all documents in a profile — the canonical evidence artefact for a compliance record. Returns immediately with a PDF resource whose
statusstarts atPENDING.
Input schema (summary).
profileId(required).documentIds(string array, optional) — omit to include all documents.includeToc,includeProfileRecord,includePurchaseHistory,includeAuditTrail,includeChartPdf— booleans.includeProfileRecordrequires a special subscription.
Output shape. Single CombinedPdfDocumentResource — id, profileId, documentIds, the include* flags, and status (PENDING | READY | ERROR).
Notable errors. Standard ECPA error envelope.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"includeToc": true,
"includeAuditTrail": true
}
6.41 get_combined_pdf
Get combined PDF status
When to use. Check the status of a previously ordered combined PDF, or retrieve its metadata. This tool returns metadata + status only — the bytes are fetched through the
combined_pdf_rawresource (see §7). For polling, preferwait_for_combined_pdf.
Input schema (summary).
profileId(required).id(required) — combined PDF ID fromorder_combined_pdf.
Output shape. Single CombinedPdfDocumentResource (see order_combined_pdf). When status === 'READY', fetch the bytes via the combined_pdf_raw resource URI.
Notable errors. Standard ECPA error envelope.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da", "id": "69e58759ca1d985769e7e29a" }
6.42 wait_for_combined_pdf
Wait for combined PDF
When to use. Poll a combined PDF order to
READY(orERROR). Mirrorswait_for_policy_completionin shape — call repeatedly ifisTerminalis false. Oncestatus === 'READY', fetch the bytes via thecombined_pdf_rawresource (see §7).
Input schema (summary).
profileId(required).id(required) — combined PDF ID fromorder_combined_pdf.maxWaitSeconds(int, 1-180, default 30).pollIntervalMs(int, 2000-10000, default 3000).
Output shape. Structured content { status, elapsedSeconds, isTerminal, lastError? }. status is PENDING | READY | ERROR. isTerminal is true for READY and ERROR; PENDING returns isTerminal: false when the window expires.
Notable errors. Transient EcpaApiError / EcpaTimeoutError are retried; a window that ends with no status read surfaces the last error via the standard ECPA error envelope. Per-poll status request timeout is 5 s. Timing defaults mirror wait_for_policy_completion; if typical PDF generation exceeds 30 s in practice, raise the defaults.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"id": "69e58759ca1d985769e7e29a",
"maxWaitSeconds": 30
}
6.43 Downloads
Each
download_*tool is a tool-call equivalent for the matching binary resource (see §7). The tool returns a short-lived signed download URL; the bytes are then retrieved by following the URL with a standard HTTPS GET. Use these tools when your MCP client surfaces tool calls but does not fetch resources directly — Claude Desktop and the claude.ai connectors are the canonical examples. Use the matching resource in §7 when your client does fetch resources (e.g. Claude Code).
All four download tools share the same response shape — a small URL envelope:
{
"download_url": "https://<server>/downloads/<token>",
"expires_at": "<ISO-8601 timestamp>",
"mime_type": "<MIME type>",
"suggested_filename": "<filename>",
"resource_uri": "ecpa://..."
}
The download_url is valid for ~5 minutes (DOWNLOAD_TOKEN_TTL_SECONDS, default 300) and may be reused within that window. The resource_uri echoes the sibling resource (§7) for clients that later want to switch paths. The /downloads/:token endpoint is mounted outside the bearer-auth chain — the 256-bit opaque token in the URL is the only authentication for retrieval, so the GET does not need an Authorization header. Per-download streaming is capped by DOWNLOAD_STREAM_MAX_BYTES (default 500 MB) — substantially larger than the 50 MiB inline-resource cap (§7), so the download path is the right choice for large profile archives.
6.44 download_profile_document
Download profile document
When to use. Tool-call equivalent of the
profile_document_rawresource (§7). Returns a signed URL to download a single document's bytes. Use afterlist_profile_documents/get_profile_documenthas told you which document you want.
Input schema (summary).
profileId(required).documentId(required) — fromlist_profile_documentsorget_profile_document.
Output shape. Download envelope (see preamble). mime_type is inferred from the document filename extension (commonly application/pdf, an image MIME type, or application/octet-stream as fallback).
Notable errors. Standard ECPA error envelope. Document IDs that do not exist surface as the upstream 404.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"documentId": "69e589e22ed8ec3a7b36b2c1"
}
6.45 download_combined_pdf
Download combined PDF
When to use. Tool-call equivalent of the
combined_pdf_rawresource (§7). Returns a signed URL to download a previously generated combined PDF. The combined PDF must already be instatus: 'READY'— runorder_combined_pdf→wait_for_combined_pdffirst.
Input schema (summary).
profileId(required).id(required) — combined PDF ID returned byorder_combined_pdf.
Output shape. Download envelope (see preamble). mime_type is application/pdf.
Notable errors. Standard ECPA error envelope. Calling before the combined PDF is READY surfaces as the upstream error.
Example.
{
"profileId": "69e589e22ed8ec3a7b2432da",
"id": "69e58759ca1d985769e7e29a"
}
6.46 download_profile_chart_pdf
Download profile chart PDF
When to use. Tool-call equivalent of the
profile_chart_pdfresource (§7). Returns a signed URL to download the profile's relationship / ownership chart as a PDF. The chart is rendered on demand by ECPA — no separate ordering or polling step is required.
Input schema (summary).
profileId(required).
Output shape. Download envelope (see preamble). mime_type is application/pdf.
Notable errors. Standard ECPA error envelope. Profiles without chartable entities surface as an upstream error.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da" }
6.47 download_profile_documents_zip
Download profile documents (zip)
When to use. Tool-call equivalent of the
profile_documents_zip/profile_documents_filtered_zipresources (§7). Returns a signed URL to download documents in a profile bundled into a single zip — every document with no filters, or a narrower bundle when filters are supplied. Useful for bulk evidence archival when the client cannot fetch resources directly. Capped byDOWNLOAD_STREAM_MAX_BYTES(default 500 MB); very large profiles may still need per-document downloads.
Input schema (summary).
profileId(required).kind,status,provider,entityId,dateCreatedStart/dateCreatedEnd,dateModifiedStart/dateModifiedEnd,includeUserAttachments,includePurchaseHistory,includeNoMatchReports,includeScreeningNoMatchReports— same filters aslist_profile_documents(see that entry for the discovery-tools rule, the attachment-exclusion caveat, and the screening carve-out).useDescriptiveFilenames— boolean; name the files inside the zip by their descriptive filename instead of the stored one. Does not by itself count as a filter (seeresource_uribehaviour below).
resource_uri behaviour. The result's resource_uri field names the sibling resource this mint corresponds to: ecpa://profiles/{profileId}/documents/all.zip only when the call sets none of the zip params at all (no filters and no useDescriptiveFilenames); as soon as any zip param is present — including useDescriptiveFilenames on its own, with no other filter — it becomes ecpa://profiles/{profileId}/documents/filtered.zip?<params>, the query string built from the params you passed (e.g. useDescriptiveFilenames alone yields .../filtered.zip?useDescriptiveFilenames=true). The filename marker is unaffected by this: it still only gains " (filtered)" when a genuine filter (something other than useDescriptiveFilenames) is present — a useDescriptiveFilenames-only call routes to the filtered.zip URI but keeps the plain, unmarked filename. Date filters accept ISO-8601; when embedding a value with a numeric UTC offset in a URI, percent-encode the plus (%2B) or use a Z/date-only form instead — an unencoded + decodes to a space and fails the resource's own validation.
Filename marker. The suggested filename ends in " (filtered)" whenever at least one genuine filter is present (any parameter other than useDescriptiveFilenames); with no filters it is the plain "<Profile> - documents.zip".
Output shape. Download envelope (see preamble). mime_type is application/zip.
Notable errors. Standard ECPA error envelope. Profiles whose total document size exceeds DOWNLOAD_STREAM_MAX_BYTES surface as a streaming error during the GET, not in the tool response itself. A filter set matching no documents is not an error: the download succeeds (HTTP 200) with a valid empty zip (a ~22-byte archive containing zero entries) — do not treat a tiny download as corruption.
Example.
{ "profileId": "69e589e22ed8ec3a7b2432da", "kind": "PASSPORT", "status": "READY" }
7 Resources
ecpa-mcp currently exposes five binary resources. They share consistent behaviour:
- Transport. Each resource returns the bytes as a single
blobcontent entry with the declared MIME type. HTTPRangerequests are supported end-to-end, so large payloads can be streamed or resumed. - Size limit. Downloads are capped at a server-configurable maximum (
ECPA_MAX_BINARY_DOWNLOAD_BYTES, default 50 MiB). Requests that exceed the limit fail fast with an error rather than streaming a truncated body. - Error handling. Upstream
EcpaApiError/EcpaTimeoutErrorare converted toProtocolError(InternalError) with the upstream message preserved — the same 404 / 413 / 5xx surfaces you would get calling ECPA directly, re-raised as MCP errors. Unknown errors propagate unchanged. - URI scheme. All resource URIs use the
ecpa://scheme with profile-scoped paths.
Prefer a resource over the equivalent metadata tool (get_profile_document, get_combined_pdf) whenever you want the raw bytes — the metadata tools return JSON descriptions while resources return the document content itself. For MCP clients that surface tool calls but do not fetch resources (e.g. Claude Desktop / the claude.ai connectors), §6 includes download_* tools that return short-lived signed URLs pointing at the same underlying bytes — pick the resource path when your client supports it, the download tool path when it does not.
7.1 profile_document_raw
Raw profile document — by profile & document ID
When to use. Download a single document's raw bytes in its default format. Use this after
list_profile_documents/get_profile_documenthas told you which document you want. The tool returns the metadata; the resource returns the file.
URI template. ecpa://profiles/{profileId}/documents/{documentId}/raw
MIME type. application/octet-stream (the underlying format depends on the document — commonly PDF, HTML, or image).
What you get. The document body in ECPA's default format for that document type, as a single binary blob.
Standard errors. Follows the shared binary-resource pattern described in the §7 preamble — 404 when the profile or document does not exist, 413 when the document exceeds ECPA_MAX_BINARY_DOWNLOAD_BYTES, upstream 5xx re-raised as InternalError.
7.2 combined_pdf_raw
Raw combined PDF — by profile & combined-PDF ID
When to use. Fetch the combined PDF bytes after
order_combined_pdf→wait_for_combined_pdfhas reachedstatus === 'READY'. This is the only way to retrieve the combined PDF body; the ordering/polling tools return metadata only.
URI template. ecpa://profiles/{profileId}/documents/combined-pdf/{id}/raw
MIME type. application/pdf
What you get. The combined PDF as a single binary blob. {id} is the combined-PDF identifier returned by order_combined_pdf.
Standard errors. Follows the shared binary-resource pattern described in the §7 preamble. 404 if the combined PDF has not been ordered / is not yet ready; 413 if the generated PDF exceeds the download limit.
7.3 profile_chart_pdf
Profile relationship/ownership chart PDF — by profile ID
When to use. Retrieve the relationship / ownership chart for a profile as a PDF. Generated on demand — no separate ordering step required. Use when you want a visual corporate-structure summary alongside the structured
get_profile_entitiesdata.
URI template. ecpa://profiles/{profileId}/documents/chart-pdf
MIME type. application/pdf
What you get. A freshly rendered PDF of the profile's relationship chart. No polling is required — ECPA generates the chart synchronously.
Standard errors. Follows the shared binary-resource pattern described in the §7 preamble. Profiles without chartable entities may return an upstream error; that is surfaced through the standard envelope.
7.4 profile_documents_zip
All profile documents as a zip — by profile ID
When to use. Bulk-download every document in a profile in a single request. Handy for evidence archival. Prefer
profile_document_rawper-document if you only need a subset — large profiles can easily exceed the 50 MiB download cap.
URI template. ecpa://profiles/{profileId}/documents/all.zip
MIME type. application/zip
What you get. A zip archive of all documents in the profile, using ECPA's server-side defaults for includeUserAttachments and useDescriptiveFilenames.
Standard errors. Follows the shared binary-resource pattern described in the §7 preamble. Profiles whose total document size exceeds ECPA_MAX_BINARY_DOWNLOAD_BYTES will return an error — either lift the server-side limit or fetch documents individually.
7.5 profile_documents_filtered_zip
Filtered profile documents as a zip — by profile ID + filters
When to use. Bulk-download only the documents in a profile matching given filters (kind, status, provider, entityId, date ranges, and the include* flags), bundled into a single zip. Prefer this over
profile_documents_zipwhen you only need a subset — narrower zips are smaller and faster.
URI template. ecpa://profiles/{profileId}/documents/filtered.zip{+query}
MIME type. application/zip
Query parameters (at least one required). kind, status, provider, entityId, dateCreatedStart/dateCreatedEnd, dateModifiedStart/dateModifiedEnd, includeUserAttachments, includePurchaseHistory, includeNoMatchReports, includeScreeningNoMatchReports, useDescriptiveFilenames. Unknown parameter names and duplicate keys are rejected, never ignored. Date values are ISO-8601; percent-encode + in UTC offsets (%2B) or use a Z/date-only form instead — an unencoded + is decoded to a space by query-string parsing and fails validation.
What you get. A zip archive of only the documents in the profile that match the supplied filters. A filter set matching no documents yields a valid empty zip (zero entries), not an error.
Strict validation. A read with no query string at all (bare filtered.zip) is served by a companion registration that always fails with guidance pointing at ecpa://profiles/{profileId}/documents/all.zip for the full unfiltered bundle. A query string present but empty (a bare trailing ?) fails with the same "at least one filter required" message.
Standard errors. Follows the shared binary-resource pattern described in the §7 preamble, plus the strict query validation above (InvalidParams) before any upstream call is made.
8 Prompts
The MCP server currently exposes a single prompt. Prompts return orchestration instructions for the AI client to execute — invoking a prompt does not run the workflow; it supplies a structured plan that the client then drives via tool calls.
8.1 run_policy
Run a compliance policy
When to use. Kick off an end-to-end compliance check where you want the assistant to handle policy discovery, order creation, polling, entity-resolution pauses, and result retrieval as a single coherent flow. Prefer the prompt over stitching the individual tools together yourself when you want the assistant to own the branching logic (ACTION_REQUIRED, PAUSED, non-terminal timeouts) and the closing summary. Use the raw tools directly when you need deterministic control or are embedding the calls in your own code.
Arguments. All optional; the prompt degrades gracefully as arguments are omitted. Provide as many as you know up front.
-
customerReference— unique reference that triggers creation of a new profile. Mutually exclusive withprofileId. -
profileId— run the policy against an existing profile. Mutually exclusive withcustomerReference. -
policyIdentifier— the policy to execute. If omitted, the prompt instructs the assistant to start withlist_policiesand pick / ask. -
policyParametersType— optionally pin the policy's input shape (one of the ninecreate_policy_ordertypes); if omitted the assistant infers it from the policy definition. -
Subject inputs mirror
create_policy_orderone-for-one, so any policy type can be pre-filled here:companyName,countryCode,companyNumber,subdivision,companyIdentifiers(a JSON object string, e.g.{"LEI":"5299000RWD2J46DMCW33"}— malformed JSON or non-flat values are ignored with a warning; entries with an empty type or value are dropped with a warning; discover the valid map keys for the instance withlist_company_identifier_types— informative only, unknown keys are ignored upstream, never rejected),companyIdentifier,companyIdentifierType,companyNumberType(VEDaaS),bvdId,firstName,surname,middleName,birthDate,personIdentifier, and the address fields (streetNumber,streetName,locality,country,postcode,addressLine1,addressLine2,zipCode,townCity,stateTerritory,streetLineAddress). All optional at the prompt layer; the assistant gathers any required-but-missing fields for the chosen type. Seecreate_policy_orderfor which fields each type requires. -
parameters— CLI slash-command affordance. A single URL query-string carrying any of the arguments above, e.g.policyIdentifier=...&policyParametersType=...&companyName=Acme+Corp&customerReference=CUST-1. Encode spaces as+or%20and percent-encode&,=,%(for JSON values such ascompanyIdentifiers, also percent-encode any literal+as%2B— a bare+decodes as a space). When supplied (and it yields at least one recognised field) it is the sole source of input — the individual arguments are ignored. Programmatic/named callers should use the individual arguments instead.Why it exists. Claude Code passes MCP-prompt slash-command arguments as whitespace-separated positional tokens (no quoting), so multi-word values — including policy identifiers that contain spaces — cannot be passed as individual arguments from the CLI.
parameterspacks everything into one space-free token. An un-encoded space silently truncates the blob (Claude Code splits before the prompt sees it, with no error), so the reliable workflow is to ask the assistant to build the encoded query-string for you, then paste the slash command.Examples.
- Policy only (assistant gathers the rest):
parameters=policyIdentifier=Authorised+Signatories+Extractor - Company:
parameters=policyIdentifier=pol-1&policyParametersType=CompanyTemplateParameters&companyName=Acme+Corp&countryCode=GB&customerReference=CUST-1 - Person:
parameters=policyIdentifier=pol-2&policyParametersType=PersonTemplateParameters&firstName=Jane&surname=Doe&customerReference=CUST-2
- Policy only (assistant gathers the rest):
What it returns. Two PromptMessages (one user, one assistant) that encode a six-step workflow: discover policies (if none specified) → create the policy order → poll to completion → resolve entity matches if ACTION_REQUIRED → fetch results in parallel (get_policy_order, get_profile, get_profile_entities, list_profile_documents, get_profile_data_sources) → present findings. The plan also references optional follow-ups: get_profile_news, get_profile_audit_trail, get_profile_purchases, and the combined-PDF path (order_combined_pdf → wait_for_combined_pdf → combined_pdf_raw resource).
Example call.
{
"prompt": "run_policy",
"arguments": {
"customerReference": "demo-acme-2026-04",
"companyName": "Acme Holdings Ltd",
"countryCode": "GB",
"policyIdentifier": "default_company_kyc"
}
}
9 End-to-end example
A realistic demo-path walkthrough, from a fresh client connection to a fully retrieved combined PDF. Each step lists the call in generic MCP tool-call JSON ({ "tool": "...", "arguments": { ... } }), as an equivalent example prompt and one sentence on what to look for in the response. Long identifiers and payload fields are elided as "..." for readability.
9.1 Connect the client and verify auth
Once your MCP client has authenticated against the ecpa-mcp server, confirm the plumbing with verify_auth before doing anything else. The response payload shape is documented in §4; if status is "failed", stop here and copy the full payload into a support ticket.
{ "tool": "verify_auth", "arguments": {} }
Look for "status": "succeeded" and a non-empty userSub. Any failure path at this step blocks every subsequent step.
9.2 list_profiles — find an existing subject (or confirm none match)
Narrow to a small, human-scannable subset. You can filter by name, by a recent creation window, or simply take the first page. The goal is to decide whether to reuse a profile or create a fresh one.
{
"tool": "list_profiles",
"arguments": {
"name": "Acme",
"limit": 10
}
}
Look at data[].id, data[].name, data[].dateCreated. If an existing profile is suitable, skip step 3 and pass its id as profileId in step 5.
9.3 create_profile — create a new subject
Only run this step if no existing profile matches. Use a stable customerReference — it's your side's idempotency key and shows up in support conversations.
{
"tool": "create_profile",
"arguments": {
"customerReference": "demo-acme-2026-04",
"name": "Acme Holdings Ltd"
}
}
Look for id in the response — that's the profileId you will use everywhere downstream. Subject-specific details like companyName/countryCode are not part of the profile itself; they are supplied later to create_policy_order (step 5).
9.4 list_policies — pick a policy definition
Fetch the policies available to your tenant and pick one whose policyParametersType matches your subject (a company-shaped type such as CompanyTemplateParameters or CompanyWithJurisdictionTemplateParameters, or a person-shaped type such as PersonTemplateParameters — see create_policy_order for the full list of supported types and their fields). When you already know roughly which policy you want, filter (name, identifier, description, parameterType, or a broad search) to narrow the list rather than paging all of it.
{ "tool": "list_policies", "arguments": { "name": "onboarding", "limit": 50 } }
Look for a policy's policyIdentifier (that's what step 5 passes to create_policy_order), its policyDescription to confirm it does what you expect, and its policyParametersType so the next step sends the correct subject fields.
9.5 create_policy_order — kick off execution
Bind the chosen policy to the profile from step 2 or step 3. Provide either customerReference (to create a new profile implicitly) or profileId (to run against an existing one) — never both.
{
"tool": "create_policy_order",
"arguments": {
"policyIdentifier": "company_onboarding_policy_xyz",
"policyParametersType": "CompanyWithJurisdictionTemplateParameters",
"profileId": "69e589e22ed8ec3a7b2432da",
"companyName": "Acme Holdings Ltd",
"countryCode": "GB"
}
}
Note: you could alternatively omit the profile ID but specify a custom reference to let the server create a new profile for you on-the-fly.
Look for callerReferenceId (threaded through every polling / resolution call) and profileId (confirm it matches the one you passed in).
9.6 wait_for_policy_completion
Poll the order. The tool blocks for up to maxWaitSeconds and returns the latest status. If isTerminal is false and status is not ACTION_REQUIRED, simply call it again — the polling tool is safe to re-invoke and does not lose state. If status === 'ACTION_REQUIRED', jump to step 8.
{
"tool": "wait_for_policy_completion",
"arguments": {
"callerReferenceId": "69e58759ca1d985769e7e29a",
"maxWaitSeconds": 30
}
}
Look at status and isTerminal. Terminal values (COMPLETED, MATCHES, NO_MATCHES, NO_RESULTS, RISK_IDENTIFIED, FAILED, ABORTED, legacy USER_SKIPPED) unlock step 7; ACTION_REQUIRED unlocks step 8; PAUSED means hold until a human decides what to do; UNKNOWN means stop polling and inspect the order directly.
9.7 Inspect with get_policy_order / get_policy_step / get_policy_sequences
Once terminal, pull the structured result. get_policy_order gives you the order-level status and decision. get_policy_sequences enumerates the sequences the policy ran. get_policy_step dives into a single step (useful both for diagnosis and for entity-resolution candidate inspection).
{
"tool": "get_policy_order",
"arguments": { "callerReferenceId": "69e58759ca1d985769e7e29a" }
}
Look for the final status and, for FAILED / ABORTED, any diagnostic fields on the order or on individual steps.
9.8 resolve_policy_step — only if a step needs user input
Skip this step entirely if no step returned ACTION_REQUIRED. Otherwise, for each unresolved step: call get_policy_sequences to find the unresolved steps, get_policy_step to retrieve the candidate entities and check autoResolutionPermitted, and then resolve each one. A human picks the match (or confirms none match) unless autoResolutionPermitted is true, in which case you may select the best-supported option yourself and report the resolution afterwards (step, option, basis).
The example below assumes autoResolutionPermitted is true for the calling identity — a permission set at the user and/or account level. Otherwise send the user's own choice with autoResolved: false and no authorisationBasis.
{
"tool": "resolve_policy_step",
"arguments": {
"callerReferenceId": "69e58759ca1d985769e7e29a",
"sequenceId": "69e5853eca1d985769e7ceab",
"stepId": "69e581f52ed8ec3a7b1eacb7",
"resolutionType": "SINGLE_ITEM_SELECTION",
"optionIds": [1],
"autoResolved": true,
"rationale": "Company name, registration number, and jurisdiction all match the profile's target entity.",
"authorisationBasis": "AGENT_DISCRETION"
}
}
resolutionType is one of SINGLE_ITEM_SELECTION, MULTIPLE_ITEM_SELECTION, or NO_MATCH. optionIds is an array of integers taken from get_policy_step's userInputRequired.options; omit it when resolutionType is NO_MATCH. autoResolved is mandatory on every call — true unless you have positive grounds for false. rationale (≤2000 chars) is required when autoResolved is true. authorisationBasis is one of HUMAN_CONFIRMED_SELECTION, HUMAN_MANDATE, OPERATING_MANDATE, or AGENT_DISCRETION, required when autoResolved is true and forbidden when it is false. mandateReference (≤500 chars) is optional and valid only alongside HUMAN_MANDATE or OPERATING_MANDATE — never send a fabricated reference to satisfy it.
Look for an acknowledgement and then go back to step 6; after resolution the policy resumes IN_PROGRESS and may yield further ACTION_REQUIRED pauses or a terminal outcome.
9.9 Combined PDF: order, wait, fetch
Unlike the earlier steps, this final step is a three-stage path made of three separate MCP calls — two tool calls (shown as JSON fences below) and a resource read (shown as a URI fence). When the policy has reached a terminal status and you want the full packaged evidence, run all three in order: order_combined_pdf kicks off generation and returns an id; wait_for_combined_pdf polls it to READY; the combined_pdf_raw resource returns the bytes.
{
"tool": "order_combined_pdf",
"arguments": { "profileId": "69e589e22ed8ec3a7b2432da" }
}
Then poll:
{
"tool": "wait_for_combined_pdf",
"arguments": {
"profileId": "69e589e22ed8ec3a7b2432da",
"id": "69e58759ca1d985769e7e29a",
"maxWaitSeconds": 30
}
}
Once status === 'READY', fetch the resource by URI — MCP-resource-capable MCP clients such as Claude Code expose this as a resource read, not a tool call. Note: MCP clients that cannot work with resources can fall back on the download_combined_pdf tool that exposes the document as a short-lived direct download link:
ecpa://profiles/69e589e22ed8ec3a7b2432da/documents/combined-pdf/cpdf_01H.../raw
Look for a blob content entry with mimeType: "application/pdf". You now have the full evidence PDF locally and the demo path is complete.
10 Errors & troubleshooting
10.1 Auth failures (HTTP 401 from the MCP server)
If the MCP server rejects your request outright it returns HTTP 401 with a WWW-Authenticate: Bearer resource_metadata="<base-url>/.well-known/oauth-protected-resource" header (per RFC 9728). That means the bearer token is missing, invalid, or scoped to the wrong audience. Common causes:
- Expired access token. Re-run your OAuth / M2M flow to mint a fresh one.
- Wrong
audienceparameter on the client-credentials grant (machine-to-machine integrations). The audience must exactly match the value Encompass supplied when your integration was provisioned. - Wrong Auth0 tenant. Double-check your client is configured against the Auth0 tenant Encompass supplied for your integration.
401s are returned before the request reaches any ECPA-backed tool. If you see one, do not retry with the same token — fix the credentials.
Tight loops trip a 429. If authentication keeps failing from the same source, repeated failures may respond with HTTP 429 (carrying Retry-After and X-Rate-Limit-* headers) instead of 401. The fix is the same — replace the broken token — but in-flight requests with the bad token will continue to receive 429 until the Retry-After window elapses. Honour Retry-After before retrying.
10.2 ECPA errors (isError: true inside a 200 response)
ECPA-backed tools use the standard ECPA error envelope (see §5). The MCP call itself returns HTTP 200 — the failure is encoded inside the MCP result:
isError: trueon the result.- A human-readable message in
content[0].text. For non-rate-limit failures this is"ECPA API error <status>: <detail>"for HTTP errors or"ECPA request timed out after Nms: …"for timeouts. For upstream 429s the text is an imperative wait instruction (see §10.4). - Structured
_metacarryingerror: 'rate_limited' | 'upstream_error' | 'upstream_timeout'plus per-category fields (status,tool,rule,retryAfterSeconds) — full schema in §5. - Schema-validation failures from ECPA return a distinct
"upstream response did not match expected schema: …"diagnostic listing up to 5 Zod issues (no_meta).
When an ECPA error appears, read content[0].text first — for non-rate-limit failures it contains the upstream HTTP status and message, which is what your ECPA support contact will ask for. For upstream 429s specifically, see §10.4 for the rate-limit shape and retry semantics.
10.3 verify_auth failure payload
On failure, verify_auth returns the structured diagnostic payload documented in §4 (includes status: "failed", userSub, the deployment identity fields, and error). Copy the payload verbatim into any support ticket — the error field in particular disambiguates Auth0-side failures (tenant config, audience, CTE) from downstream issues.
10.4 Rate limits and timeouts
Three classes of failures land here, with distinct shapes.
Upstream Encompass Public Automation REST API code 429 errors (rate-limited). The MCP call returns HTTP 200 with isError: true. The content[0].text is an imperative instruction the LLM is expected to honour:
"Upstream rate limit exceeded for tool 'X' (ECPA API). You MUST wait at least N seconds before retrying. Retrying sooner will be rejected with the same response. Continue with other work or report the rate limit to the user; do not retry sooner."
_meta carries the structured payload: { error: 'rate_limited', rule: 'ecpa-upstream', retryAfterSeconds: <int>, tool: '<name>' }. Programmatic clients should read retryAfterSeconds from _meta and wait at least that long before retrying; LLM-driven clients will follow the imperative wait instruction in the text content. rule: 'ecpa-upstream' identifies the throttle source as the ECPA upstream API.
MCP server's own rate limit. Separately from the upstream, this server applies its own rate limiting to incoming MCP calls. When a budget is exhausted, the call returns HTTP 200 with the same Annex A shape as the upstream-429 case — isError: true, the imperative wait message in content[0].text, and _meta: { error: 'rate_limited', rule: <string>, retryAfterSeconds: <int>, tool: '<name>' }. The only fields integrators need to act on are retryAfterSeconds (wait at least that long before retrying) and _meta.error: 'rate_limited' (to recognise the category). The rule value is 'ecpa-upstream' when the throttle comes from Encompass's upstream API (above); any other value indicates this server's own throttle — treat it as an opaque identifier whose specific value may change between releases.
Requests to the discovery endpoints under /.well-known/* may instead respond with a real HTTP 429 plus standard Retry-After and X-Rate-Limit-* headers — not the in-body shape described above. Authenticated /mcp traffic is unaffected by this. Repeated authentication failures from a single source can likewise respond with HTTP 429 instead of 401 (see §10.1).
Malformed or unsupported requests (HTTP 4xx from the MCP server, or a JSON-RPC error). These are answered by the MCP server itself, before any ECPA call, so they never carry the ECPA error envelope:
- A
tools/callnaming a tool that does not exist (e.g. a misspelt name) is answered with a JSON-RPC error object, code-32602(Invalid params), inside an HTTP 200, rather than aCallToolResultwithisError: true. Treat both shapes as "the call failed"; check the tool name againsttools/list. - Request bodies over 1 MB are refused with HTTP 413 and a JSON-RPC envelope (
error.code -32600); no legitimate MCP request approaches this, i.e. binary uploads use the separate upload URL. - A body that is not valid JSON is HTTP 400 with
error.code -32700; an empty body, or one that is not a JSON-RPC message, is HTTP 400 witherror.code -32600. Content-Type: application/jsonwith a charset other than UTF-8, or a compressed (Content-Encoding) body, is HTTP 415 witherror.code -32600. Send plain UTF-8 JSON.
Other ECPA errors (non-2xx, timeouts). Surface through the standard ECPA error envelope (see §5):
EcpaApiError— ECPA returned a non-2xx;content[0].textincludes the status and upstream message;_meta.error: 'upstream_error'withstatusandtool.EcpaTimeoutError— the request exceeded the client-side timeout;_meta.error: 'upstream_timeout'withtool. Retry policy is caller-driven.
For the polling tools (wait_for_policy_completion, wait_for_combined_pdf) a non-terminal result means the underlying ECPA operation did not complete within maxWaitSeconds — it does not indicate a failed operation. Call the polling tool again with the same arguments; state is server-side and nothing is lost between polls.
The polling tools never fail on their own timeout: window expiry always returns a status with isTerminal: false. If a wait call instead ends in a timeout or connection error, the client or something on the network path cut the request before the window finished (every MCP client applies its own tool-call timeout, and some hops do too). Retry with a smaller maxWaitSeconds, e.g. halve it, and keep it there for the rest of the session. The 30 s default is safe on every client we know of. The server stops polling as soon as it notices the client has gone.
10.5 Download links that return 404
The download_* tools return a short-lived download_url (the expires_at timestamp is included in the response envelope; links may be reused within that window — see download_profile_document in §6 for the full envelope shape). A plain HTTP 404 with { "error": "not_found" } from /downloads/<token> means the link has expired or is unknown to the server.
Expired links are not recoverable — re-run the download tool to mint a fresh URL, then fetch it promptly.
10.6 Order stuck in ACTION_REQUIRED
A policy order in ACTION_REQUIRED is waiting for user input — it will not progress regardless of how long you poll. Whether the assistant may resolve the blocked steps itself is governed by autoResolutionPermitted (see resolve_policy_step) rather than anything said in the conversation; when it is false, resolve them by presenting the candidates to the user instead.
Call get_policy_sequences to list the order's steps, then for each step with status: "ACTION_REQUIRED" call get_policy_step to retrieve the candidate options and check autoResolutionPermitted, then resolve_policy_step to submit the selection (or NO_MATCH if none match) along with the mandatory autoResolved attestation. A 403 from resolve_policy_step means the calling identity was not permitted to resolve autonomously — stop and escalate to a human rather than retrying. Once the user has chosen, submit their selection with autoResolved: false and no authorisationBasis: the API accepts that call regardless of autoResolutionPermitted, and it is not a retry of the refused call. Once every blocked step is resolved, call wait_for_policy_completion again to resume monitoring.
11 Support & next steps
11.1 Reporting issues
Email support@encompasscorporation.com — the standard support entry point for Encompass production systems — with questions, bug reports, and feature requests. Include the details below to speed up triage.
11.2 What to include in a support ticket
The more of the following you include up front, the faster the turnaround:
- The full
verify_authresponse payload (especially on auth problems — theerrorfield is load-bearing). - The MCP response body from the failing tool call, including the
isErrorflag andcontent[0].text. - A request-id from the response headers, or from your self-hosted server logs if running locally (filter by
userSub+ timestamp if you don't have the id directly). - A UTC timestamp for when the failure occurred.
- A one-line description of what you were trying to do, including the tool name and relevant IDs (
profileId,callerReferenceId).
Important: Do not paste bearer tokens or client secrets — they are never needed to triage an issue.
11.3 Further reading
- ECPA API documentation — the upstream REST reference. Reachable with the same Encompass credentials used for MCP authentication; your Encompass contact can point you at the current URL for your specific environment if you do not already have it bookmarked.
- Other Encompass developer resources — contact Encompass for access to additional developer resources, SDK samples, and onboarding material appropriate to your use case.