MCP : catalogue embarqué de serveurs connus

Ajouter un serveur MCP demandait d'écrire soi-même `npx -y @scope/paquet …`
dans la modale, en devinant le nom du paquet. Le catalogue liste une vingtaine
de serveurs connus, commande déjà renseignée, classés par catégorie.

- internal/loki/mcp_catalog.json est EMBARQUÉ dans le binaire (go:embed), pas
  interrogé sur le réseau : Loki tourne hors ligne, et rien de ce qui s'exécute
  sur la machine ne vient d'un annuaire distant. Pour proposer un serveur de
  plus : éditer le fichier et recompiler.
- Choisir une entrée n'installe rien. Ça préremplit la modale d'ajout existante
  et l'utilisateur relit la commande avant d'enregistrer — un serveur stdio
  exécute un process arbitraire, au même titre que l'outil bash du mode agent.
  Aucune ligne de mcp_client.go n'est touchée : le catalogue s'arrête à
  l'affichage, tout le reste passe par l'API MCP déjà en place.
- Une entrée dont le runtime manque (npx ou uvx absent) le signale dans la
  liste, plutôt que de laisser l'utilisateur découvrir l'échec au démarrage du
  serveur.
- Les entrées qui réclament une clé d'API la rappellent avant l'enregistrement,
  au lieu d'enregistrer un serveur qui ne peut pas se connecter.
- Les entrées Python publiées avant le SDK MCP 2.0 sont épinglées avec
  `uvx --with "mcp<2"` : sans cela elles plantent sur ImportError: McpError.
- Le Dockerfile gagne uv/uvx (~35 Mo). Sans lui, 9 des 21 entrées s'affichent
  sans pouvoir démarrer dans le conteneur.

Intensité du raisonnement (REASONING_EFFORT)

L'interrupteur Raisonnement était binaire. llama-server accepte
`reasoning_effort` dans /v1/chat/completions : `none` coupe le raisonnement,
toute autre valeur est passée au gabarit jinja du modèle.

- Nouvelle clé de preset REASONING_EFFORT — donc réglée par modèle, comme le
  reste du preset. Vide = on n'envoie rien et le gabarit garde son comportement.
- Pas de repli à prévoir : un gabarit qui ne lit pas la valeur l'ignore sans
  erreur. En pratique seuls gpt-oss et apparentés changent de comportement, et
  le sous-titre du réglage le dit — promettre un effet universel serait faux.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 5 committed 2026-08-17 10:06:14 +02:00
1 parent e602adbbee
commit 847aad217b
15 files changed
+914 -4

No files matched your search

+33 -1
View File
@@ -168,7 +168,10 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
<!-- Même texte que celui rendu après chargement quand il n'y a aucun
serveur : sinon la carte partait vide puis grandissait d'une ligne. -->
<div id="mcp-list" class="mcp-list"><div class="muted" style="font-size:12px">(aucun serveur — ajoute un serveur fichiers, une base de données, une API…)</div></div>
<button class="addbtn" style="margin-top:6px" onclick="openMcp('')">+ ajouter un serveur</button>
<div class="mcp-actions">
<button class="addbtn" onclick="openMcpCatalog()">catalogue</button>
<button class="addbtn" onclick="openMcp('')">+ ajouter un serveur</button>
</div>
</div>
</div>
</div>
@@ -574,6 +577,23 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
</div>
</div>
</div>
<div id="mcp-catalog-modal" class="modal-ov" style="display:none" onclick="if(event.target===this)closeMcpCatalog()">
<div class="modal-card" style="max-width:640px">
<div class="modal-head">
<strong>Catalogue MCP</strong>
<button class="modal-x" onclick="closeMcpCatalog()" aria-label="Fermer"><svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.5 6.5l11 11"/><path d="M17.5 6.5l-11 11"/></svg></button>
</div>
<div class="modal-body">
<div class="muted" style="font-size:12px;margin-bottom:8px">
Serveurs connus, embarqués dans Loki — aucun appel réseau pour cette liste.
« Utiliser » remplit le formulaire d'ajout : la commande s'exécutera sur
cette machine, relis-la avant d'enregistrer.
</div>
<div id="mcp-catalog-tabs" class="mcp-cat-tabs"></div>
<div id="mcp-catalog-list" class="mcp-cat-list"></div>
</div>
</div>
</div>
<div id="mcp-modal" class="modal-ov" style="display:none" onclick="if(event.target===this)closeMcp()">
<div class="modal-card" style="max-width:560px">
<div class="modal-head">
@@ -821,6 +841,18 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
<span class="pe-row-l">Raisonnement<span class="pe-sub" id="s-reasoning-sub">réflexion étape par étape</span></span>
<span class="pe-row-c"><label class="pe-switch"><input type="checkbox" id="s-reasoning" onchange="cfgWriteKey('REASONING', this.checked?'on':'off')"><span class="pe-sl"></span></label></span>
</div>
<div class="pe-row" id="s-reasoning-effort-row">
<span class="pe-row-l">Intensité du raisonnement<span class="pe-sub" id="s-reasoning-effort-sub">envoyée au gabarit du modèle — auto = ne rien imposer</span></span>
<span class="pe-row-c">
<select id="s-reasoning-effort" class="pe-val" onchange="cfgWriteKey('REASONING_EFFORT', this.value)">
<option value="">auto</option>
<option value="none">aucune</option>
<option value="low">basse</option>
<option value="medium">moyenne</option>
<option value="high">haute</option>
</select>
</span>
</div>
<div class="pe-row">
<span class="pe-row-l">Flash attention<span class="pe-sub">plus rapide, moins de VRAM</span></span>
<span class="pe-row-c"><label class="pe-switch"><input type="checkbox" id="s-flash" onchange="eaSetValued('--flash-attn', this.checked?'on':'')"><span class="pe-sl"></span></label></span>