mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-12 03:42:08 +00:00
fix(mcp): coerce numeric tool args defensively
This commit is contained in:
parent
43cf72a458
commit
62c2f5d8d2
2 changed files with 132 additions and 1 deletions
32
mcp_serve.py
32
mcp_serve.py
|
|
@ -115,6 +115,25 @@ def _load_channel_directory() -> dict:
|
|||
return {}
|
||||
|
||||
|
||||
def _coerce_int(
|
||||
value,
|
||||
*,
|
||||
default: int,
|
||||
minimum: int,
|
||||
maximum: int,
|
||||
) -> int:
|
||||
"""Coerce value to int with fallback and clamping.
|
||||
|
||||
Used at MCP tool boundaries to handle invalid types from external clients.
|
||||
Returns default if value cannot be converted to int.
|
||||
"""
|
||||
try:
|
||||
coerced = int(value)
|
||||
except (TypeError, ValueError):
|
||||
coerced = default
|
||||
return max(minimum, min(coerced, maximum))
|
||||
|
||||
|
||||
def _extract_message_content(msg: dict) -> str:
|
||||
"""Extract text content from a message, handling multi-part content."""
|
||||
content = msg.get("content", "")
|
||||
|
|
@ -465,6 +484,7 @@ def create_mcp_server(event_bridge: Optional[EventBridge] = None) -> "FastMCP":
|
|||
limit: Maximum number of conversations to return (default 50)
|
||||
search: Optional text to filter conversations by name
|
||||
"""
|
||||
limit = _coerce_int(limit, default=50, minimum=1, maximum=200)
|
||||
entries = _load_sessions_index()
|
||||
conversations = []
|
||||
|
||||
|
|
@ -552,6 +572,7 @@ def create_mcp_server(event_bridge: Optional[EventBridge] = None) -> "FastMCP":
|
|||
session_key: The session key from conversations_list
|
||||
limit: Maximum number of messages to return (default 50, most recent)
|
||||
"""
|
||||
limit = _coerce_int(limit, default=50, minimum=1, maximum=200)
|
||||
entries = _load_sessions_index()
|
||||
entry = entries.get(session_key)
|
||||
if not entry:
|
||||
|
|
@ -664,6 +685,8 @@ def create_mcp_server(event_bridge: Optional[EventBridge] = None) -> "FastMCP":
|
|||
session_key: Optional filter to one conversation
|
||||
limit: Maximum events to return (default 20)
|
||||
"""
|
||||
after_cursor = _coerce_int(after_cursor, default=0, minimum=0, maximum=10**18)
|
||||
limit = _coerce_int(limit, default=20, minimum=1, maximum=200)
|
||||
result = bridge.poll_events(
|
||||
after_cursor=after_cursor,
|
||||
session_key=session_key,
|
||||
|
|
@ -689,10 +712,17 @@ def create_mcp_server(event_bridge: Optional[EventBridge] = None) -> "FastMCP":
|
|||
session_key: Optional filter to one conversation
|
||||
timeout_ms: Maximum wait time in milliseconds (default 30000)
|
||||
"""
|
||||
after_cursor = _coerce_int(after_cursor, default=0, minimum=0, maximum=10**18)
|
||||
timeout_ms = _coerce_int(
|
||||
timeout_ms,
|
||||
default=30000,
|
||||
minimum=0,
|
||||
maximum=300000,
|
||||
) # Cap at 5 minutes
|
||||
event = bridge.wait_for_event(
|
||||
after_cursor=after_cursor,
|
||||
session_key=session_key,
|
||||
timeout_ms=min(timeout_ms, 300000), # Cap at 5 minutes
|
||||
timeout_ms=timeout_ms,
|
||||
)
|
||||
if event:
|
||||
return json.dumps({"event": event}, indent=2)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue