# Intégration MCP

Accessful héberge un serveur MCP permettant à votre application IA de traiter des PDF, de suivre leur progression et de récupérer le résultat.
Vous avez besoin d’une clé API Accessful et d’un client prenant en charge les **serveurs distants via Streamable HTTP et les en-têtes HTTP personnalisés**.

## Configurer la connexion

1. Dans le portail Accessful, ouvrez **API-Keys** et créez une clé pour cette intégration.
   Copiez-la dès sa création ; elle ne s’affiche qu’une fois. Voir [Créer une clé API](https://docs.accessful.de/fr/authentication/#créer-une-clé-api).
2. Ajoutez dans votre client un serveur MCP distant nommé **Accessful** avec les paramètres suivants :

   | Paramètre | Valeur |
   | --- | --- |
   | URL du serveur | `https://api.accessful.de/mcp` |
   | Transport | Streamable HTTP |
   | Nom de l’en-tête | `X-API-Key` |
   | Valeur de l’en-tête | Votre clé API Accessful personnelle |

3. Enregistrez la clé dans le stockage des secrets du client, sauvegardez et connectez-vous. L’en-tête doit accompagner **chaque requête**.
   Utilisez une clé distincte et révocable par utilisateur et par intégration. **La connexion OAuth n’est pas disponible en V1**.

Connectez vos propres applications web via leur backend. Les requêtes directes du navigateur depuis une autre origine sont rejetées avec `403`.

## Vérifier la connexion

Actualisez la liste des outils du client. Ces **quatre outils** doivent apparaître :

| Outil | Entrée | Résultat |
| --- | --- | --- |
| `accessful_start_pdf` | `url`, `filename`, `requestId` | Lance une tâche à partir d’un lien de téléchargement ; renvoie `caseId`, `pollAfterSeconds` |
| `accessful_start_pdf_file` | `file` (rempli par l’hôte) | Lance une tâche à partir d’une pièce jointe au chat ; renvoie `caseId`, `pollAfterSeconds` |
| `accessful_get_status` | `caseId` | Renvoie `jobStatus`, `stage`, `terminal` et les informations de progression disponibles |
| `accessful_get_result` | `caseId` | Renvoie `downloadUrl`, `expiresAt`, `filename`, `mimeType` |

<details>
<summary>Facultatif : vérifier avec MCP Inspector</summary>

Avec Node.js 22.19 ou une version ultérieure et votre clé dans la variable d’environnement `ACCESSFUL_API_KEY`,
exécutez cette commande dans un terminal Bash ou Zsh. Elle liste les outils sans créer de tâche PDF :

```bash
npx @modelcontextprotocol/inspector --cli https://api.accessful.de/mcp \
  --transport http --header "X-API-Key: ${ACCESSFUL_API_KEY:?Set ACCESSFUL_API_KEY}" \
  --method tools/list
```

La sortie doit contenir les quatre noms ci-dessus. Voir la [documentation de MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector).

</details>

## Traiter un PDF

Lancez une tâche avec **l’un des deux outils de lancement**, puis consultez le statut et téléchargez le résultat.
Maximum **50 Mio**, un PDF par tâche.

### Option A : pièce jointe au chat

Certains hôtes MCP transmettent directement les pièces jointes du chat aux outils qui déclarent un paramètre de fichier dans `_meta["openai/fileParams"]`.
`accessful_start_pdf_file` déclare ainsi son paramètre `file`. Si votre hôte le prend en charge, l’utilisateur joint le PDF
et l’hôte remplit `file` avec un lien de téléchargement temporaire ; le modèle n’a donc jamais à construire d’URL :

```json
{
  "file": {
    "download_url": "https://files.example.com/temporary/abc123",
    "file_id": "file_abc123",
    "mime_type": "application/pdf",
    "file_name": "Rapport annuel.pdf"
  }
}
```

La `download_url` de l’hôte doit être accessible à Accessful en HTTPS public, sans connexion ni en-têtes supplémentaires,
et rester valide jusqu’à ce qu’Accessful ait téléchargé le fichier. Le téléchargement commence peu après l’acceptation de la tâche.
Aucun `requestId` n’est nécessaire : un appel identique renvoie le même `caseId`, tandis qu’un lien renouvelé pour le même fichier lance une nouvelle tâche.

Les hôtes sans cette prise en charge affichent `file` comme un objet ordinaire. Utilisez alors l’option B ; ne laissez pas le modèle inventer une `download_url`.

### Option B : lien de téléchargement

Préparez un **lien HTTPS de téléchargement direct du PDF original**, accessible à Accessful sans connexion ni en-têtes supplémentaires.
Un lien vers un PDF déjà public convient. Pour les fichiers privés, votre application doit générer un lien de téléchargement signé.
Un chemin local ne suffit pas ; si l’hôte ne prend pas en charge les fichiers, l’application doit rendre le fichier accessible par URL.
Le lien doit rester valide encore au moins **15 minutes**.

Appelez `accessful_start_pdf` avec les arguments suivants. Remplacez l’URL d’exemple par le lien vers votre PDF
et générez un nouvel UUID `requestId` pour chaque nouvelle tâche :

```json
{
  "url": "https://files.example.com/document.pdf",
  "filename": "document.pdf",
  "requestId": "96d35d20-7f2a-4de2-9a85-0e7d03cc68a4"
}
```

Pour les reprises, réutilisez **le même `requestId`, la même URL et le même nom de fichier**, même après une rotation de clé API.

### Consulter le statut et télécharger le résultat

1. Conservez le `caseId` renvoyé par l’outil de lancement. Appelez avec lui `accessful_get_status` toutes les **10 secondes**, jusqu’à ce que `terminal` vaille `true`.
   Après **120 secondes** d’attente active, affichez l’état courant et le `caseId` ; le traitement continue, consultez donc le statut plus tard.
2. Lorsque `jobStatus` vaut `completed`, appelez `accessful_get_result` avec le même `caseId` et affichez `downloadUrl` comme lien cliquable.
   Il fonctionne sans clé API pendant **cinq minutes**. Rappelez l’outil pour obtenir un nouveau lien après expiration.

L’application doit gérer les reprises et les consultations périodiques et, si l’hôte ne prend pas en charge les fichiers, aussi l’accès au fichier ; l’ajout du serveur MCP ne met pas en place ce parcours.
Excluez clés, URL signées et contenu PDF des journaux et des prompts. Affichez le lien du résultat uniquement à l’utilisateur destinataire.

## Limites et erreurs fréquentes

| Problème | Solution |
| --- | --- |
| `401` ou `AUTHENTICATION_REQUIRED` | Vérifiez que `X-API-Key` accompagne chaque requête et que la clé est valide. |
| `403` lors de la connexion depuis le navigateur | Connectez-vous via votre backend ; les requêtes d’autres origines sont rejetées. |
| `RESULT_NOT_READY` | Consultez le statut. Demandez le résultat uniquement après `completed`. |
| `IDEMPOTENCY_CONFLICT` | Réutilisez l’URL et le nom de fichier d’origine avec ce `requestId`. Renouveler une URL source signée change aussi l’entrée. |
| `UNSUPPORTED_FILE_TYPE` | Le fichier joint n’est pas un PDF. Joignez le PDF original. |
| `failed` avec l’erreur `DOWNLOAD_FAILED` | Accessful n’a pas pu télécharger l’original. Vérifiez que le lien est accessible publiquement en HTTPS et toujours valide, puis lancez une nouvelle tâche ; pour une pièce jointe au chat, joignez de nouveau le fichier. |
| Timeout | La tâche peut déjà exister. Réessayez le lancement avec les mêmes entrées : le même `requestId` ou le même objet `file`. |
| Lien du résultat expiré | Rappelez `accessful_get_result`. |
| `quota_exceeded` | Le traitement s’est arrêté car votre quota est épuisé. Voir [Limites et conservation](https://docs.accessful.de/fr/limits/). |

<details>
<summary>Référence technique</summary>

- `filename` : au plus 255 caractères, conforme à `^[A-Za-z0-9_-]+\.pdf$`, par exemple `document.pdf`.
- `url` : au plus 8192 caractères, sans identifiants intégrés ni fragments. Les destinations privées sont rejetées ;
  le téléchargement de l’original est limité à **120 secondes**. Voir [Téléverser par URL](https://docs.accessful.de/fr/reference/upload-by-url/).
- `file` : objet avec les chaînes obligatoires `download_url` et `file_id` et les chaînes facultatives `mime_type` et `file_name` ;
  les autres propriétés sont rejetées. `download_url` suit les mêmes règles que `url`. `file_name` est converti en `filename` valide
  (valeur par défaut `document.pdf`) ; un `mime_type` autre que `application/pdf` produit `UNSUPPORTED_FILE_TYPE`.
- `caseId` et `requestId` sont des UUID. Les arguments invalides produisent `INVALID_ARGUMENT`.
- États finaux : `completed`, `failed`, `analyzer_failed`, `canceled`, `quota_exceeded`.
  `queued`, `running` et `quota_pending` restent actifs. Seul `completed` permet de télécharger le résultat.
- Le statut peut inclure `queuePosition`, `queueTotal`, `estimatedWaitSeconds` et `error` ; `score` apparaît uniquement pour `completed`.
  L’absence de champs de file n’indique pas un état final.
- Les réponses réussies contiennent un JSON identique dans `structuredContent` et un bloc texte. Les résultats incluent aussi un `resource_link` PDF.
  Les liens donnent accès à une version du résultat ; traitez-les comme des secrets.
- Les erreurs d’outil contiennent `isError: true` et `{code, message, retryable}`. Les erreurs HTTP de connexion peuvent avoir un corps vide ;
  n’attendez pas le format Problem Details de l’API REST.

</details>