mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-13 05:07:40 +02:00
[haik]: rename _sanitize_server_name to sanitize_mcp_server_name (mcp_config canonical, agent_manager, prompt_context, main, tests, toolLabels comment), add no-underscore-names linter check banning leading-underscore Python names in backend, extract _models.py from classes.py for shared pydantic BaseModel field detection used by both classes and vulture checks, add vulture-ignore inline comment suppression and automatic pydantic field-name whitelisting to vulture.py, remove leaked payload arg from client.py sync, update README with new check docs and inline-ignore usage
This commit is contained in:
@@ -16,7 +16,6 @@ from backend.apps.agents.core.ws_manager import ws_manager
|
||||
from backend.apps.settings.settings import load_settings
|
||||
from backend.apps.tools_lib.tools_lib import (
|
||||
_load_all as load_all_tools,
|
||||
_sanitize_server_name,
|
||||
derive_mcp_config,
|
||||
load_builtin_permissions,
|
||||
load_trusted_sensitive_paths,
|
||||
@@ -25,6 +24,7 @@ from backend.apps.tools_lib.tools_lib import (
|
||||
refresh_hubspot_token,
|
||||
save_trusted_sensitive_paths,
|
||||
)
|
||||
from backend.apps.tools_lib.mcp_config import sanitize_mcp_server_name
|
||||
from backend.apps.agents.core.error_classify import (
|
||||
_is_auth_error,
|
||||
_is_free_trial_exhausted,
|
||||
@@ -173,7 +173,7 @@ class AgentManager:
|
||||
logger.info(f"[MCP-DEBUG] SKIPPED {tool.name}: '{tool_ref}' not in allowed_tools")
|
||||
continue
|
||||
|
||||
server_name = _sanitize_server_name(tool.name)
|
||||
server_name = sanitize_mcp_server_name(tool.name)
|
||||
if active_set is not None and server_name not in active_set:
|
||||
logger.info(f"[MCP-DEBUG] GATED {server_name}: not in session.active_mcps, model must call MCPActivate first")
|
||||
continue
|
||||
@@ -664,7 +664,7 @@ class AgentManager:
|
||||
for t in load_all_tools():
|
||||
if not t.mcp_config or not t.enabled:
|
||||
continue
|
||||
if _sanitize_server_name(t.name) == server_slug:
|
||||
if sanitize_mcp_server_name(t.name) == server_slug:
|
||||
return t.tool_permissions.get(mcp_tool_name, "ask")
|
||||
return _default_for(tool_name)
|
||||
|
||||
@@ -1039,7 +1039,7 @@ class AgentManager:
|
||||
# Emit a context_status event so the model and UI both know.
|
||||
try:
|
||||
_enabled = {
|
||||
_sanitize_server_name(t.name)
|
||||
sanitize_mcp_server_name(t.name)
|
||||
for t in load_all_tools()
|
||||
if t.mcp_config and t.enabled and t.auth_status in ("configured", "connected")
|
||||
}
|
||||
@@ -1340,7 +1340,7 @@ class AgentManager:
|
||||
|
||||
tool_def = next(
|
||||
(t for t in all_tools_list
|
||||
if t.mcp_config and t.enabled and _sanitize_server_name(t.name) == name),
|
||||
if t.mcp_config and t.enabled and sanitize_mcp_server_name(t.name) == name),
|
||||
None,
|
||||
)
|
||||
if tool_def:
|
||||
|
||||
@@ -3,8 +3,8 @@ from typing import Callable
|
||||
from backend.apps.modes.modes import load_mode
|
||||
from backend.apps.tools_lib.tools_lib import (
|
||||
_load_all as load_all_tools,
|
||||
_sanitize_server_name,
|
||||
)
|
||||
from backend.apps.tools_lib.mcp_config import sanitize_mcp_server_name
|
||||
from backend.apps.agents.manager.prompt.tool_catalog import _get_denied_tool_names, _is_fully_denied
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ def _build_connected_tools_context(allowed_tools: list[str], get_all_tool_names:
|
||||
if _is_fully_denied(tool):
|
||||
continue
|
||||
|
||||
server_name = _sanitize_server_name(tool.name)
|
||||
server_name = sanitize_mcp_server_name(tool.name)
|
||||
denied = _get_denied_tool_names(tool)
|
||||
tool_descs = {
|
||||
k: v for k, v in tool.tool_permissions.get("_tool_descriptions", {}).items()
|
||||
@@ -263,7 +263,7 @@ def _build_mcp_registry_summary(allowed_tools: list[str], active_mcps: list[str]
|
||||
continue
|
||||
if _is_fully_denied(tool):
|
||||
continue
|
||||
server_name = _sanitize_server_name(tool.name)
|
||||
server_name = sanitize_mcp_server_name(tool.name)
|
||||
desc = (getattr(tool, "description", None) or "").strip()
|
||||
if not desc:
|
||||
# Fall back to a generic blurb keyed on the tool name so the
|
||||
@@ -373,7 +373,7 @@ def _resolve_forced_tools(forced_tools: list[str] | None) -> str:
|
||||
if not t.enabled or not t.tool_permissions:
|
||||
continue
|
||||
tool_descs = t.tool_permissions.get("_tool_descriptions", {})
|
||||
server_name = _sanitize_server_name(t.name)
|
||||
server_name = sanitize_mcp_server_name(t.name)
|
||||
for tn, td in tool_descs.items():
|
||||
desc_map[tn] = td
|
||||
tool_to_server[tn] = server_name
|
||||
|
||||
@@ -40,7 +40,7 @@ def _patched_get_credentials():
|
||||
)
|
||||
|
||||
|
||||
gauth.get_credentials = _patched_get_credentials
|
||||
gauth.get_credentials = _patched_get_credentials # vulture-ignore: get_credentials
|
||||
|
||||
|
||||
from google_workspace_mcp import __main__ as _gw_main # noqa: E402,F401
|
||||
|
||||
@@ -296,7 +296,7 @@ def sync(data: dict | None = None) -> None:
|
||||
"t": time.time(),
|
||||
"submission_id": uuid4().hex,
|
||||
}
|
||||
_log("s", payload)
|
||||
_log("s")
|
||||
if _test_sink is not None:
|
||||
try:
|
||||
_test_sink("s", body)
|
||||
|
||||
@@ -11,7 +11,7 @@ from backend.apps.tools_lib.oauth_config import OPENSWARM_OAUTH_BASE_URL
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _sanitize_server_name(name: str) -> str:
|
||||
def sanitize_mcp_server_name(name: str) -> str:
|
||||
"""Convert a tool name into a valid MCP server identifier (alphanumeric + hyphens)."""
|
||||
return re.sub(r"[^a-z0-9]+", "-", name.lower()).strip("-")
|
||||
|
||||
|
||||
+4
-3
@@ -550,7 +550,8 @@ async def mcp_meta(action: str, request: Request):
|
||||
valid options instead of activating (anti-hallucination).
|
||||
"""
|
||||
from backend.apps.agents.agent_manager import agent_manager
|
||||
from backend.apps.tools_lib.tools_lib import _load_all as load_all_tools, _sanitize_server_name
|
||||
from backend.apps.tools_lib.tools_lib import _load_all as load_all_tools
|
||||
from backend.apps.tools_lib.mcp_config import sanitize_mcp_server_name
|
||||
|
||||
body = await request.json()
|
||||
parent_session_id = body.get("parent_session_id", "")
|
||||
@@ -586,7 +587,7 @@ async def mcp_meta(action: str, request: Request):
|
||||
for t in load_all_tools():
|
||||
if not (t.mcp_config and t.enabled and t.auth_status in ("configured", "connected")):
|
||||
continue
|
||||
sanitized = _sanitize_server_name(t.name)
|
||||
sanitized = sanitize_mcp_server_name(t.name)
|
||||
# Pull tool sub-action names from tool_permissions._tool_descriptions
|
||||
# so MCPSearch can match against capability names (e.g. "send_email").
|
||||
action_names: list[str] = []
|
||||
@@ -710,7 +711,7 @@ async def mcp_meta(action: str, request: Request):
|
||||
tool_hint = ""
|
||||
try:
|
||||
for t in load_all_tools():
|
||||
if _sanitize_server_name(t.name) != server_name:
|
||||
if sanitize_mcp_server_name(t.name) != server_name:
|
||||
continue
|
||||
descs = (t.tool_permissions or {}).get("_tool_descriptions", {}) or {}
|
||||
if not descs:
|
||||
|
||||
@@ -581,9 +581,9 @@ def test_mcp_brand_covers_curated_servers():
|
||||
"google-workspace", "microsoft-365", "slack", "discord",
|
||||
"notion", "airtable", "hubspot", "reddit", "youtube",
|
||||
}
|
||||
from backend.apps.tools_lib.tools_lib import _sanitize_server_name
|
||||
from backend.apps.tools_lib.mcp_config import sanitize_mcp_server_name
|
||||
for slug in curated:
|
||||
assert _sanitize_server_name(slug) == slug, (
|
||||
assert sanitize_mcp_server_name(slug) == slug, (
|
||||
f"curated slug {slug!r} is not in sanitized form"
|
||||
)
|
||||
|
||||
@@ -599,30 +599,30 @@ def test_curated_server_aliases_in_main():
|
||||
|
||||
|
||||
def test_sanitize_server_name_idempotent():
|
||||
"""_sanitize_server_name must be idempotent (sanitize twice = sanitize once)."""
|
||||
from backend.apps.tools_lib.tools_lib import _sanitize_server_name
|
||||
"""sanitize_mcp_server_name must be idempotent (sanitize twice = sanitize once)."""
|
||||
from backend.apps.tools_lib.mcp_config import sanitize_mcp_server_name
|
||||
test_inputs = [
|
||||
"Google Workspace", "Microsoft 365", "Slack", "Discord",
|
||||
"Notion", "Airtable", "HubSpot", "Reddit", "YouTube",
|
||||
"GitHub", "GitLab", "Jira",
|
||||
]
|
||||
for raw in test_inputs:
|
||||
once = _sanitize_server_name(raw)
|
||||
twice = _sanitize_server_name(once)
|
||||
once = sanitize_mcp_server_name(raw)
|
||||
twice = sanitize_mcp_server_name(once)
|
||||
assert once == twice, f"{raw}: sanitize not idempotent ({once} != {twice})"
|
||||
|
||||
|
||||
def test_sanitize_server_name_lowercase():
|
||||
from backend.apps.tools_lib.tools_lib import _sanitize_server_name
|
||||
assert _sanitize_server_name("Gmail") == "gmail"
|
||||
assert _sanitize_server_name("UPPERCASE") == "uppercase"
|
||||
from backend.apps.tools_lib.mcp_config import sanitize_mcp_server_name
|
||||
assert sanitize_mcp_server_name("Gmail") == "gmail"
|
||||
assert sanitize_mcp_server_name("UPPERCASE") == "uppercase"
|
||||
|
||||
|
||||
def test_sanitize_server_name_strips_special_chars():
|
||||
from backend.apps.tools_lib.tools_lib import _sanitize_server_name
|
||||
assert _sanitize_server_name("Foo Bar!") == "foo-bar"
|
||||
assert _sanitize_server_name("@x/y") == "x-y"
|
||||
assert _sanitize_server_name("a__b") == "a-b"
|
||||
from backend.apps.tools_lib.mcp_config import sanitize_mcp_server_name
|
||||
assert sanitize_mcp_server_name("Foo Bar!") == "foo-bar"
|
||||
assert sanitize_mcp_server_name("@x/y") == "x-y"
|
||||
assert sanitize_mcp_server_name("a__b") == "a-b"
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
@@ -635,10 +635,10 @@ def test_mcp_activate_handler_unknown_server():
|
||||
# We test the response shape independently of the FastAPI plumbing.
|
||||
# The handler is a closure inside main.py:mcp_meta_handler, so we
|
||||
# instead exercise the contract: invalid name surfaces alternatives.
|
||||
from backend.apps.tools_lib.tools_lib import _sanitize_server_name
|
||||
from backend.apps.tools_lib.mcp_config import sanitize_mcp_server_name
|
||||
valid = {"gmail", "slack", "google-workspace"}
|
||||
requested = "Gmail" # raw, needs sanitize
|
||||
sanitized = _sanitize_server_name(requested)
|
||||
sanitized = sanitize_mcp_server_name(requested)
|
||||
if sanitized in valid:
|
||||
status = "would_activate"
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user