fix(mcp): noms d'outils à tirets (Context7) + read_file sur dossier

Les noms MCP à tirets (resolve-library-id) cassaient le tool-calling :
modèles et grammaires mélangent tirets et underscores -> « Tool not
found ». Les noms exposés sont assainis en underscores avec table de
correspondance vers le vrai nom, et l'appel tolère les deux formes.

read_file sur un dossier disait « fichier introuvable » : message
explicite « c'est un dossier — utilise list_dir ».

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 4.8 committed 2026-07-19 11:26:27 +02:00
1 parent 7d1fa8913d
commit 9f56989cc2
3 files changed
+67 -10

No files matched your search

+15 -1
View File
@@ -12,7 +12,8 @@ from app import db, mcp_client # noqa: E402
db.init_db()
# Serveur MCP minimal : un outil "echo" qui renvoie son argument.
# Serveur MCP minimal : un outil "echo" + un outil au nom À TIRETS
# (comme Context7 « resolve-library-id »).
_FAKE_SERVER = textwrap.dedent("""
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("fake")
@@ -22,6 +23,11 @@ _FAKE_SERVER = textwrap.dedent("""
\"\"\"Répète le texte fourni.\"\"\"
return "echo:" + text
@mcp.tool(name="dash-tool-name")
def dash_tool(text: str) -> str:
\"\"\"Outil au nom à tirets.\"\"\"
return "dash:" + text
mcp.run()
""")
@@ -46,9 +52,17 @@ async def test_tools_exposed_and_called(fake_server_cmd, monkeypatch):
defs = await mgr.tool_definitions()
names = [d["function"]["name"] for d in defs]
assert "mcp_fake_echo" in names
# Nom à tirets exposé assaini (compatibilité function-calling).
assert "mcp_fake_dash_tool_name" in names
result = await mgr.call_tool("mcp_fake_echo", {"text": "bonjour"})
assert result["ok"] is True
assert "echo:bonjour" in result["content"]
# Appel via le nom assaini -> résolu vers le vrai nom à tirets.
dash = await mgr.call_tool("mcp_fake_dash_tool_name", {"text": "x"})
assert dash["ok"] is True and "dash:x" in dash["content"]
# Tolérance : le modèle répond avec des tirets au lieu d'underscores.
mixed = await mgr.call_tool("mcp_fake_dash-tool-name", {"text": "y"})
assert mixed["ok"] is True and "dash:y" in mixed["content"]
finally:
await mgr.aclose()
mcp_client.set_mcp_state("fake", enabled=False, params={})