Serveur MCP Scell.io -- 54 Outils
Version: 1.2.0 Protocole: MCP 2024-11-05 Transport: HTTP Streamable + SSE
Table des matieres
- Introduction
- Installation et Configuration
- Outils Disponibles (54)
- Exemples d'Integration
- Architecture Technique
1. Introduction
Qu'est-ce que MCP (Model Context Protocol) ?
Le Model Context Protocol (MCP) est un standard ouvert initie par Anthropic permettant aux modeles de langage (LLM) d'interagir avec des services externes de maniere structuree. Le protocole definit un format JSON-RPC 2.0 pour decouvrir et appeler des outils mis a disposition par un serveur.
Un serveur MCP expose :
- Des outils (tools) : fonctions que le LLM peut appeler avec des parametres JSON Schema
- Des ressources (resources) : donnees contextuelles accessibles en lecture
- Des prompts (prompts) : templates de conversation preconfigures
Pourquoi un serveur MCP pour la facturation ?
Scell.io integre un serveur MCP natif permettant aux agents IA de :
- Creer des factures conformes Factur-X/UBL/CII par simple instruction en langage naturel
- Gerer les signatures electroniques (eIDAS EU-SES) via conversation
- Consulter la conformite fiscale NF525/ISCA en temps reel
- Administrer les tenants et sous-tenants sans interface graphique
- Exporter les donnees fiscales (FEC, forensic) a la demande
Cas d'usage typique : un comptable demande a Claude "Cree une facture de 500 EUR HT pour ACME SAS" et le LLM appelle directement create_invoice via MCP.
Compatibilite
Le serveur MCP Scell.io est compatible avec :
- Claude Desktop (via
claude_desktop_config.json) - Claude Code (connexion directe)
- Tout client MCP implementant le protocole 2024-11-05
- Agents IA custom via appels HTTP JSON-RPC
2. Installation et Configuration
Endpoint
Le serveur MCP est accessible a l'adresse :
POST https://api.scell.io/mcp/Endpoints disponibles :
| Methode | URL | Description |
|---|---|---|
GET | /mcp/ | Informations serveur (public) |
POST | /mcp/ | Handler JSON-RPC (authentifie) |
GET | /mcp/stream | Flux SSE (optionnel) |
Authentification
Le serveur accepte deux types de cles API via le header X-Scell-API-Key :
| Type de cle | Format | Outils accessibles |
|---|---|---|
| Cle utilisateur | sk_live_xxx / sk_test_xxx | Factures, Signatures, Systeme, Validation, Compte, Audit |
| Cle tenant | sk_live_xxx / sk_test_xxx | Tous les 54 outils (incluant Fiscal, Tenant, Billing, Sub-Tenant) |
# Exemple avec cle utilisateur
curl -X POST https://api.scell.io/mcp/ \
-H "X-Scell-API-Key: sk_live_abc123..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'Configuration backend
Le fichier config/mcp.php controle le comportement du serveur :
return [
'enabled' => env('MCP_ENABLED', true),
'version' => '2024-11-05', // Version du protocole MCP
'server' => [
'name' => 'scell-mcp-server',
'version' => '1.2.0',
],
'session' => [
'ttl' => env('MCP_SESSION_TTL', 3600), // Duree de session : 1h
'driver' => env('MCP_SESSION_DRIVER', 'redis'),
],
'rate_limit' => [
'requests_per_minute' => env('MCP_RATE_LIMIT', 60),
],
];Variables d'environnement :
| Variable | Description | Defaut |
|---|---|---|
MCP_ENABLED | Active/desactive le serveur MCP | true |
MCP_SESSION_TTL | Duree de vie des sessions (secondes) | 3600 |
MCP_SESSION_DRIVER | Driver de stockage des sessions | redis |
MCP_RATE_LIMIT | Requetes par minute par cle API | 60 |
Flux d'initialisation
Avant d'utiliser les outils, le client doit initialiser une session :
Client Serveur MCP
| |
|-- POST /mcp/ (initialize) ----->|
|<---- session-id + capabilities --|
| |
|-- POST /mcp/ (tools/list) ----->|
|<---- liste des 54 outils -------|
| |
|-- POST /mcp/ (tools/call) ----->|
|<---- resultat de l'outil -------|Requete initialize :
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": {
"name": "mon-agent",
"version": "1.0.0"
}
}
}Reponse :
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": { "listChanged": true }
},
"serverInfo": {
"name": "scell-mcp-server",
"version": "1.2.0"
}
}
}Le header de reponse mcp-session-id contient l'identifiant de session a renvoyer dans les requetes suivantes.
3. Outils Disponibles (54)
3.1 Factures (4 outils)
create_invoice
Cree une facture electronique conforme Factur-X/UBL/CII.
Parametres :
{
"type": "object",
"required": ["invoice_number", "issue_date", "due_date", "seller", "buyer", "lines"],
"properties": {
"invoice_number": { "type": "string", "description": "Numero de facture unique" },
"issue_date": { "type": "string", "format": "date", "description": "Date d'emission (YYYY-MM-DD)" },
"due_date": { "type": "string", "format": "date", "description": "Date d'echeance (YYYY-MM-DD)" },
"seller": {
"type": "object",
"required": ["name", "address", "city", "postal_code"],
"properties": {
"name": { "type": "string" },
"siret": { "type": "string" },
"vat_number": { "type": "string" },
"address": { "type": "string" },
"city": { "type": "string" },
"postal_code": { "type": "string" },
"country": { "type": "string", "default": "FR" }
}
},
"buyer": {
"type": "object",
"required": ["name", "address", "city", "postal_code"],
"properties": {
"name": { "type": "string" },
"siret": { "type": "string" },
"vat_number": { "type": "string" },
"address": { "type": "string" },
"city": { "type": "string" },
"postal_code": { "type": "string" },
"country": { "type": "string", "default": "FR" }
}
},
"lines": {
"type": "array",
"items": {
"type": "object",
"required": ["description", "quantity", "unit_price"],
"properties": {
"description": { "type": "string" },
"quantity": { "type": "number" },
"unit_price": { "type": "number" },
"vat_rate": { "type": "number", "default": 20 }
}
}
},
"format": { "type": "string", "enum": ["facturx", "ubl", "cii"], "default": "facturx" },
"profile": { "type": "string", "enum": ["minimum", "basicwl", "basic", "en16931", "extended"], "default": "en16931" }
}
}Exemple d'appel :
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "create_invoice",
"arguments": {
"invoice_number": "FA-2026-001",
"issue_date": "2026-03-03",
"due_date": "2026-04-02",
"seller": {
"name": "Ma Societe SAS",
"siret": "12345678900001",
"address": "10 rue de la Paix",
"city": "Paris",
"postal_code": "75002"
},
"buyer": {
"name": "ACME SAS",
"siret": "98765432100001",
"address": "5 avenue des Champs",
"city": "Lyon",
"postal_code": "69001"
},
"lines": [
{ "description": "Prestation de conseil", "quantity": 5, "unit_price": 100, "vat_rate": 20 }
],
"format": "facturx",
"profile": "en16931"
}
}
}Reponse type :
{
"content": [{
"type": "text",
"text": {
"id": "9f3a1b2c-...",
"invoice_number": "FA-2026-001",
"status": "draft",
"total_ht": 500.0,
"total_tax": 100.0,
"total_ttc": 600.0,
"download_url": "https://api.scell.io/api/v1/invoices/9f3a1b2c-.../download/pdf",
"xml_url": "https://api.scell.io/api/v1/invoices/9f3a1b2c-.../download/xml"
}
}]
}Cout : 0.04 EUR par facture (gratuit en sandbox).
get_invoice
Recupere les details d'une facture par son ID.
Parametres : { "invoice_id": "string (UUID, requis)" }
Reponse : Objet facture complet (numero, montants, statut, lignes, URLs de telechargement).
list_invoices
Liste les factures avec filtrage et pagination.
Parametres :
| Parametre | Type | Description |
|---|---|---|
status | string | Filtrer par statut : draft, submitted, paid |
date_from | string (date) | Date de debut |
date_to | string (date) | Date de fin |
page | integer | Page (defaut: 1) |
per_page | integer | Elements par page (defaut: 15, max: 100) |
download_invoice
Telecharge une facture dans le format souhaite.
Parametres :
| Parametre | Type | Description |
|---|---|---|
invoice_id | string | UUID de la facture (requis) |
format | string | Format : pdf, xml, facturx, ubl, cii (defaut: pdf) |
Reponse : URL de telechargement temporaire ou contenu encode en base64.
3.2 Signatures (6 outils)
create_signature
Cree une demande de signature electronique simple (eIDAS EU-SES).
Parametres :
{
"type": "object",
"required": ["document_name", "signer"],
"properties": {
"document_name": { "type": "string", "description": "Nom du document a signer" },
"document_url": { "type": "string", "format": "uri", "description": "URL du PDF (accessible publiquement)" },
"document_base64": { "type": "string", "description": "PDF encode en base64 (alternative a document_url)" },
"signer": {
"type": "object",
"required": ["first_name", "last_name", "email"],
"properties": {
"first_name": { "type": "string" },
"last_name": { "type": "string" },
"email": { "type": "string", "format": "email" },
"phone": { "type": "string", "description": "Telephone pour OTP SMS (format E.164)" }
}
},
"otp_method": { "type": "string", "enum": ["sms", "email"], "default": "email" },
"webhook_url": { "type": "string", "format": "uri" },
"redirect_url": { "type": "string", "format": "uri" }
}
}Reponse type :
{
"id": "a1b2c3d4-...",
"status": "pending",
"signing_url": "https://api.scell.io/sign/a1b2c3d4-...",
"expires_at": "2026-04-02T00:00:00+00:00",
"signer": {
"email": "jean.dupont@example.com",
"otp_method": "email"
}
}Cout : 1.20 EUR par signature (gratuit en sandbox).
get_signature
Recupere les details d'une signature. Parametres : { "signature_id": "string (UUID)" }
list_signatures
Liste les signatures avec filtrage. Parametres : status, date_from, date_to, page, per_page.
download_signed
Telecharge le document signe. Parametres : { "signature_id": "string (UUID)" }. Disponible uniquement apres completion.
cancel_signature
Annule une demande de signature en cours. Parametres : { "signature_id": "string (UUID)" }. Seules les signatures au statut pending peuvent etre annulees.
send_reminder
Envoie un rappel au signataire. Parametres : { "signature_id": "string (UUID)" }. Un rappel par heure maximum.
3.3 Avoirs (7 outils) -- Tenant uniquement
Ces outils necessitent une cle tenant (tk_*).
create_credit_note
Cree un avoir lie a une facture existante.
Parametres :
| Parametre | Type | Description |
|---|---|---|
invoice_id | string | UUID de la facture d'origine (requis) |
reason | string | Motif de l'avoir (requis) |
lines | array | Lignes de l'avoir (description, quantity, unit_price, vat_rate) |
get_credit_note
Recupere un avoir par son ID. Parametres : { "credit_note_id": "string" }
list_credit_notes
Liste les avoirs avec pagination. Parametres : status, page, per_page.
download_credit_note
Telecharge l'avoir en PDF. Parametres : { "credit_note_id": "string" }
send_credit_note
Envoie l'avoir (change le statut de draft a sent). Parametres : { "credit_note_id": "string" }
delete_credit_note
Supprime un avoir (uniquement au statut draft). Parametres : { "credit_note_id": "string" }
get_remaining_creditable
Retourne le montant restant creditable sur une facture. Parametres : { "invoice_id": "string" }
3.4 Fiscal (12 outils) -- Tenant uniquement
get_fiscal_compliance
Retourne le statut de conformite fiscale NF525/ISCA du tenant.
Parametres : aucun.
Reponse type :
{
"compliant": true,
"last_closing": "2026-03-02",
"chain_integrity": "valid",
"entries_count": 1247,
"last_attestation_year": 2025,
"kill_switch_status": "inactive"
}check_fiscal_integrity
Verifie l'integrite de la chaine de hachage fiscale.
Parametres :
| Parametre | Type | Description |
|---|---|---|
date_from | string (date) | Date de debut (optionnel, verification complete si omis) |
date_to | string (date) | Date de fin (optionnel) |
Reponse type :
{
"result": "valid",
"entries_checked": 1247,
"first_sequence": 1,
"last_sequence": 1247,
"discrepancies_count": 0,
"discrepancies": [],
"duration_ms": 342,
"verified_at": "2026-03-03T14:30:00+00:00"
}list_fiscal_entries
Liste les ecritures du grand livre fiscal. Parametres : entry_type, date_from, date_to, page, per_page.
list_fiscal_closings
Liste les clotures fiscales (journalieres/mensuelles). Parametres : closing_type, page, per_page.
get_fiscal_attestation
Recupere l'attestation de conformite annuelle. Parametres : { "year": "integer (requis)" }
get_kill_switch_status
Retourne l'etat du kill switch fiscal. Parametres : aucun.
list_fiscal_rules
Liste les regles fiscales configurees pour le tenant. Parametres : page, per_page.
export_fec
Exporte le Fichier des Ecritures Comptables (FEC) conforme DGFIP. Parametres : year (requis), format (pipe ou tab, defaut: pipe).
perform_daily_closing
Declenche une cloture journaliere manuelle. Parametres : aucun. Normalement automatique a 00:05 UTC.
activate_kill_switch
Active le kill switch fiscal (arret d'urgence). Parametres : { "reason": "string (requis)" }. Necessite le scope fiscal:admin.
deactivate_kill_switch
Desactive le kill switch fiscal. Parametres : { "reason": "string (requis)" }. Necessite le scope fiscal:admin.
export_forensic
Exporte l'ensemble des donnees fiscales pour audit forensique. Parametres : date_from, date_to.
3.5 Systeme (2 outils)
health_check
Verifie l'etat de sante de l'API et de ses services.
Parametres : aucun.
Reponse type :
{
"status": "healthy",
"services": {
"database": "healthy",
"cache": "healthy"
},
"version": "1.2.0",
"environment": "production",
"timestamp": "2026-03-03T14:30:00+00:00"
}validate_api_key
Verifie la validite d'une cle API et retourne ses informations (scopes, environnement, entreprise associee).
Parametres : aucun (utilise la cle de la session courante).
3.6 Validation (2 outils)
validate_siret
Verifie un numero SIRET aupres de l'API INSEE Sirene.
Parametres : { "siret": "string (14 chiffres, requis)" }
Reponse : Informations de l'etablissement (raison sociale, adresse, code NAF, etat administratif).
validate_vat
Verifie un numero de TVA intracommunautaire via VIES.
Parametres : { "vat_number": "string (format EU, requis)" }
Reponse : Validite du numero, raison sociale, adresse.
3.7 Compte (1 outil)
get_balance
Retourne le solde du compte (credits disponibles, reserves, total).
Parametres : aucun.
Reponse type :
{
"available_balance": 45.60,
"reserved_balance": 2.40,
"total_balance": 48.00,
"currency": "EUR"
}3.8 Audit (1 outil)
get_audit_trail
Recupere la piste d'audit d'une entite (facture, signature, avoir).
Parametres :
| Parametre | Type | Description |
|---|---|---|
entity_type | string | Type : invoice, signature, credit_note (requis) |
entity_id | string | UUID de l'entite (requis) |
3.9 Tenant (3 outils) -- Tenant uniquement
get_tenant_profile
Retourne le profil du tenant (nom, SIRET, TVA, statut KYB, solde).
update_tenant_profile
Met a jour le profil du tenant. Parametres : name, billing_email, technical_email, webhook_url.
get_tenant_stats
Retourne les statistiques globales du tenant (factures, signatures, avoirs, consommation).
3.10 Billing (3 outils) -- Tenant uniquement
list_billing_invoices
Liste les factures de facturation du tenant. Parametres : status, page, per_page.
get_billing_usage
Retourne la consommation du mois en cours (nombre de factures, signatures, avoirs, montant).
list_billing_transactions
Liste les transactions de credit/debit du tenant. Parametres : page, per_page.
3.11 Statistiques (2 outils) -- Tenant uniquement
get_stats_overview
Vue d'ensemble du dashboard : totaux factures/signatures/avoirs, evolution, repartition.
get_stats_monthly
Statistiques mensuelles detaillees. Parametres : year, month.
3.12 Sous-tenants (6 outils) -- Tenant uniquement
list_sub_tenants
Liste les sous-tenants du tenant. Parametres : status, page, per_page.
create_sub_tenant
Cree un sous-tenant.
Parametres :
| Parametre | Type | Description |
|---|---|---|
external_id | string | ID externe dans le systeme du tenant (requis) |
name | string | Nom de l'entreprise (requis) |
email | string | Email de contact |
siret | string | SIRET |
vat_number | string | Numero TVA |
get_sub_tenant
Recupere un sous-tenant par ID. Parametres : { "sub_tenant_id": "string" }
update_sub_tenant
Met a jour un sous-tenant. Parametres : sub_tenant_id + champs a modifier.
delete_sub_tenant
Supprime un sous-tenant. Parametres : { "sub_tenant_id": "string" }
find_sub_tenant_by_external_id
Recherche un sous-tenant par son ID externe. Parametres : { "external_id": "string" }
3.13 Factures entrantes (5 outils) -- Tenant uniquement
list_incoming_invoices
Liste les factures recues des fournisseurs via SuperPDP.
get_incoming_invoice
Recupere le detail d'une facture entrante. Parametres : { "invoice_id": "string" }
accept_incoming_invoice
Accepte une facture entrante. Parametres : { "invoice_id": "string" }
reject_incoming_invoice
Rejette une facture entrante. Parametres : { "invoice_id": "string", "reason": "string" }
mark_incoming_invoice_paid
Marque une facture entrante comme payee. Parametres : { "invoice_id": "string", "payment_reference": "string" }
Recapitulatif des 54 outils par categorie
| Categorie | Outils | Auth requise |
|---|---|---|
| Factures | 4 | sk_* ou tk_* |
| Signatures | 6 | sk_* ou tk_* |
| Avoirs | 7 | tk_* uniquement |
| Fiscal | 12 | tk_* uniquement |
| Systeme | 2 | sk_* ou tk_* |
| Validation | 2 | sk_* ou tk_* |
| Compte | 1 | sk_* ou tk_* |
| Audit | 1 | sk_* ou tk_* |
| Tenant | 3 | tk_* uniquement |
| Billing | 3 | tk_* uniquement |
| Statistiques | 2 | tk_* uniquement |
| Sous-tenants | 6 | tk_* uniquement |
| Factures entrantes | 5 | tk_* uniquement |
| Total | 54 |
4. Exemples d'Integration
4.1 Integration avec Claude Desktop
Ajouter la configuration dans ~/.claude/claude_desktop_config.json :
{
"mcpServers": {
"scell-io": {
"transport": "http",
"url": "https://api.scell.io/mcp/",
"headers": {
"X-Scell-API-Key": "sk_live_votre_cle_api_ici"
}
}
}
}Apres redemarrage de Claude Desktop, les 54 outils Scell.io sont disponibles. Exemples de prompts :
- "Cree une facture de 1500 EUR HT pour ACME SAS, SIRET 12345678900001, pour une prestation de conseil"
- "Montre-moi le statut de conformite fiscale de mon tenant"
- "Liste les 5 dernieres factures au statut draft"
4.2 Agent IA custom (Node.js)
const MCP_URL = 'https://api.scell.io/mcp/';
const API_KEY = 'sk_live_votre_cle_api';
// 1. Initialiser la session
const initResponse = await fetch(MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Scell-API-Key': API_KEY,
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: { protocolVersion: '2024-11-05' },
}),
});
const initResult = await initResponse.json();
const sessionId = initResponse.headers.get('mcp-session-id');
// 2. Lister les outils disponibles
const toolsResponse = await fetch(MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Scell-API-Key': API_KEY,
'mcp-session-id': sessionId,
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 2,
method: 'tools/list',
params: {},
}),
});
const tools = await toolsResponse.json();
console.log(`${tools.result.tools.length} outils disponibles`);
// 3. Creer une facture
const invoiceResponse = await fetch(MCP_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Scell-API-Key': API_KEY,
'mcp-session-id': sessionId,
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 3,
method: 'tools/call',
params: {
name: 'create_invoice',
arguments: {
invoice_number: 'FA-2026-042',
issue_date: '2026-03-03',
due_date: '2026-04-02',
seller: {
name: 'Ma Societe SAS',
siret: '12345678900001',
address: '10 rue de la Paix',
city: 'Paris',
postal_code: '75002',
},
buyer: {
name: 'Client SARL',
siret: '98765432100001',
address: '5 avenue Victor Hugo',
city: 'Lyon',
postal_code: '69002',
},
lines: [
{ description: 'Developpement web', quantity: 10, unit_price: 800, vat_rate: 20 },
{ description: 'Hebergement annuel', quantity: 1, unit_price: 500, vat_rate: 20 },
],
},
},
}),
});
const invoice = await invoiceResponse.json();
console.log('Facture creee:', invoice.result);4.3 Agent IA custom (Python)
import requests
import json
MCP_URL = 'https://api.scell.io/mcp/'
API_KEY = 'sk_live_votre_cle_api'
HEADERS = {
'Content-Type': 'application/json',
'X-Scell-API-Key': API_KEY,
}
# 1. Initialiser
resp = requests.post(MCP_URL, headers=HEADERS, json={
'jsonrpc': '2.0', 'id': 1,
'method': 'initialize',
'params': {'protocolVersion': '2024-11-05'},
})
session_id = resp.headers.get('mcp-session-id')
HEADERS['mcp-session-id'] = session_id
# 2. Verifier la conformite fiscale
resp = requests.post(MCP_URL, headers=HEADERS, json={
'jsonrpc': '2.0', 'id': 2,
'method': 'tools/call',
'params': {
'name': 'get_fiscal_compliance',
'arguments': {},
},
})
compliance = resp.json()
print(json.dumps(compliance['result'], indent=2))
# 3. Exporter le FEC
resp = requests.post(MCP_URL, headers=HEADERS, json={
'jsonrpc': '2.0', 'id': 3,
'method': 'tools/call',
'params': {
'name': 'export_fec',
'arguments': {'year': 2025},
},
})
fec = resp.json()
print('FEC exporte:', fec['result'])4.4 Scenario complet : "Cree une facture pour client X"
Voici le flux complet lorsqu'un utilisateur demande a un LLM de creer une facture :
Utilisateur: "Cree une facture de 2000 EUR pour ACME"
LLM -> Reflexion:
1. Je dois chercher les infos du client ACME
2. Je dois connaitre les infos du vendeur (profil tenant)
3. Je cree la facture
LLM -> tools/call: get_tenant_profile
<- { name: "Ma Societe", siret: "123...", address: {...} }
LLM -> tools/call: validate_siret { siret: "987..." }
<- { company_name: "ACME SAS", address: {...} }
LLM -> tools/call: create_invoice {
invoice_number: "FA-2026-043",
seller: { ... donnees du profil tenant ... },
buyer: { ... donnees ACME ... },
lines: [{ description: "Prestation", quantity: 1, unit_price: 2000 }]
}
<- { id: "...", status: "draft", total_ttc: 2400.0, download_url: "..." }
LLM -> Utilisateur: "Facture FA-2026-043 creee pour ACME SAS.
Montant: 2 000 EUR HT / 2 400 EUR TTC.
Telechargement: [lien]"5. Architecture Technique
5.1 Diagramme de composants
graph TB
Client["Client MCP<br/>(Claude, Agent IA)"]
subgraph "Scell.io Backend"
MC["McpController<br/>POST /mcp/"]
SM["SessionManager<br/>(Redis)"]
TR["HttpStreamableTransport<br/>(JSON-RPC 2.0)"]
REG["ToolRegistry<br/>(54 outils)"]
subgraph "Outils"
BT["BaseTool<br/>(16 outils user)"]
TAT["TenantAwareTool<br/>(38 outils tenant)"]
end
SRV["Services metier<br/>(Fiscal, Billing, etc.)"]
DB[(PostgreSQL)]
RD[(Redis)]
end
Client -->|"X-Scell-API-Key"| MC
MC --> SM
MC --> TR
TR --> REG
REG --> BT
REG --> TAT
BT --> SRV
TAT --> SRV
SRV --> DB
SM --> RD5.2 Transport HTTP Streamable
Le serveur utilise le transport HTTP Streamable du protocole MCP :
- Requetes :
POST /mcp/avec body JSON-RPC 2.0 - Sessions : Identifiees par le header
mcp-session-id(formatmcp_+ 32 caracteres aleatoires) - SSE : Endpoint optionnel
GET /mcp/streampour notifications en temps reel - Keepalive : Ping toutes les 30 secondes sur la connexion SSE
Methodes JSON-RPC supportees :
| Methode | Description |
|---|---|
initialize | Initialise la session, retourne les capacites serveur |
tools/list | Liste les outils disponibles avec leurs schemas |
tools/call | Execute un outil avec des arguments |
ping | Verification de connectivite |
5.3 Gestion des sessions
Les sessions MCP sont stockees en base de donnees (table mcp_sessions) avec cache Redis :
McpSession {
session_id: "mcp_aB3cD4eF..." // Identifiant unique
api_key_id: UUID | null // Si cle utilisateur (sk_*)
tenant_id: UUID | null // Si cle tenant (tk_*)
tools_accessed: ["create_invoice", ...] // Audit des outils utilises
expires_at: "2026-03-03T15:30:00" // Expiration (TTL configurable)
metadata: { client_info: "...", auth_type: "tenant" }
}Cycle de vie :
- Creation : lors du premier
initialize(auto-detectionsk_*vstk_*) - Validation : a chaque requete, le session_id est verifie et l'activite prolongee
- Expiration : apres le TTL (defaut : 1 heure sans activite)
- Nettoyage : les sessions expirees sont purgees automatiquement
5.4 Tenant-awareness
Le serveur detecte automatiquement le type de cle API :
- Cle
sk_*(utilisateur) : acces aux 16 outils de base (factures, signatures, validation, systeme, compte, audit) - Cle
tk_*(tenant) : acces aux 54 outils (incluant fiscal, billing, sub-tenants, factures entrantes)
Les outils tenant heritent de TenantAwareTool qui :
- Verifie que la session est de type tenant
- Charge le tenant depuis la base
- Applique l'isolation des donnees (scoping automatique par
tenant_id)
// Exemple : un outil tenant verifie automatiquement le contexte
abstract class TenantAwareTool extends BaseTool
{
public function execute(array $arguments, McpSession $session): array
{
$tenant = $this->requireTenant($session);
if (!$tenant) {
return $this->error('Cle tenant (tk_*) requise.');
}
return $this->executeTenant($arguments, $session, $tenant);
}
}5.5 Gestion des erreurs
Les erreurs suivent le standard JSON-RPC 2.0 :
| Code | Signification |
|---|---|
-32700 | Erreur de parsing JSON |
-32601 | Methode inconnue |
-32001 | Cle API manquante ou invalide |
-32002 | Session invalide ou expiree |
-32603 | Erreur interne du serveur |
Les outils retournent un champ isError: true en cas d'erreur metier :
{
"content": [{ "type": "text", "text": "{\"error\": \"Solde insuffisant\"}" }],
"isError": true
}5.6 Rate limiting
Le serveur applique un rate limit de 60 requetes par minute par cle API (configurable via MCP_RATE_LIMIT). En cas de depassement, le serveur retourne une erreur JSON-RPC avec le code -32001.
5.7 Securite
- Toutes les communications transitent en HTTPS
- Les cles API sont hashees en base (seul le prefixe
sk_live_,sk_test_est stocke en clair) - Les sessions sont liees a la cle API d'origine
- Chaque appel d'outil est trace dans
tools_accessedde la session - Les outils fiscaux (
fiscal:admin) necessitent des scopes explicites