MAj API pour PE

This commit is contained in:
ocroguennec committed 2026-09-19 17:34:09 +02:00
1 parent c918de1e7d
commit 8817ac693d
7 files changed
+377 -25

No files matched your search

+70 -5
View File
@@ -30,7 +30,7 @@ const READ_ONLY_ANNOTATIONS = {
};
/**
* Enregistre les 9 outils de lecture de données sur `server`.
* Enregistre les 11 outils de lecture de données sur `server`.
*
* @param {import('@modelcontextprotocol/sdk/server/mcp.js').McpServer} server
* @param {object} ctx
@@ -85,7 +85,13 @@ export function registerDataTools(server, { apiGet, withLabel = (t) => t, withSo
"depuis le début\" de l'app, toujours un total, jamais filtré par année, " +
"reste valable même après un retrait complet des plateformes). Les " +
"montants d'investissements sont des soldes actuels (photo à " +
"aujourd'hui), pas des cumuls par période. Point d'entrée idéal pour " +
"aujourd'hui), pas des cumuls par période. Depuis le 20/09/26, une clé " +
"investissements_pe distincte résume le portefeuille Private Equity " +
"(nb_deals, total_investi, valorisation_totale, distributions_cumulees, " +
"tvpi/dpi/rvpi) — ces chiffres ne sont PAS inclus dans les champs " +
"ci-dessus (investissements, cash, gain_net_depuis_debut), qui restent " +
"strictement crowdlending ; voir crowdlending_list_investissements_pe " +
"pour le détail par deal. Point d'entrée idéal pour " +
"une vue d'ensemble avant d'aller chercher le détail."),
inputSchema: {
annee: z.number().int().optional()
@@ -146,6 +152,57 @@ export function registerDataTools(server, { apiGet, withLabel = (t) => t, withSo
},
);
server.registerTool(
'crowdlending_list_investissements_pe',
{
title: withLabel('Liste des investissements Private Equity'),
description: withSource(
"Liste les investissements Private Equity (deals) du portefeuille — distinct de " +
"crowdlending_list_investissements : un deal PE n'a ni échéancier connu à l'avance ni " +
"taux d'intérêt fixe, c'est un montant unique investi (montant_investi), valorisé " +
"périodiquement (derniere_valorisation, derniere_valorisation_date), avec des " +
"distributions perçues au fil du temps (distributions_cumulees, dont un sous-ensemble " +
"obligation_cumulee = intérêts sur capital non encore déployé). tvpi (Total Value to " +
"Paid-In = (dernière valorisation + distributions cumulées) / montant investi) est null " +
"tant qu'aucune valorisation n'a été saisie pour ce deal. Filtrable par statut et par " +
"workspace. Ne renvoie pas l'historique des valorisations ni le détail des distributions " +
"— utiliser crowdlending_get_investissement_pe pour le détail d'un deal."),
inputSchema: {
statut: z.enum(['en_attente', 'valide', 'cloture', 'perte_definitive'])
.optional()
.describe("Filtrer par statut. Omettre pour lister tous les deals."),
workspace: z.string().optional()
.describe('Slug du workspace à filtrer (utile si plusieurs workspaces Private Equity existent). Absent : tous confondus.'),
},
annotations: READ_ONLY_ANNOTATIONS,
},
async ({ statut, workspace }) => {
try { return toolResult(await apiGet('/investissements-pe', { statut, workspace })); }
catch (e) { return toolError(e); }
},
);
server.registerTool(
'crowdlending_get_investissement_pe',
{
title: withLabel("Détail d'un investissement Private Equity"),
description: withSource(
"Retourne le détail complet d'un deal Private Equity (identifié par son id, obtenu via " +
"crowdlending_list_investissements_pe), y compris valorisations (historique complet — " +
"la plus récente est celle utilisée pour derniere_valorisation/tvpi dans la liste), " +
"remboursements (distributions perçues : retour de capital, plus-value) et " +
"frais_operations (tous modes de règlement confondus)."),
inputSchema: {
id: z.number().int().positive().describe("Identifiant de l'investissement PE"),
},
annotations: READ_ONLY_ANNOTATIONS,
},
async ({ id }) => {
try { return toolResult(await apiGet(`/investissements-pe/${id}`)); }
catch (e) { return toolError(e); }
},
);
server.registerTool(
'crowdlending_list_remboursements',
{
@@ -196,17 +253,25 @@ export function registerDataTools(server, { apiGet, withLabel = (t) => t, withSo
"fois. Tous les autres modes (\"source\", \"portefeuille\", " +
"\"compte_courant\") représentent chacun une sortie d'argent réelle : " +
"c'est cet ensemble (tout sauf \"remboursement\") qui est déduit de " +
"gain_net_depuis_debut sur crowdlending_get_dashboard. Filtrable par période."),
"gain_net_depuis_debut sur crowdlending_get_dashboard. Depuis le " +
"20/09/26, couvre aussi bien les frais crowdlending que les frais " +
"Private Equity — `source_type` (\"crowdlending\" ou \"private_equity\") " +
"indique de quel côté vient chaque ligne (une ligne crowdlending porte " +
"investissement_id/nom_projet, une ligne PE porte investissement_pe_id/" +
"nom_deal). Filtrable par période et par workspace (paramètre workspace ; " +
"sans ce paramètre, les deux univers sont renvoyés ensemble)."),
inputSchema: {
date_debut: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
.describe('Date de début au format YYYY-MM-DD (incluse)'),
date_fin: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
.describe('Date de fin au format YYYY-MM-DD (incluse)'),
workspace: z.string().optional()
.describe('Slug du workspace à filtrer (ex. "crowdlending" ou "private-equity"). Absent : les deux univers confondus.'),
},
annotations: READ_ONLY_ANNOTATIONS,
},
async ({ date_debut, date_fin }) => {
try { return toolResult(await apiGet('/frais-operations', { date_debut, date_fin })); }
async ({ date_debut, date_fin, workspace }) => {
try { return toolResult(await apiGet('/frais-operations', { date_debut, date_fin, workspace })); }
catch (e) { return toolError(e); }
},
);