feat(0145-2,3,4): schema + launcher wiring + claude --mcp-config arg

Pieza 2 — schema (internal/config/schema.go):
- DeviceMeshConfig.ExposeViaMCP *bool: pointer para distinguir "no
  establecido" vs "false explicito". Helper ShouldExposeViaMCP() devuelve
  true cuando enabled && (nil || *true).
- ClaudeCodeCfg.MCPConfigPath y MCPServerName: poblados en runtime por
  la launcher, NUNCA por YAML.

Pieza 3 — launcher wiring (devagents/mcp_bridge.go + cmd/launcher/main.go):
- ApplyMCPBridge(cfg, logger): si DeviceMesh.ShouldExposeViaMCP() y
  provider=claude-code, resuelve binario devicemesh-mcp (junto al
  launcher), URL device_agent (env override > YAML), lista tools allowed
  (RegisterBuiltins + FilterByAllowed igual que registry_build.go), y
  escribe /tmp/<agent_id>-mcp-config.json (0600).
- Aplica overrides a cfg.LLM.Primary.ClaudeCode: MCPConfigPath,
  AllowedTools (formato mcp__<server>__<tool>), DisableTools=false
  defensivo.
- Launcher main.go llama ApplyMCPBridge inmediatamente despues de
  config.Load, ANTES de devagents.New (que es donde se construye el
  CompleteFunc del provider).

Pieza 4 — claude args (shell/llm/claudecode.go):
- buildClaudeArgs ahora emite "--mcp-config <path>" cuando
  cfg.MCPConfigPath no esta vacio.
- Guard defensivo: DisableTools=true + AllowedTools no vacio ahora
  produce solo --allowedTools (efectivamente ignora DisableTools). El
  launcher ya lo previene en ApplyMCPBridge, pero esto protege a
  callers directos.

Build limpio con goolm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 18:28:34 +02:00
parent 15596df7e4
commit b92a350023
4 changed files with 368 additions and 1 deletions
+15 -1
View File
@@ -449,7 +449,21 @@ func buildClaudeArgs(cfg config.ClaudeCodeCfg, req coretypes.CompletionRequest)
args = append(args, "--system-prompt", req.SystemPrompt)
}
if cfg.DisableTools {
// Issue 0145: --mcp-config tells claude where to find external MCP
// servers (per-agent devicemesh bridge). Must come BEFORE --allowedTools
// because the allowed list usually references `mcp__<server>__<tool>`
// names that only exist once the MCP config is loaded.
if cfg.MCPConfigPath != "" {
args = append(args, "--mcp-config", cfg.MCPConfigPath)
}
// Defensive: DisableTools=true plus a non-empty AllowedTools is a
// contradiction. The launcher's ApplyMCPBridge already forces
// DisableTools=false in that case, but this guard keeps direct callers
// safe too.
effectiveDisableTools := cfg.DisableTools && len(cfg.AllowedTools) == 0
if effectiveDisableTools {
args = append(args, "--tools", "")
} else {
if len(cfg.AllowedTools) > 0 {