mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-11-06 05:17:15 +00:00
fix(desktop): compare a re-declared MCP server after env expansion
load_config() expands ${VAR} in a native mcp_servers entry while the
package declaration keeps its placeholders until connect, so a user who
re-declares the package server (to widen its trust) with an env-backed
argument compared as a different server and the package lost its cards.
Both sides now compare after the same connect-time expansion.
This commit is contained in:
1 parent
7c4e7e5517
commit
567569267a
2 files changed
+22
-7
No files matched your search
@@ -38,13 +38,13 @@ def _native_plugin(root: Path, name: str, tool: str, extra: str = "") -> None:
|
||||
(plugin / "__init__.py").write_text(_NATIVE % {"name": name, "tool": tool, "extra": extra % {"name": name}})
|
||||
|
||||
|
||||
def _portable_plugin(root: Path) -> None:
|
||||
def _portable_plugin(root: Path, args: list[str] | None = None) -> None:
|
||||
from hermes_cli.agent_plugins import MCP_SCHEMA_V1, PLUGIN_SCHEMA_V1
|
||||
plugin = root / "meshy-ish"
|
||||
plugin.mkdir(parents=True)
|
||||
(plugin / "plugin.json").write_text(json.dumps({"$schema": PLUGIN_SCHEMA_V1, "name": "meshy-ish"}))
|
||||
(plugin / "mcp.json").write_text(json.dumps({
|
||||
"$schema": MCP_SCHEMA_V1, "mcpServers": {"meshy-3d": {"type": "stdio", "command": "python"}}}))
|
||||
"$schema": MCP_SCHEMA_V1, "mcpServers": {"meshy-3d": {"type": "stdio", "command": "python", **({"args": args} if args else {})}}}))
|
||||
|
||||
|
||||
def test_list_reports_only_tools_the_package_itself_registered():
|
||||
@@ -81,10 +81,10 @@ def test_list_reports_only_tools_the_package_itself_registered():
|
||||
|
||||
|
||||
def _list_meshy_tools(live: list[str] | None = None, lazy: list[str] | None = None,
|
||||
native: dict | None = None) -> list[str]:
|
||||
native: dict | None = None, args: list[str] | None = None) -> list[str]:
|
||||
root = Path(os.environ["HERMES_HOME"]) / "plugins"
|
||||
if not (root / "meshy-ish").exists():
|
||||
_portable_plugin(root)
|
||||
_portable_plugin(root, args)
|
||||
cfg = load_config()
|
||||
cfg["plugins"] = {"enabled": ["meshy-ish"]}
|
||||
cfg["mcp_servers"] = native or {}
|
||||
@@ -114,3 +114,14 @@ def test_a_native_server_of_the_same_name_credits_the_package_only_when_it_runs_
|
||||
assert _list_meshy_tools(live, native={"meshy-3d": {"command": "my-own-server"}}) == []
|
||||
# The same server re-declared natively (the way a user widens its trust) stays the package's.
|
||||
assert _list_meshy_tools(live, native={"meshy-3d": {"command": "python", "trust": "high"}}) == live
|
||||
|
||||
|
||||
def test_a_native_redeclaration_with_env_backed_args_still_credits_the_package(monkeypatch):
|
||||
# load_config() expands ${VAR} in the native entry while the package's declaration keeps the
|
||||
# placeholder until connect: the same server must still compare equal.
|
||||
monkeypatch.setenv("MESHY_PROBE_TOKEN", "tok-123")
|
||||
live = ["mcp__meshy_3d__download"]
|
||||
args = ["-m", "meshy", "--key", "${MESHY_PROBE_TOKEN}"]
|
||||
native = {"meshy-3d": {"command": "python", "args": args, "trust": "high"}}
|
||||
assert _list_meshy_tools(live, native=native, args=args) == live
|
||||
|
||||
@@ -60,9 +60,13 @@ def _plugin_server_rows(
|
||||
|
||||
def _server_identity(cfg: object) -> tuple:
|
||||
"""What a server config runs: a same-name native entry that runs the same thing is the user
|
||||
widening the package server's trust; anything else is the user's own, different server."""
|
||||
cfg = cfg if isinstance(cfg, dict) else {}
|
||||
return cfg.get("command"), tuple(cfg.get("args") or ()), cfg.get("url")
|
||||
widening the package server's trust; anything else is the user's own, different server. Both
|
||||
sides compare after the connect-time ``${VAR}`` expansion (``load_config`` already expanded the
|
||||
native entry; the package's declaration keeps its placeholders until connect)."""
|
||||
cfg = _tools_mod("tools.mcp_tool_config")._interpolate_env_vars(cfg if isinstance(cfg, dict) else {})
|
||||
args = cfg.get("args") or ()
|
||||
return (str(cfg.get("command") or ""), tuple(str(a) for a in (args if isinstance(args, list) else [args])),
|
||||
str(cfg.get("url") or ""))
|
||||
|
||||
|
||||
def _portable_server_tools(manager, native: dict) -> dict[str, set[str]]:
|
||||
|
||||
Reference in new issue
Block a user