diff --git a/backend/apps/agents/agent_manager.py b/backend/apps/agents/agent_manager.py
index 0cc6234f..85a85580 100644
--- a/backend/apps/agents/agent_manager.py
+++ b/backend/apps/agents/agent_manager.py
@@ -135,24 +135,33 @@ class AgentManager:
mcp_servers: dict = {}
all_tools = load_all_tools()
mcp_tools = [t for t in all_tools if t.mcp_config and t.enabled and t.auth_status in ("configured", "connected")]
+ logger.info(f"[MCP-DEBUG] Building MCP servers. {len(mcp_tools)} MCP tools found, allowed_tools has {len(allowed_tools)} entries")
for tool in mcp_tools:
tool_ref = f"mcp:{tool.name}"
if tool_ref not in allowed_tools and allowed_tools != get_all_tool_names():
if not any(tool_ref == at for at in allowed_tools):
+ logger.info(f"[MCP-DEBUG] SKIPPED {tool.name}: '{tool_ref}' not in allowed_tools")
continue
if _is_fully_denied(tool):
+ logger.info(f"[MCP-DEBUG] SKIPPED {tool.name}: fully denied")
continue
if tool.auth_type == "oauth2" and tool.auth_status == "connected":
- await refresh_google_token(tool)
+ refreshed = await refresh_google_token(tool)
+ logger.info(f"[MCP-DEBUG] {tool.name} token refresh: {'OK' if refreshed else 'FAILED'}")
config = derive_mcp_config(tool)
if config:
server_name = _sanitize_server_name(tool.name)
mcp_servers[server_name] = config
+ env_keys = list(config.get("env", {}).keys())
+ logger.info(f"[MCP-DEBUG] ADDED {server_name}: command={config.get('command')}, args={config.get('args')}, env_keys={env_keys}")
+ else:
+ logger.warning(f"[MCP-DEBUG] {tool.name}: derive_mcp_config returned None")
+ logger.info(f"[MCP-DEBUG] Final mcp_servers: {list(mcp_servers.keys())}")
return mcp_servers
def _build_connected_tools_context(self, allowed_tools: list[str]) -> str | None:
@@ -489,6 +498,7 @@ class AgentManager:
from claude_agent_sdk.types import (
HookMatcher, PermissionResultAllow, PermissionResultDeny,
TextBlock, ToolUseBlock, StreamEvent,
+ SystemMessage,
)
except ImportError:
logger.warning("claude_agent_sdk not installed, running in mock mode")
@@ -858,6 +868,15 @@ class AgentManager:
else:
effective_allowed.append(f"mcp__{name}__*")
+ # Log effective tool lists
+ google_allowed = [t for t in effective_allowed if "google-workspace" in t]
+ reddit_allowed = [t for t in effective_allowed if "reddit" in t]
+ builtin_allowed = [t for t in effective_allowed if not t.startswith("mcp__")]
+ logger.info(f"[MCP-DEBUG] effective_allowed: {len(effective_allowed)} total "
+ f"(builtins={len(builtin_allowed)}, google={len(google_allowed)}, reddit={len(reddit_allowed)})")
+ if effective_disallowed:
+ logger.info(f"[MCP-DEBUG] effective_disallowed: {effective_disallowed}")
+
options_kwargs = {
"model": session.model,
"max_buffer_size": 5 * 1024 * 1024,
@@ -875,6 +894,7 @@ class AgentManager:
from backend.apps.nine_router import is_running as _9r_running
if global_settings.anthropic_api_key:
options_kwargs["env"] = {"ANTHROPIC_API_KEY": global_settings.anthropic_api_key}
+ logger.info("[MCP-DEBUG] Using direct API key")
elif _9r_running():
options_kwargs["env"] = {
"ANTHROPIC_API_KEY": "9router",
@@ -882,10 +902,13 @@ class AgentManager:
}
# --bare skips CLI's own OAuth/keychain auth, uses only ANTHROPIC_API_KEY
options_kwargs["extra_args"] = {"bare": None}
+ logger.info("[MCP-DEBUG] Using 9Router (bare mode)")
else:
raise ValueError("No AI provider configured. Set an API key or connect a subscription.")
if mcp_servers:
options_kwargs["mcp_servers"] = mcp_servers
+ mcp_json_len = len(json.dumps({"mcpServers": mcp_servers}))
+ logger.info(f"[MCP-DEBUG] mcp_servers passed to SDK: {list(mcp_servers.keys())}, JSON length={mcp_json_len}")
if composed_prompt:
options_kwargs["system_prompt"] = composed_prompt
if session.max_turns:
@@ -899,7 +922,9 @@ class AgentManager:
if fork_session:
options_kwargs["fork_session"] = True
+ logger.info(f"[MCP-DEBUG] Creating ClaudeAgentOptions with model={session.model}")
options = ClaudeAgentOptions(**options_kwargs)
+ logger.info(f"[MCP-DEBUG] ClaudeAgentOptions created. Starting query...")
async def prompt_stream():
yield {
@@ -911,11 +936,21 @@ class AgentManager:
stream_tool_msg_ids_ordered = []
stream_block_index_map = {}
_turn_number = 0
+ _first_event = True
async for message in query(
prompt=prompt_stream(),
options=options,
):
+ if _first_event:
+ logger.info(f"[MCP-DEBUG] First event received: {type(message).__name__}")
+ _first_event = False
+
+ # Log system messages (MCP server status, errors, etc.)
+ if isinstance(message, SystemMessage):
+ raw = message.__dict__ if hasattr(message, '__dict__') else str(message)
+ logger.info(f"[MCP-DEBUG] SystemMessage: {raw}")
+
if isinstance(message, StreamEvent):
event = message.event
event_type = event.get("type")
diff --git a/electron/build/entitlements.mac.plist b/electron/build/entitlements.mac.plist
index 7ace8487..7491bffe 100644
--- a/electron/build/entitlements.mac.plist
+++ b/electron/build/entitlements.mac.plist
@@ -6,6 +6,8 @@
com.apple.security.cs.allow-jit
+ com.apple.security.cs.disable-library-validation
+
com.apple.security.network.client
com.apple.security.network.server
diff --git a/electron/package-lock.json b/electron/package-lock.json
index 43651a59..9309677e 100644
--- a/electron/package-lock.json
+++ b/electron/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "openswarm",
- "version": "1.0.17",
+ "version": "1.0.18",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openswarm",
- "version": "1.0.17",
+ "version": "1.0.18",
"hasInstallScript": true,
"dependencies": {
"electron-updater": "^6.3.0",