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:
@@ -78,6 +78,27 @@ type DeviceMeshConfig struct {
|
||||
// client_timeout_s; we accept both. When both set, ClientTimeoutS wins
|
||||
// when non-zero.
|
||||
ClientTimeoutS int `yaml:"client_timeout_s,omitempty"`
|
||||
|
||||
// ExposeViaMCP gates the MCP bridge (issue 0145). When the field is
|
||||
// absent from YAML, the launcher defaults to "expose" (true) so an
|
||||
// agent with device_mesh.enabled=true gets the bridge for free. The
|
||||
// pointer shape lets us distinguish "unset" from "explicitly false";
|
||||
// use ShouldExposeViaMCP() to read it.
|
||||
ExposeViaMCP *bool `yaml:"expose_via_mcp,omitempty"`
|
||||
}
|
||||
|
||||
// ShouldExposeViaMCP reports whether the launcher must build the MCP bridge
|
||||
// for this device-mesh block. Returns false when the block is nil or not
|
||||
// enabled; otherwise returns true unless ExposeViaMCP is explicitly false.
|
||||
// Pure function — used by both the launcher and tests.
|
||||
func (d *DeviceMeshConfig) ShouldExposeViaMCP() bool {
|
||||
if d == nil || !d.Enabled {
|
||||
return false
|
||||
}
|
||||
if d.ExposeViaMCP != nil {
|
||||
return *d.ExposeViaMCP
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ResolvedHost returns Host if non-empty, otherwise DeviceID. Used by the
|
||||
@@ -211,6 +232,18 @@ type ClaudeCodeCfg struct {
|
||||
AddDirs []string `yaml:"add_dirs"` // additional directories accessible
|
||||
Streaming bool `yaml:"streaming"` // use --output-format stream-json for realtime progress
|
||||
ShowToolProgress bool `yaml:"show_tool_progress"` // edit Matrix message to show tool usage progress
|
||||
|
||||
// MCPConfigPath points to a JSON file consumed by `claude -p --mcp-config`.
|
||||
// Set at runtime by the launcher (issue 0145) when the agent has
|
||||
// device_mesh.enabled=true and ExposeViaMCP. Empty means claude runs
|
||||
// without external MCP servers. NEVER set in YAML — overrides the
|
||||
// runtime-generated bridge.
|
||||
MCPConfigPath string `yaml:"mcp_config_path,omitempty"`
|
||||
|
||||
// MCPServerName is the key inside the mcp-config JSON's "mcpServers"
|
||||
// map. claude prefixes tool names exposed to the model as
|
||||
// `mcp__<MCPServerName>__<tool>`. Defaults to "devicemesh" when empty.
|
||||
MCPServerName string `yaml:"mcp_server_name,omitempty"`
|
||||
}
|
||||
|
||||
type LLMReasoningCfg struct {
|
||||
|
||||
Reference in New Issue
Block a user