68 lines
2.5 KiB
Python
68 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Apply the upstream Hermes API-server MCP refresh workaround.
|
|
|
|
Hermes 0.20.5 creates an API-server AIAgent without rebuilding its tool
|
|
snapshot from the live MCP registry. Healthy MCP servers that finish
|
|
discovery after process startup are therefore invisible through the OpenAI
|
|
compatible API even though ``hermes mcp test`` can reach them.
|
|
|
|
This startup patch is deliberately small and fail-closed: it accepts either
|
|
the pristine upstream source or an already patched source, and refuses to
|
|
modify an unknown future implementation.
|
|
"""
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
API_TARGET = Path("/opt/hermes/gateway/platforms/api_server.py")
|
|
API_ANCHOR = " agent = AIAgent(**agent_kwargs)\n"
|
|
API_PATCHED = """ # Athena workaround for upstream issue #69746: the API platform
|
|
# otherwise snapshots tools before the live MCP registry is attached.
|
|
agent = AIAgent(**agent_kwargs)
|
|
try:
|
|
from tools.mcp_tool import refresh_agent_mcp_tools
|
|
|
|
refresh_agent_mcp_tools(agent, quiet_mode=True)
|
|
except Exception:
|
|
logger.warning(
|
|
"api_server failed to refresh the live MCP tool registry",
|
|
exc_info=True,
|
|
)
|
|
"""
|
|
|
|
REFRESH_TARGET = Path("/opt/hermes/tools/mcp_tool.py")
|
|
REFRESH_ANCHOR = """ if new_names == current:
|
|
# No change → leave the live snapshot untouched (no churn), but
|
|
"""
|
|
REFRESH_PATCHED = """ if (
|
|
new_names == current
|
|
and new_defs == (getattr(agent, "tools", None) or [])
|
|
):
|
|
# Names and schemas are unchanged. Comparing schemas is required
|
|
# for the tool_search bridge, whose three public names stay fixed
|
|
# while its embedded deferred-tool catalog changes (#72560).
|
|
"""
|
|
|
|
|
|
def apply_patch(target: Path, anchor: str, replacement: str, label: str) -> None:
|
|
source = target.read_text(encoding="utf-8")
|
|
if replacement in source:
|
|
print(f"Hermes {label} patch already present")
|
|
elif source.count(anchor) == 1:
|
|
target.write_text(source.replace(anchor, replacement, 1), encoding="utf-8")
|
|
print(f"Applied Hermes {label} patch")
|
|
else:
|
|
raise SystemExit(
|
|
f"HERMES_START_REFUSED: upstream {target.name} changed; "
|
|
f"review the {label} patch before upgrading"
|
|
)
|
|
|
|
|
|
apply_patch(API_TARGET, API_ANCHOR, API_PATCHED, "API MCP refresh")
|
|
apply_patch(
|
|
REFRESH_TARGET,
|
|
REFRESH_ANCHOR,
|
|
REFRESH_PATCHED,
|
|
"tool-search catalog refresh",
|
|
)
|