@@ -189,14 +189,27 @@ async def _run_claude_agent_sdk(self, prompt: str):
189189 # Log working directory and additional directories for debugging
190190 logging .info (f"Claude SDK CWD: { cwd_path } " )
191191 logging .info (f"Claude SDK additional directories: { add_dirs } " )
192-
192+
193+ # Load MCP server configuration from .mcp.json if present
194+ mcp_servers = self ._load_mcp_config (cwd_path )
195+ # Build allowed_tools list with MCP server
196+ allowed_tools = ["Read" ,"Write" ,"Bash" ,"Glob" ,"Grep" ,"Edit" ,"MultiEdit" ,"WebSearch" ,"WebFetch" ]
197+ if mcp_servers :
198+ # Add permissions for all tools from each MCP server
199+ for server_name in mcp_servers .keys ():
200+ allowed_tools .append (f"mcp__{ server_name } " )
201+ logging .info (f"MCP tool permissions granted for servers: { list (mcp_servers .keys ())} " )
202+
193203 options = ClaudeAgentOptions (
194- cwd = cwd_path , permission_mode = "acceptEdits" ,
195- allowed_tools = ["Read" ,"Write" ,"Bash" ,"Glob" ,"Grep" ,"Edit" ,"MultiEdit" ,"WebSearch" ,"WebFetch" ],
204+ cwd = cwd_path ,
205+ permission_mode = "acceptEdits" ,
206+ allowed_tools = allowed_tools ,
207+ mcp_servers = mcp_servers ,
196208 setting_sources = ["project" ],
197209 system_prompt = {"type" :"preset" ,
198210 "preset" :"claude_code" }
199211 )
212+
200213 # Best-effort set add_dirs if supported by SDK version
201214 try :
202215 if add_dirs :
@@ -1085,6 +1098,66 @@ def _get_repos_config(self) -> list[dict]:
10851098 return []
10861099 return []
10871100
1101+ def _load_mcp_config (self , cwd_path : str ) -> dict | None :
1102+ """Load MCP server configuration from .mcp.json file in the workspace.
1103+
1104+ Searches for .mcp.json in the following locations:
1105+ 1. MCP_CONFIG_PATH environment variable (if set)
1106+ 2. cwd_path/.mcp.json (main working directory)
1107+ 3. workspace root/.mcp.json (for multi-repo setups)
1108+
1109+ Returns the parsed MCP servers configuration dict, or None if not found.
1110+ """
1111+ try :
1112+ # Check if MCP discovery is disabled
1113+ if os .getenv ('MCP_CONFIG_SEARCH' , '' ).strip ().lower () in ('0' , 'false' , 'no' ):
1114+ logging .info ("MCP config search disabled by MCP_CONFIG_SEARCH env var" )
1115+ return None
1116+
1117+ # Option 1: Explicit path from environment
1118+ explicit_path = os .getenv ('MCP_CONFIG_PATH' , '' ).strip ()
1119+ if explicit_path :
1120+ mcp_file = Path (explicit_path )
1121+ if mcp_file .exists () and mcp_file .is_file ():
1122+ logging .info (f"Loading MCP config from MCP_CONFIG_PATH: { mcp_file } " )
1123+ with open (mcp_file , 'r' ) as f :
1124+ config = _json .load (f )
1125+ logging .info (f"MCP servers loaded: { list (config .get ('mcpServers' , {}).keys ())} " )
1126+ return config .get ('mcpServers' )
1127+ else :
1128+ logging .warning (f"MCP_CONFIG_PATH specified but file not found: { explicit_path } " )
1129+
1130+ # Option 2: Look in cwd_path (main working directory)
1131+ mcp_file = Path (cwd_path ) / ".mcp.json"
1132+ if mcp_file .exists () and mcp_file .is_file ():
1133+ logging .info (f"Found .mcp.json in working directory: { mcp_file } " )
1134+ with open (mcp_file , 'r' ) as f :
1135+ config = _json .load (f )
1136+ server_names = list (config .get ('mcpServers' , {}).keys ())
1137+ logging .info (f"MCP servers loaded from { mcp_file } : { server_names } " )
1138+ return config .get ('mcpServers' )
1139+
1140+ # Option 3: Look in workspace root (for multi-repo setups)
1141+ if self .context and self .context .workspace_path != cwd_path :
1142+ workspace_mcp_file = Path (self .context .workspace_path ) / ".mcp.json"
1143+ if workspace_mcp_file .exists () and workspace_mcp_file .is_file ():
1144+ logging .info (f"Found .mcp.json in workspace root: { workspace_mcp_file } " )
1145+ with open (workspace_mcp_file , 'r' ) as f :
1146+ config = _json .load (f )
1147+ server_names = list (config .get ('mcpServers' , {}).keys ())
1148+ logging .info (f"MCP servers loaded from { workspace_mcp_file } : { server_names } " )
1149+ return config .get ('mcpServers' )
1150+
1151+ logging .info ("No .mcp.json file found in any search location" )
1152+ return None
1153+
1154+ except _json .JSONDecodeError as e :
1155+ logging .error (f"Failed to parse .mcp.json: { e } " )
1156+ return None
1157+ except Exception as e :
1158+ logging .error (f"Error loading MCP config: { e } " )
1159+ return None
1160+
10881161
10891162async def main ():
10901163 """Main entry point for the Claude Code runner wrapper."""
0 commit comments