> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Didit MCP: avançat, resolució i autoallotjament

> Didit MCP avançat: rols i permisos, catàleg allotjat, fluxos amb branques, webhooks, resolució de problemes i autoallotjament.

## Àmbits i permisos de rol

El connector funciona amb els àmbits `didit:management` i `didit:verification` (un tercer, `didit:staff`, s'anuncia però només té efecte per als comptes del personal de Didit). Els dos límits s'apliquen en cada crida: el token porta els àmbits que has aprovat i **dins d'aquests àmbits, el teu rol a la consola decideix què pots fer**. L'accés efectiu és la intersecció, de manera que aprovar només `didit:verification` manté la superfície de gestió tancada fins i tot per a un `OWNER`.

Cada eina correspon a un permís del backend (`read:sessions`, `write:workflows`, `delete:lists`, etc.; la [referència d'eines](https://docs.didit.me/ca/integration/mcp/tools.md) el detalla per eina). El servidor verifica prèviament aquest permís amb els permisos de l'organització que retorna la introspecció del token; aquest control està determinat per `MCP_PERMISSION_MODE`:

| Mode | Comportament |
| - | - |
| `shadow` (per defecte) | Totes les eines apareixen a la llista; una crida que el teu rol no pot fer va al backend, que respon `403`. El veredicte queda registrat al registre d'auditoria del servidor. |
| `enforce` | Les eines que el teu rol no pot executar s'ometen de `tools/list`; si en crides una, es retorna un error `missing_scope` que indica el permís. |
| `off` | Sense verificació prèvia. |

L'MCP mai va més enllà del teu rol. Un `403` en una eina vol dir que el teu rol no té aquell permís, no que hagi fallat tota la connexió.

***

## Resolució entre aplicacions i organitzacions

L'API de gestió de Didit té l'àmbit per aplicació (`/organization/{org}/application/{app}/…`). El MCP resol l'àmbit per tu:

* **Una sola organització + aplicació** → es resol automàticament; mai no passes IDs.
* **Diverses aplicacions** → les eines entre aplicacions (`didit_session_search`, `didit_transaction_search`, `didit_case_search`, `didit_vendor_user_search`, `didit_vendor_business_search`, `didit_workflow_search`, `didit_analytics`) agreguen **totes** les aplicacions en una sola crida, i cada fila està etiquetada amb el seu `organization_id` / `application_id`.
* Les eines de llista per aplicació (`didit_session_list`, `didit_transaction_list`, `didit_case_list`, `didit_vendor_user_list`, `didit_vendor_business_list`, `didit_workflow_list`) **abasten totes les aplicacions** automàticament quan no n'especifiques cap, de manera que una petició simple com «llista les meves sessions» funciona fins i tot amb moltes aplicacions. Passa `organization_id` + `application_id` per restringir-ho a una sola aplicació.

Fes servir `didit_context_get` per veure totes les teves organitzacions i aplicacions (i els seus IDs) en una sola crida. També informa del `mode` de cada aplicació (`live` o `sandbox`), així que mai no dedueixis l'entorn pel nom d'una aplicació. `didit_session_create` accepta un `sandbox_scenario` a les aplicacions sandbox per a proves sense facturació.

***

## Què conté el catàleg allotjat

El connector allotjat et dona **169 eines**. També llista 17 eines de l'Investigator, que només funcionen un cop l'Investigator està habilitat per a la teva organització. Dues eines més, `didit_org_top_up` (procés de pagament de Stripe) i `didit_org_reveal_application_api_key` (secret en brut), queden ocultes del `tools/list` de tots els clients autenticats amb OAuth. Les cinc eines de configuració del compte (`didit_account_*`) s'exclouen completament dels servidors remots i no s'executen allà, perquè un connector remot no ha de rebre mai credencials com a arguments d'eina. Un servidor stdio local les conserva totes, 193 en total.

Cada eina llistada porta anotacions MCP (`readOnlyHint`, `destructiveHint`, `openWorldHint`, un `title`) i un `outputSchema`, i una etiqueta `_meta["anthropic/toolGroup"]` que indica la seva àrea (Sessions, Workflows i Questionnaires, Transaccions (AML), etc.). Clients com Claude fan servir les anotacions per separar les eines del connector en grups d'eines de només lectura, d'escriptura i destructives.

***

## Branques de flux de treball

Els flux de treball senzills són una llista plana de funcionalitats. Per a la **lògica condicional** (rebutjar segons un estat, encaminar segons un camp extret, condicionar un pas a una coincidència o afegir una sol·licitud de Document AI), el MCP fa servir el **graf de nodes** de Didit (la mateixa estructura que el constructor visual de la consola). Un graf és `{ start_node, nodes }`, i cada node és una `feature`, una `branch`, un `status` (terminal), una `action` o un `webhook`. Les regles de branca admeten operadors com **`fuzzy_match`** (per a camps de text, amb un llindar de similitud `score` de 0 a 100) sobre camps extrets com `kyc.extra_fields.profession`, i un node de funcionalitat `DOCUMENT_AI` sol·licita documents (p. ex., comprovant de fons).

### Edició d'un flux de treball existent (recomanat)

Els flux de treball reals porten configuracions de funcionalitat **molt grans**: una llista de documents permesos (`documents_allowed`) d'OCR pot ocupar 150 KB o més, a més de les llistes de POA i de països per als telèfons. Per tant, **no** llegeixis el graf complet per tornar-lo a enviar. Edita'l amb **operacions** petites:

**1. Localitza i inspecciona**

`didit_workflow_search { workflow_id }` el troba en totes les teves aplicacions. `didit_workflow_get_graph` retorna l'estructura amb les configuracions grans **resumides** (mai no es desborda; passa `include_config: true` per obtenir els valors bruts). `didit_workflow_get_field_definitions` enumera els camps que es poden fer servir en branques i els operadors vàlids.

**2. Edita amb operacions**

`didit_workflow_edit_graph` rep unes quantes operacions petites (`set_next`, `set_node`, `set_branches`, `merge_node_config`). El MCP obté el graf complet al servidor, aplica les operacions, valida el resultat, crea automàticament un **esborrany** i el desa. Les teves llistes de permesos es conserven byte a byte i mai no passen per la sol·licitud. Si la validació falla, retorna `applied: false` (no es desa res).

**3. Revisa i publica**

Es manté com a esborrany revisable fins que facis `publish` (a la consola o amb `didit_workflow_publish`). La versió activa mai no es modifica.

Per exemple, per inserir una branca després de la verificació d'identitat que **torni a la teva cadena existent**, només cal enviar: reconnectar el `next` del node OCR a una branca nova, i afegir la branca, un node terminal `Declined` i un pas `DOCUMENT_AI` (el `next` del qual apunta de nou al pas següent original). Els altres 10 nodes, juntament amb les seves llistes de permesos, no es toquen.

> *"Després de la verificació d'identitat, si ha estat rebutjada, rebutja; si la professió ≈ 'Software Engineer' (≥80%), sol·licita comprovant de fons; després continua."* → un únic node `branch`: `kyc.status == Declined` → un node d'estat `Declined`; `kyc.extra_fields.profession` `fuzzy_match` "Software Engineer" amb puntuació 80 → un node `DOCUMENT_AI` de comprovant de fons → i un camí **else** que torna a la cadena.

> [!NOTE]
>
> **Una branca sempre necessita una branca else explícita.** La ruta de captura general (la que es segueix quan no coincideix cap condició) ha de ser una branca amb el camp `rules` buit, per exemple `{ "id": "else", "rules": [], "goto": "<liveness>" }`, i no el `next` simple del node de branca. El MCP (i el backend) converteixen automàticament el `next` d'un node de branca en una branca else, de manera que una branca mai no es mostra com una aresta ambigua sense un else visible.

Per crear un flux de treball nou des de zero, fes servir `didit_workflow_validate_graph` i després `didit_workflow_set_graph` (graf complet), o deixa que `didit_workflow_build_graph` munti un graf complet a partir d'una especificació simple de funcionalitats sense desar-lo. Fins i tot un `didit_workflow_create` simple es desa com aquest mateix graf de nodes: el MCP converteix la teva llista `features` en nodes de funcionalitat encadenats que acaben en un estat de decisió automàtica, perquè les funcionalitats s'executin realment (per defecte es publica; passa `status: "draft"` per mantenir-lo sense publicar). Consulta [Crear flux de treball → branques i flux de treball basats en nodes](https://docs.didit.me/ca/management-api/workflows/create.md) per veure l'estructura JSON completa.

### Branques de motiu d'omissió de NFC amb el MCP

Per a un graf nou, demana:

> *"Crea un flux de treball en esborrany amb la verificació d'identitat seguida de NFC. Si `nfc.skip_reason` és `DEVICE_WITHOUT_NFC` o `DOCUMENT_WITHOUT_CHIP`, envia la sessió a En revisió; en cas contrari, aprova-la. Mantén una branca else explícita i valida el graf abans de desar-lo."*

L'agent hauria de cridar `didit_workflow_get_field_definitions`, `didit_workflow_validate_graph` i després `didit_workflow_set_graph`. Per a un flux de treball existent, demana:

> *"Edita el flux de treball `26d33c04…`: després del seu node NFC, envia qualsevol dels set valors coneguts de `nfc.skip_reason` a En revisió, i conserva el camí d'NFC satisfactori existent com a else explícit. Desa un esborrany; no el publiquis."*

L'agent hauria de cridar `didit_workflow_search`, `didit_workflow_get_graph`, `didit_workflow_get_field_definitions` i després `didit_workflow_edit_graph`. L'eina d'edició aplica operacions petites al servidor, de manera que conserva els nodes no relacionats i les llistes de permesos grans. Consulta [Crear flux de treball → Branca segons per què no s'ha executat NFC](https://docs.didit.me/ca/management-api/workflows/create.md#branca-segons-per-què-no-s’ha-executat-nfc) per veure els set valors, les regles `equals`/`in`, el comportament amb null i un graf ordenat complet.

### Configuracions de funcionalitats i llistes de permesos

La `config` d'un node de funcionalitat restringeix el que accepta. `didit_workflow_get_feature_config_schema` retorna totes les claus que accepta cada funcionalitat, amb tipus i valors per defecte, i les dues eines de catàleg (`didit_workflow_get_id_verification_methods_catalog` i `didit_workflow_get_kyb_registry_catalog`) responen les preguntes, determinades pel servidor, de les quals depèn una configuració. La llista de permesos OCR canònica és per país → per document → objecte: `{ "<ISO3>": { "<CODE>": { "enabled": 1 } } }` (p. ex., `{ "ESP": { "P": { "enabled": 1 } } }`). El MCP **normalitza formats més senzills** per a tu abans de validar, de manera que no cal que escriguis a mà aquesta estructura:

| Pots passar | Es normalitza a |
| - | - |
| Una llista de tipus de document: `["PASSPORT"]` | aquest document per a **tots** els països (només passaport a tot el món) |
| **Noms** o **codis** de document: `PASSPORT`/`P`, `NATIONAL_ID`/`ID`, `DRIVER_LICENSE`/`DL`, `RESIDENCE_PERMIT`/`RP` (també `SSC`, `HIC`, `TC`) | el codi canònic |
| Una clau de país `"ALL"`: `{ "ALL": { "P": 1 } }` | aplicat a tots els països |
| Indicadors escalars: `{ "ESP": { "P": 1 } }` | `{ "ESP": { "P": { "enabled": 1 } } }` |
| Omès completament | tots els documents, tots els països |

`poa_languages_allowed` de `PROOF_OF_ADDRESS` funciona igual: passa una llista d'idiomes (`["es"]`) o un mapa (`{ "es": 1 }`). Aquestes facilitats s'apliquen a tot arreu on donis al MCP una configuració de funcionalitat: les funcionalitats de `didit_workflow_create`, i les `config` dels nodes a `set_graph`, `edit_graph` i `validate_graph`.

***

## Forma de la resposta (contracte V3)

Cada eina retorna el JSON literal de l'endpoint REST subjacent. Hi ha dues coses a tenir en compte:

* **Les eines síncrones** (fluxos de treball, facturació, `verify_*` independents i gestió de llistes) retornen el resultat final en línia: actua-hi en el mateix torn.
* **La creació de sessions és asíncrona**: `didit_session_create` retorna una `url` on l'usuari ha de completar el procés; la decisió arriba per webhook o mitjançant `didit_session_get_decision`.

Les claus de decisió són **sempre matrius en plural** amb un `node_id` per entrada (`id_verifications[]`, `liveness_checks[]`, `face_matches[]`, `aml_screenings[]`, `poa_verifications[]`, `phone_verifications[]`, `email_verifications[]`, `database_validations[]`, `reviews[]`, i, per a KYB, `registry_checks[]`, `document_verifications[]`, `key_people_checks[]`). Consulta [Models de dades](https://docs.didit.me/ca/reference/data-models.md) i [Estats de verificació](https://docs.didit.me/ca/integration/verification-statuses.md).

***

## Gestió dels webhooks

Fes que un webhook lliuri la decisió final al teu backend en lloc de sondejar des de l'agent:

1. L'agent crida `didit_webhook_create` una sola vegada amb un `label`, la teva `url` HTTPS pública, `webhook_version: "v3"` i `subscribed_events` (normalment `["status.updated", "data.updated"]`). La resposta oculta el secret de signatura, igual que `didit_webhook_get` i `didit_webhook_list`; copia'l des de **Webhooks** a la consola i desa'l com a `DIDIT_WEBHOOK_SECRET`.
2. El teu backend verifica la capçalera canònica **X-Signature-V2** a cada lliurament: `shortenFloats` → `sortKeys` → `JSON.stringify` (unicode sense escapar) → HMAC-SHA256 → `timingSafeEqual`. Rebutja la petició si `abs(now − X-Timestamp) > 300` segons.
3. Deduplica pel `event_id`. Retorna `2xx` dins de **5 segons**; mou el treball pesat a una cua.
4. Didit reintenta en cas de `5xx` / `404` fins a **2 vegades** (\~1 min, després \~4 min) i, després, descarta el lliurament; torna a enviar els lliuraments fallits des de la pestanya **Lliuraments** de la consola.

L'agent només necessita *configurar* el receptor; ell mateix no escolta. Contracte complet: [Webhooks](https://docs.didit.me/ca/integration/webhooks.md).

***

## Transport i endpoints

| Endpoint | Finalitat |
| - | - |
| `POST https://mcp.didit.me/mcp` | L'endpoint MCP (Streamable HTTP). `GET` i `DELETE` responen `405`: el servidor no té estat, crea una nova instància de servidor per cada petició i no manté cap flux iniciat pel servidor ni cap sessió iniciada pel servidor que s'hagin de tancar. |
| `GET https://mcp.didit.me/healthz` | Comprovació de salut: `{ "status": "ok", "service": "didit-mcp-server", "version": "5.1.1" }`. |
| `GET https://mcp.didit.me/.well-known/oauth-protected-resource/mcp` | Metadades del recurs protegit RFC 9728 (també servides a l'arrel de l'origen). |

L'endpoint és compatible amb dues èpoques del protocol: els clients que fixen una versió del protocol 2026-07-28 o posterior a cada missatge ometen l'intercanvi inicial `initialize` i poden cridar `server/discover`; tots els clients anteriors (Claude Code, Cursor, clients basats en SDK) fan servir l'intercanvi inicial estàndard de Streamable HTTP sense canvis. CORS està obert, de manera que els clients basats en navegador (el connector web de Claude, MCP Inspector) poden accedir a `/mcp` i als documents de descobriment des d'altres orígens. El límit del cos JSON és de 25 MB, prou per a una entrada de fitxer en base64 de 15 MB.

***

## Resolució de problemes

> [accordion] L'agent crida una eina i obté un 403 o missing\_scope
>
> El teu **rol** en aquesta organització no té el permís que necessita l'eina (per exemple, un `READER` que intenta una escriptura); l'error `missing_scope` indica quin és. Si fallen totes les eines, torna a connectar o torna a executar *Log in with Didit*. (El MCP només admet Bearer/OAuth: un `x-api-key` és rebutjat per totes les eines, de manera que una clau d'API no soluciona un 403.)

> [accordion] Una escriptura o eliminació no s'ha executat
>
> Les eines destructives requereixen confirmació al teu client. Aprova la crida o comprova que la sol·licitud de confirmació de l'eina no es rebutja automàticament. `didit_session_delete`, `didit_session_batch_delete` i `didit_org_reveal_application_api_key` necessiten a més `confirm: true` als arguments de l'eina; sense això, la crida es rebutja abans que s'executi res.

> [accordion] 'organization\_id is required' o cap resultat
>
> Probablement tens diverses aplicacions. Utilitza una eina `*_search` (que abasta totes) o executa `didit_context_get` i passa el `organization_id` / `application_id` que vols.

> [accordion] El navegador no s'ha obert per iniciar sessió (allotjat)
>
> Alguns clients (Windsurf, Zed) es connecten mitjançant el pont `mcp-remote`: assegura't que `npx -y mcp-remote@latest https://mcp.didit.me/mcp` és a la configuració. Torna a obrir el client per tornar a activar l'intercanvi OAuth.

> [accordion] Les eines no apareixen al client
>
> Confirma que el servidor s'ha connectat (la majoria de clients mostren un punt d'estat) i que has completat *Log in with Didit*. Reinicia l'amfitrió MCP després d'editar la seva configuració. `didit_org_top_up` i `didit_org_reveal_application_api_key` mai no apareixen al connector allotjat.

> [accordion] VS Code (o un altre client) no pot descobrir OAuth / no obre mai un navegador
>
> Assegura't que apuntes a `https://mcp.didit.me/mcp`, no a l'origen sense la ruta `https://mcp.didit.me`: les metadades del recurs es serveixen a `/.well-known/oauth-protected-resource/mcp`, limitades a aquesta ruta (amb una còpia a l'arrel de l'origen per als clients que hi busquen). Si autoallotges el servidor, això sol voler dir que `MCP_RESOURCE_URI` està definit a l'origen en lloc de la URL completa del transport; consulta [Autoallotjament](#autoallotjament).

> [accordion] Una pujada de fitxer és rebutjada
>
> A l'endpoint allotjat, envia el fitxer com a `*_base64` (base64 en brut o una URL `data:`); `*_path` només funciona en un servidor stdio local. Els fitxers estan limitats a 15 MB i han de ser PNG, JPG, WebP, GIF, BMP, ICO o PDF segons el contingut, no només per l'extensió.

***

## Seguretat

El MCP actua amb els teus permisos reals i pot modificar recursos en producció. Mantén activada l'opció **"review tool calls before running"** al teu client, especialment per a les eines **Write** i **Destructive**. El propi MCP no emmagatzema **cap secret** a la teva configuració (utilitza **Iniciar sessió amb Didit**), oculta les claus d'API i els secrets de signatura dels webhooks a la sortida de les eines, amaga les eines de recàrrega i de clau en brut del catàleg allotjat, i mai accepta credencials del compte com a arguments d'eina en un servidor remot. Cada crida d'eina queda registrada al registre d'auditoria del servidor amb qui fa la crida, l'eina i el veredicte de permisos.

### Injecció d'instruccions

Les eines de Didit retornen el que els teus usuaris han escrit o pujat, com ara noms, text de documents i respostes de qüestionaris.
La persona que es verifica controla aquest text, de manera que pot escriure instruccions dirigides al teu agent en un nom o en un document, i el servidor retorna aquests camps tal com s'han capturat.
Un agent no pot distingir de manera fiable aquest text de les teves pròpies instruccions, així que tracta cada resultat d'eina com a dades:

* Mantén l'aprovació d'eines activada per a les eines **Write** i **Destructive**, i llegeix què està a punt de fer l'agent abans d'aprovar-ho.
* Inicia sessió com a membre amb un rol adequat a la feina. Un agent que només llegeix sessions pot utilitzar un membre `READER`, i el backend rebutja les seves escriptures facin el que faci l'agent.
* Prova primer un agent o una instrucció nova en una [aplicació sandbox](https://docs.didit.me/ca/integration/sandbox-testing.md).
* Mai aprovis ni rebutgis una verificació perquè el text que hi ha dins ho indiqui. Basa't en la decisió, en les advertències i en la teva pròpia revisió.

### Dades personals

Els resultats de les eines poden incloure dades personals, com ara noms, dates de naixement, números de document i enllaços a imatges, i el teu client MCP els envia al model que utilitza.
Abans de connectar una aplicació en producció, comprova que el teu acord amb el proveïdor d'IA cobreix aquestes dades, o treballa en una aplicació sandbox.

***

## Autoallotjament

El servidor allotjat es construeix a partir de [github.com/didit-protocol/mcp](https://github.com/didit-protocol/mcp) (MIT). Clona'l i executa'l amb **Docker** o Node; sempre autentica com a **usuari** de Didit (no hi ha mode de clau d'API), en qualsevol dels dos transports. Els passos de configuració són a [Instal·lació → autoallotjament](https://docs.didit.me/ca/integration/mcp/installation.md#autoallotjament).

```bash theme={null}
git clone https://github.com/didit-protocol/mcp.git && cd mcp

# Docker (recommended) — serves /mcp + /healthz on port 3000
docker build -t didit-mcp . && docker run -p 3000:3000 --env-file .env didit-mcp

# …or with Node
npm install && npm run build
node dist/http.js                                          # hosted HTTP/OAuth
DIDIT_ACCESS_TOKEN=<user-access-token> node dist/index.js  # stdio (headless)
```

### Variables d'entorn

| Variable | Mode | Finalitat |
| - | - | - |
| `DIDIT_ACCESS_TOKEN` | stdio | El token d'accés Bearer de l'usuari per a execucions sense interfície. |
| `DIDIT_API_BASE_URL` | ambdós | Base de l'API de verificació (per defecte `https://verification.didit.me/v3`). |
| `DIDIT_AUTH_BASE_URL` | ambdós | Base de l'API d'autenticació (per defecte `https://apx.didit.me/auth/v2`). |
| `MCP_PORT` | allotjat | Port d'escolta HTTP (per defecte `3000`). |
| `MCP_RESOURCE_URI` | allotjat | URL pública del transport, incloent-hi el camí (per exemple `https://mcp.example.com/mcp`). La URL de metadades RFC 9728 es deriva d'aquesta. |
| `MCP_AUTHORIZATION_SERVER_ORIGIN` | allotjat | Origen del servidor d'autorització (per defecte `https://business.didit.me`). |
| `MCP_TOKEN_VERIFY_MODE` | allotjat | `introspection` (per defecte; tokens opacs) o `jwks` (tokens d'accés JWT). |
| `MCP_OAUTH_INTROSPECT_URL` | allotjat | Endpoint d'introspecció RFC 7662. |
| `MCP_OAUTH_CLIENT_ID` / `MCP_OAUTH_CLIENT_SECRET` | allotjat | Credencials d'autenticació bàsica que el servidor de recursos utilitza per cridar l'endpoint d'introspecció. Proporciona-les des d'un gestor de secrets. |
| `MCP_SCOPES_SUPPORTED` | allotjat | Àmbits anunciats a les metadades (per defecte `didit:management didit:verification`). |
| `MCP_DEFAULT_ORG` / `MCP_DEFAULT_APP` | ambdós | Omple automàticament l'àmbit per a desplegaments d'un sol inquilí. |
| `DIDIT_AUTH_ISSUER`, `DIDIT_OIDC_DISCOVERY_URL`, `DIDIT_OIDC_AUTHORIZE_URL`, `DIDIT_OIDC_TOKEN_URL`, `DIDIT_OIDC_REGISTRATION_URL` | allotjat | Sobreescriptures de les metadades del servidor d'autorització; només cal si publica els seus endpoints en un lloc diferent dels valors per defecte de l'origen. |
| `DIDIT_JWKS_URL` | allotjat | JWKS que s'utilitza quan `MCP_TOKEN_VERIFY_MODE=jwks`. |
| `MCP_PERMISSION_MODE` | ambdós | Comprovació prèvia de permisos per eina: `shadow` (per defecte), `enforce` o `off`. |
| `MCP_JSON_BODY_LIMIT` | allotjat | Límit del cos JSON-RPC (per defecte `25mb`). |

`.env.example` del repositori és una plantilla per copiar, i `ARCHITECTURE.md` explica la separació entre servidor de recursos i servidor d'autorització. En arrencar, el servidor HTTP obté el document de descoberta del servidor d'autorització i, si no és accessible, recorre a les URL configurades.

***

> [card] [Referència d'eines](https://docs.didit.me/ca/integration/mcp/tools.md)
>
> Totes les eines, agrupades per àrea.

> [card] [Exemples](https://docs.didit.me/ca/integration/mcp/examples.md)
>
> Indicacions i converses completes de principi a fi.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.