@casys/mcp-einvoice 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -0
- package/mcp-einvoice.mjs +39197 -0
- package/package.json +34 -0
- package/ui-dist/directory-card/index.html +128 -0
- package/ui-dist/doclist-viewer/index.html +130 -0
- package/ui-dist/invoice-viewer/index.html +128 -0
- package/ui-dist/status-timeline/index.html +133 -0
package/README.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# @casys/mcp-einvoice
|
|
2
|
+
|
|
3
|
+
MCP server for French e-invoicing — PA-agnostic via the adapter pattern.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌──────────────────────────────────────────────────┐
|
|
9
|
+
│ MCP Tools (27 tools, einvoice_*) │
|
|
10
|
+
│ invoice · directory · status · reporting · webhook │
|
|
11
|
+
├──────────────────────────────────────────────────┤
|
|
12
|
+
│ MCP Apps (4 viewers) │
|
|
13
|
+
│ invoice-viewer · doclist-viewer │
|
|
14
|
+
│ status-timeline · directory-card │
|
|
15
|
+
├──────────────────────────────────────────────────┤
|
|
16
|
+
│ EInvoiceAdapter (interface) │
|
|
17
|
+
│ PA-agnostic: emitInvoice, searchInvoices, ... │
|
|
18
|
+
├──────────┬───────────────────────────────────────┤
|
|
19
|
+
│ Iopole │ Autres PA via EInvoiceAdapter │
|
|
20
|
+
│ (REST) │ (ajout sans toucher aux tools) │
|
|
21
|
+
└──────────┴───────────────────────────────────────┘
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Chaque PA (Plateforme Agréée) implémente `EInvoiceAdapter`. Les tools MCP appellent l'adapter, jamais l'API directement.
|
|
25
|
+
|
|
26
|
+
## Configuration
|
|
27
|
+
|
|
28
|
+
### Variables d'environnement
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Choix du provider (default: iopole)
|
|
32
|
+
EINVOICE_ADAPTER=iopole
|
|
33
|
+
|
|
34
|
+
# Config Iopole — OAuth2 client credentials
|
|
35
|
+
IOPOLE_API_URL=https://api.ppd.iopole.fr/v1 # sandbox
|
|
36
|
+
IOPOLE_CLIENT_ID=your-client-id
|
|
37
|
+
IOPOLE_CLIENT_SECRET=your-client-secret
|
|
38
|
+
IOPOLE_CUSTOMER_ID=your-customer-id # required since 2026-02-01
|
|
39
|
+
|
|
40
|
+
# Optionnel — token endpoint Keycloak (default: production)
|
|
41
|
+
# Sandbox : https://auth.ppd.iopole.fr/realms/iopole/protocol/openid-connect/token
|
|
42
|
+
IOPOLE_AUTH_URL=https://auth.iopole.com/realms/iopole/protocol/openid-connect/token
|
|
43
|
+
|
|
44
|
+
# Sécurité (optionnel — mode HTTP du serveur MCP)
|
|
45
|
+
MCP_AUTH_PROVIDER=oidc
|
|
46
|
+
MCP_AUTH_ISSUER=https://auth.example.com
|
|
47
|
+
MCP_AUTH_AUDIENCE=mcp-einvoice
|
|
48
|
+
MCP_AUTH_JWKS_URI=https://auth.example.com/.well-known/jwks.json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### MCP config (stdio mode)
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"einvoice": {
|
|
57
|
+
"command": "deno",
|
|
58
|
+
"args": ["run", "--allow-all", "server.ts"],
|
|
59
|
+
"env": {
|
|
60
|
+
"EINVOICE_ADAPTER": "iopole",
|
|
61
|
+
"IOPOLE_API_URL": "https://api.ppd.iopole.fr/v1",
|
|
62
|
+
"IOPOLE_CLIENT_ID": "your-client-id",
|
|
63
|
+
"IOPOLE_CLIENT_SECRET": "your-client-secret",
|
|
64
|
+
"IOPOLE_CUSTOMER_ID": "your-customer-id"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### HTTP mode
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
deno run --allow-all server.ts --http --port=3015
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Options :
|
|
78
|
+
- `--http` — mode HTTP (default: stdio)
|
|
79
|
+
- `--port=3015` — port HTTP (default: 3015)
|
|
80
|
+
- `--hostname=0.0.0.0` — hostname (default: 0.0.0.0)
|
|
81
|
+
- `--adapter=iopole` — override le provider (default: env `EINVOICE_ADAPTER` ou `iopole`)
|
|
82
|
+
- `--categories=invoice,status` — filtrer les catégories de tools
|
|
83
|
+
|
|
84
|
+
**Note** : en mode HTTP, le `generated-store` (flow generate → emit) est in-memory et single-instance. Ne pas déployer derrière un load-balancer sans sticky sessions.
|
|
85
|
+
|
|
86
|
+
## Tools (27)
|
|
87
|
+
|
|
88
|
+
| Catégorie | N | Tools | Description |
|
|
89
|
+
|-----------|---|-------|-------------|
|
|
90
|
+
| **invoice** | 13 | `emit`, `search`, `get`, `download`, `download_readable`, `files`, `attachments`, `download_file`, `mark_seen`, `not_seen`, `generate_cii`, `generate_ubl`, `generate_facturx` | Émission, recherche, téléchargement, génération CII/UBL/Factur-X |
|
|
91
|
+
| **directory** | 3 | `fr_search`, `int_search`, `peppol_check` | Annuaire PPF (France) + Peppol (international) |
|
|
92
|
+
| **status** | 4 | `send`, `history`, `not_seen`, `mark_seen` | Cycle de vie facture (APPROVED, REFUSED, DISPUTED, PAYMENT_SENT...) |
|
|
93
|
+
| **reporting** | 2 | `invoice_transaction`, `transaction` | E-reporting DGFiP (B2C, international) |
|
|
94
|
+
| **webhook** | 5 | `list`, `get`, `create`, `update`, `delete` | Notifications temps réel |
|
|
95
|
+
|
|
96
|
+
Tous les noms de tools sont préfixés `einvoice_<category>_` (ex: `einvoice_invoice_search`).
|
|
97
|
+
|
|
98
|
+
### Flow generate → preview → emit
|
|
99
|
+
|
|
100
|
+
1. **Generate** (`generate_cii`, `generate_ubl`, `generate_facturx`) : Génère le XML/PDF, stocke le fichier côté serveur, retourne un `generated_id` + preview pour le viewer
|
|
101
|
+
2. **Preview** : Le `invoice-viewer` affiche la facture avec un bouton "Déposer"
|
|
102
|
+
3. **Emit** (`emit`) : Accepte `generated_id` (consomme le fichier stocké) ou `file_base64` + `filename` direct
|
|
103
|
+
|
|
104
|
+
Les fichiers générés expirent après 10 minutes.
|
|
105
|
+
|
|
106
|
+
## MCP Apps (4 viewers)
|
|
107
|
+
|
|
108
|
+
| Viewer | Tools associés | Description |
|
|
109
|
+
|--------|---------------|-------------|
|
|
110
|
+
| **invoice-viewer** | `get`, `generate_*` | Facture détaillée avec actions (accepter, rejeter, contester, marquer lu, télécharger, déposer) |
|
|
111
|
+
| **doclist-viewer** | `search`, `not_seen`, `fr_search`, `int_search`, `webhook_list` | Table générique avec drill-down (clic → appel tool) |
|
|
112
|
+
| **status-timeline** | `history` | Timeline verticale des changements de statut |
|
|
113
|
+
| **directory-card** | `fr_search` (single result) | Fiche entreprise avec SIREN/SIRET, réseaux, détails |
|
|
114
|
+
|
|
115
|
+
Build des viewers :
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
cd src/ui && node build-all.mjs
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Utilisation directe de l'adapter
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { createIopoleAdapter } from "@casys/mcp-einvoice";
|
|
125
|
+
|
|
126
|
+
const adapter = createIopoleAdapter();
|
|
127
|
+
|
|
128
|
+
// Rechercher des factures (Lucene syntax)
|
|
129
|
+
const results = await adapter.searchInvoices({
|
|
130
|
+
q: 'status:accepted AND direction:received',
|
|
131
|
+
expand: "businessData",
|
|
132
|
+
offset: 0,
|
|
133
|
+
limit: 20,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Envoyer un statut
|
|
137
|
+
await adapter.sendStatus({
|
|
138
|
+
invoiceId: "uuid-de-la-facture",
|
|
139
|
+
code: "APPROVED",
|
|
140
|
+
message: "Facture validée",
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Chercher dans l'annuaire PPF
|
|
144
|
+
const company = await adapter.searchDirectoryFr({
|
|
145
|
+
q: 'siret:"43446637100011"',
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Générer une facture CII
|
|
149
|
+
const xml = await adapter.generateCII({
|
|
150
|
+
invoice: { invoiceId: "F-001", seller: { ... }, buyer: { ... }, ... },
|
|
151
|
+
flavor: "EN16931",
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Ajouter un adapter (nouveau PA)
|
|
156
|
+
|
|
157
|
+
1. Créer `src/adapters/my-pa.ts` implémentant `EInvoiceAdapter`
|
|
158
|
+
2. Ajouter le case dans `server.ts` → `createAdapter()`
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import type { EInvoiceAdapter } from "../adapter.ts";
|
|
162
|
+
|
|
163
|
+
export class MyPAAdapter implements EInvoiceAdapter {
|
|
164
|
+
readonly name = "my-pa";
|
|
165
|
+
// Implémenter les 27 méthodes de l'interface
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
L'interface `EInvoiceAdapter` est définie dans `src/adapter.ts` — 27 méthodes couvrant factures, annuaire, statuts, reporting et webhooks.
|
|
170
|
+
|
|
171
|
+
## Node.js
|
|
172
|
+
|
|
173
|
+
Build single-file CLI via esbuild :
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
./scripts/build-node.sh
|
|
177
|
+
# Produit dist-node/bin/mcp-einvoice.mjs (~1.3MB)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Le script swap `runtime.ts` par `runtime.node.ts` et strip les extensions `.ts` des imports.
|
|
181
|
+
|
|
182
|
+
## Structure
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
├── deno.json # Package @casys/mcp-einvoice
|
|
186
|
+
├── mod.ts # Public API
|
|
187
|
+
├── server.ts # MCP server (stdio + HTTP)
|
|
188
|
+
├── scripts/
|
|
189
|
+
│ └── build-node.sh # esbuild single-file build
|
|
190
|
+
└── src/
|
|
191
|
+
├── adapter.ts # EInvoiceAdapter interface (26 méthodes)
|
|
192
|
+
├── generated-store.ts # Temp file store (generate → emit flow)
|
|
193
|
+
├── adapters/
|
|
194
|
+
│ └── iopole.ts # IopoleAdapter
|
|
195
|
+
├── api/
|
|
196
|
+
│ └── iopole-client.ts # HTTP client + OAuth2 token provider
|
|
197
|
+
├── runtime.ts # Deno runtime (env vars)
|
|
198
|
+
├── runtime.node.ts # Node.js runtime
|
|
199
|
+
├── tools/
|
|
200
|
+
│ ├── types.ts # EInvoiceTool, EInvoiceToolContext
|
|
201
|
+
│ ├── mod.ts # Registry (27 tools)
|
|
202
|
+
│ ├── invoice.ts # 13 tools
|
|
203
|
+
│ ├── directory.ts # 3 tools
|
|
204
|
+
│ ├── status.ts # 4 tools
|
|
205
|
+
│ ├── reporting.ts # 2 tools
|
|
206
|
+
│ └── webhook.ts # 5 tools
|
|
207
|
+
├── testing/
|
|
208
|
+
│ └── helpers.ts # Mock fetch, mock adapter
|
|
209
|
+
└── ui/
|
|
210
|
+
├── build-all.mjs
|
|
211
|
+
├── shared/ # Theme, brand, refresh
|
|
212
|
+
├── invoice-viewer/ # Viewer facture interactif
|
|
213
|
+
├── doclist-viewer/ # Table générique drill-down
|
|
214
|
+
├── status-timeline/ # Timeline verticale statuts
|
|
215
|
+
└── directory-card/ # Fiche entreprise
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Iopole API
|
|
219
|
+
|
|
220
|
+
- Production : `https://api.iopole.com/v1`
|
|
221
|
+
- Sandbox : `https://api.ppd.iopole.fr/v1`
|
|
222
|
+
- Search : `https://api.ppd.iopole.fr/v1.1/invoice/search` (version v1.1)
|
|
223
|
+
- Auth : OAuth2 `client_credentials` (token TTL 10 min, auto-refresh 60s avant expiry)
|
|
224
|
+
- Token endpoint : `https://auth.iopole.com/realms/iopole/protocol/openid-connect/token`
|
|
225
|
+
- Header `customer-id` obligatoire sur toutes les requêtes (depuis 2026-02-01)
|