Skip to content

Serveur MCP Scell.io -- 54 Outils ​

Version applicative: 1.2.1 SDK MCP (@scell/mcp-client): 2.33.0 Protocole: MCP 2024-11-05 Transport: HTTP Streamable + SSE


Table des matieres ​

  1. Introduction
  2. Installation et Configuration
  3. Outils Disponibles (54)
  4. Exemples d'Integration
  5. 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 ISCA (autocertification) 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 :

MethodeURLDescription
GET/mcp/Informations serveur (public)
POST/mcp/Handler JSON-RPC (authentifie)
GET/mcp/streamFlux SSE (optionnel)

Authentification ​

Le serveur accepte deux types de cles API via le header X-Scell-API-Key :

Type de cleFormatOutils accessibles
Cle secrete tenantsk_live_xxx / sk_test_xxxTous les 54 outils. Une cle sk_* appartient a un tenant ; le sous-tenant est cible via le parametre sub_tenant_id de l'appel (modele cle=tenant, depuis 2026-05-11).
bash
# 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 :

php
return [
    'enabled' => env('MCP_ENABLED', true),
    'version' => '2024-11-05',        // Version du protocole MCP
    'server' => [
        'name' => 'scell-mcp-server',
        'version' => '1.2.1',
    ],
    '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 :

VariableDescriptionDefaut
MCP_ENABLEDActive/desactive le serveur MCPtrue
MCP_SESSION_TTLDuree de vie des sessions (secondes)3600
MCP_SESSION_DRIVERDriver de stockage des sessionsredis
MCP_RATE_LIMITRequetes par minute par cle API60

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 :

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "clientInfo": {
      "name": "mon-agent",
      "version": "1.0.0"
    }
  }
}

Reponse :

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": { "listChanged": true }
    },
    "serverInfo": {
      "name": "scell-mcp-server",
      "version": "1.2.1"
    }
  }
}

Le header de reponse mcp-session-id contient l'identifiant de session a renvoyer dans les requetes suivantes.


3. Outils Disponibles (54) ​

Les outils Devis (scell_*_quote) et l'echeancier de paiement ont ete ajoutes a partir du SDK MCP v2.11.0. Le decompte par categorie ci-dessous peut differer d'une version a l'autre ; la source de verite est le ToolRegistry backend (php artisan mcp:generate-llms-txt), qui expose actuellement 54 outils canoniques.

3.1 Factures (4 outils) ​

create_invoice ​

Cree une facture electronique conforme Factur-X/UBL/CII.

Parametres :

json
{
  "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 :

json
{
  "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 :

json
{
  "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 :

ParametreTypeDescription
statusstringFiltrer par statut : draft, submitted, paid
date_fromstring (date)Date de debut
date_tostring (date)Date de fin
pageintegerPage (defaut: 1)
per_pageintegerElements par page (defaut: 15, max: 100)

download_invoice ​

Telecharge une facture dans le format souhaite.

Parametres :

ParametreTypeDescription
invoice_idstringUUID de la facture (requis)
formatstringFormat : 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 :

json
{
  "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 :

json
{
  "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 secrete tenant (sk_live_* / sk_test_*).

create_credit_note ​

Cree un avoir lie a une facture existante.

Parametres :

ParametreTypeDescription
invoice_idstringUUID de la facture d'origine (requis)
reasonstringMotif de l'avoir (requis)
linesarrayLignes 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 ISCA (autocertification) du tenant.

Parametres : aucun.

Reponse type :

json
{
  "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 :

ParametreTypeDescription
date_fromstring (date)Date de debut (optionnel, verification complete si omis)
date_tostring (date)Date de fin (optionnel)

Reponse type :

json
{
  "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 :

json
{
  "status": "healthy",
  "services": {
    "database": "healthy",
    "cache": "healthy"
  },
  "version": "1.2.1",
  "environment": "production",
  "timestamp": "2026-05-28T14: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 :

json
{
  "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 :

ParametreTypeDescription
entity_typestringType : invoice, signature, credit_note (requis)
entity_idstringUUID 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 :

ParametreTypeDescription
external_idstringID externe dans le systeme du tenant (requis)
namestringNom de l'entreprise (requis)
emailstringEmail de contact
siretstringSIRET
vat_numberstringNumero 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 ​

CategorieOutilsAuth requise
Factures4sk_*
Signatures6sk_*
Avoirs7sk_*
Devis (scell_*_quote)11sk_*
Fiscal12sk_*
Systeme2sk_*
Validation2sk_*
Compte1sk_*
Audit1sk_*
Tenant3sk_*
Billing3sk_*
Statistiques2sk_*
Sous-tenants(couverts par les outils Tenant)sk_*
Factures entrantes5sk_*
Total (source de verite : code MCP)54

La cle MCP est une cle secrete tenant sk_live_* / sk_test_* (l'ancien prefixe tk_* n'existe plus). Les outils fiscaux/tenant/billing necessitent simplement une cle secrete valide ; le sous-tenant est cible via le parametre sub_tenant_id dans l'appel (modele cle=tenant, depuis 2026-05-11).


4. Exemples d'Integration ​

4.1 Integration avec Claude Desktop ​

Ajouter la configuration dans ~/.claude/claude_desktop_config.json :

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) ​

javascript
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) ​

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 ​

mermaid
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 --> RD

5.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 (format mcp_ + 32 caracteres aleatoires)
  • SSE : Endpoint optionnel GET /mcp/stream pour notifications en temps reel
  • Keepalive : Ping toutes les 30 secondes sur la connexion SSE

Methodes JSON-RPC supportees :

MethodeDescription
initializeInitialise la session, retourne les capacites serveur
tools/listListe les outils disponibles avec leurs schemas
tools/callExecute un outil avec des arguments
pingVerification 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            // Cle secrete utilisee (sk_*)
  tenant_id: UUID | null             // Tenant resolu depuis la cle sk_*
  tools_accessed: ["create_invoice", ...]  // Audit des outils utilises
  expires_at: "2026-05-28T15:30:00"  // Expiration (TTL configurable)
  metadata: { client_info: "...", auth_type: "tenant" }
}

Cycle de vie :

  1. Creation : lors du premier initialize (resolution du tenant depuis la cle sk_*)
  2. Validation : a chaque requete, le session_id est verifie et l'activite prolongee
  3. Expiration : apres le TTL (defaut : 1 heure sans activite)
  4. Nettoyage : les sessions expirees sont purgees automatiquement

5.4 Tenant-awareness ​

Le serveur resout automatiquement le tenant depuis la cle secrete sk_* :

  • Une cle secrete sk_live_* / sk_test_* donne acces aux 54 outils (factures, signatures, avoirs, devis, fiscal, billing, statistiques, factures entrantes, etc.).
  • Le sous-tenant emetteur est cible via le parametre sub_tenant_id de l'appel (modele cle=tenant, depuis 2026-05-11).

Les outils tenant heritent de TenantAwareTool qui :

  1. Verifie que la session est de type tenant
  2. Charge le tenant depuis la base
  3. Applique l'isolation des donnees (scoping automatique par tenant_id)
php
// 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 secrete tenant (sk_*) requise.');
        }
        return $this->executeTenant($arguments, $session, $tenant);
    }
}

5.5 Gestion des erreurs ​

Les erreurs suivent le standard JSON-RPC 2.0 :

CodeSignification
-32700Erreur de parsing JSON
-32601Methode inconnue
-32001Cle API manquante ou invalide
-32002Session invalide ou expiree
-32603Erreur interne du serveur

Les outils retournent un champ isError: true en cas d'erreur metier :

json
{
  "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_accessed de la session
  • Les outils fiscaux (fiscal:admin) necessitent des scopes explicites

Documentation Scell.io