Utiliser l'API
Serveur MCP
Un serveur Model Context Protocol, pour qu’un agent IA puisse rechercher des mesures, évaluer une entreprise et expliquer un résultat avec la même clé, les mêmes limites et les mêmes réponses que l’API REST.
L’endpoint
| Propriété | Valeur |
|---|---|
| URL | POST https://api.subsido.be/mcp |
| Transport | Streamable HTTP, sans état : chaque requête est un message JSON-RPC 2.0 (ou un lot), avec une réponse en JSON simple. Pas de session, pas de server-sent events ; un GET reçoit 405 method_not_allowed. |
| Authentification | Votre clé API comme jeton bearer : Authorization: Bearer sb_live_.... |
| Versions du protocole | 2025-06-18, 2025-03-26, 2024-11-05. Le serveur répond à initialize avec la version demandée s’il la prend en charge, sinon avec la plus récente. |
| Méthodes | initialize, ping, tools/list, tools/call. Une notification (un message sans id) est acquittée par un 202. |
| Limites | Les mêmes que sur les routes REST : chaque POST compte pour une requête dans votre limite de débit et votre quota mensuel, et les outils de matching comptent en plus une évaluation de matching chacun. L’outil du flux de modifications demande la formule Developer, comme /v1/changes. |
Outils
Chaque outil est en lecture seule. Les arguments sont validés exactement comme la route correspondante valide ses paramètres.
| Outil | Arguments | Renvoie |
|---|---|---|
| search_subsidies | q, region, topic, company_size, instrument_type, status, nace, deadline_before, language, limit (1 à 25) | Des fiches compactes, comme GET /v1/subsidies : { results, has_more, disclaimer }. Première page uniquement. |
| get_subsidy | id (id ou slug, obligatoire), language | La fiche complète, comme GET /v1/subsidies/{id}. |
| match_company | company, project, language, limit (1 à 25, 10 par défaut) | { matches, matched, missing_information, disclaimer }, comme POST /v1/match avec les options par défaut. Une évaluation de matching. |
| explain_eligibility | subsidy_id (obligatoire), company, project, language | Une mesure évaluée pour l’entreprise quels que soient son statut ou ses thèmes, même quand une règle l’exclut : { match, subsidy, disclaimer }. Une évaluation de matching. |
| list_changes | since, type, source, region, subsidy, cursor, limit (1 à 50) | { changes, has_more, next_cursor, latest_seq } : les événements de GET /v1/changes, avec les mêmes filtres, le même curseur et chaque événement sous la même forme. Renvoyez next_cursor comme cursor pour continuer, puis plus tard pour n’obtenir que les nouveautés. À partir de la formule Developer. |
| list_sources | aucun | { sources }, chacune avec id, name, rights_mode, licence, freshness, measures, enabled. |
L’argument company annonce les propriétés courantes (code postal, région, taille, effectif, chiffre d’affaires, total du bilan, codes NACE, forme juridique, date de création, aides de minimis) et accepte toutes les propriétés d’une requête de matching. Un résultat revient à la fois en texte (JSON mis en forme) et en structuredContent. Un outil qui échoue (argument invalide, formule que la clé n’a pas, quota épuisé) renvoie un résultat avec isError: true et l’erreur de l’API dans structuredContent.error, pour que le modèle puisse lire ce qui s’est mal passé ; seul un message mal formé donne une erreur JSON-RPC.
Ce que le serveur dit au modèle
initialize contient des instructions qui se terminent par la phrase d’indépendance, en anglais : « Independent service. Not affiliated with, endorsed by, or operated by any government or public authority. Eligibility and awards are decided by the competent authority. » Chaque résultat d’outil la contient aussi. Un modèle qui reprend un résultat devrait dire « probablement » ou « peut-être » éligible, et renvoyer vers la page officielle.Connecter un client
Claude Code
claude mcp add --transport http subsido https://api.subsido.be/mcp \ --header "Authorization: Bearer sb_live_..."Ou dans le .mcp.json d’un projet, en lisant la clé depuis l’environnement pour qu’elle ne soit pas versionnée :
{
"mcpServers": {
"subsido": {
"type": "http",
"url": "https://api.subsido.be/mcp",
"headers": {
"Authorization": "Bearer ${SUBSIDY_API_KEY}"
}
}
}
}Claude Desktop
Claude Desktop lance des serveurs locaux depuis son fichier de configuration : un serveur distant avec une clé passe donc par le pont mcp-remote (qui demande Node.js). Dans claude_desktop_config.json (Settings, Developer, Edit config) :
{
"mcpServers": {
"subsido": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://api.subsido.be/mcp",
"--header",
"Authorization:${AUTH_HEADER}"
],
"env": {
"AUTH_HEADER": "Bearer sb_live_..."
}
}
}
}L’en-tête passe par une variable d’environnement, car certains systèmes découpent les arguments sur l’espace de Bearer …. Redémarrez Claude Desktop après la modification.
Autres clients
Tout client qui parle Streamable HTTP et sait envoyer un en-tête fonctionne : donnez-lui l’URL et l’en-tête Authorization. Beaucoup (Cursor, VS Code, Windsurf) acceptent un bloc JSON de cette forme :
{
"mcpServers": {
"subsido": {
"url": "https://api.subsido.be/mcp",
"headers": {
"Authorization": "Bearer sb_live_..."
}
}
}
}Un client qui ne lance que des serveurs locaux peut utiliser le pont mcp-remote comme ci-dessus.
À la main
Comme le serveur est sans état, curl est un client complet. Listez les outils, puis appelez-en un :
curl -X POST "https://api.subsido.be/mcp" \ -H "Authorization: Bearer sb_live_..." \ -H "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'curl -X POST "https://api.subsido.be/mcp" \ -H "Authorization: Bearer sb_live_..." \ -H "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "match_company", "arguments": {"company": {"postcode": "4000", "employees": 8, "legal_form": "srl"}, "project": {"topics": ["digitalisation"], "budget_eur": 15000}, "language": "fr", "limit": 5}}}'{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "{\n \"matches\": [ … ],\n \"matched\": 9,\n …\n}"
}
],
"structuredContent": {
"matches": [
"…"
],
"matched": 9,
"missing_information": [
"…"
],
"disclaimer": "Independent service. Not affiliated with, endorsed by, or operated by any government or public authority. Eligibility and awards are decided by the competent authority."
},
"isError": false
}
}- Erreurs du protocole lui-même :
-32700pour un corps qui n’est pas du JSON (avec HTTP 400),-32600quandjsonrpcne vaut pas"2.0",-32601pour une méthode inconnue. - Sans clé valide, l’endpoint répond
401, et avec la clé d’un compte sans formule402 subscription_required, dans la structure d’erreur habituelle de l’API, avant toute lecture du JSON-RPC. Voir authentification.
