fix(agent): register MCP tools after server initialization

Critical bug fix:
- MCP tools were never registered because servers loaded in Run()
  but tool registration happened in NewAgentLoop() with empty manager
- Move MCP tool registration from createToolRegistry to Run()
- Register MCP tools for both main agent and subag after successful server loading
- Add subagentManager field to AgentLoop for dynamic registration
- Add tool_count logging for better observability

This ensures MCP tools are properly available to both agent and subagents.
This commit is contained in:
yuchou87 2026-02-16 20:00:37 +08:00
parent 2318232b71
commit 0f6fadb445

View file

@ -32,22 +32,23 @@ import (
) )
type AgentLoop struct { type AgentLoop struct {
bus *bus.MessageBus bus *bus.MessageBus
provider providers.LLMProvider provider providers.LLMProvider
workspace string workspace string
model string model string
contextWindow int // Maximum context window size in tokens contextWindow int // Maximum context window size in tokens
maxIterations int maxIterations int
sessions *session.SessionManager sessions *session.SessionManager
state *state.Manager state *state.Manager
contextBuilder *ContextBuilder contextBuilder *ContextBuilder
tools *tools.ToolRegistry tools *tools.ToolRegistry
mcpManager *mcp.Manager // MCP server manager for resource cleanup mcpManager *mcp.Manager // MCP server manager for resource cleanup
mcpConfig *config.Config // Config for lazy MCP initialization mcpConfig *config.Config // Config for lazy MCP initialization
mcpInitOnce sync.Once // Ensures MCP is initialized only once mcpInitOnce sync.Once // Ensures MCP is initialized only once
running atomic.Bool subagentManager *tools.SubagentManager // Subagent manager for MCP tool registration
summarizing sync.Map // Tracks which sessions are currently being summarized running atomic.Bool
channelManager *channels.Manager summarizing sync.Map // Tracks which sessions are currently being summarized
channelManager *channels.Manager
} }
// processOptions configures how a message is processed // processOptions configures how a message is processed
@ -105,22 +106,8 @@ func createToolRegistry(workspace string, restrict bool, cfg *config.Config, msg
}) })
registry.Register(messageTool) registry.Register(messageTool)
// Register MCP tools from all connected servers // Note: MCP tools are registered dynamically in Run() after servers are loaded
if mcpManager != nil { // This ensures we use the agent's lifecycle context for MCP connections
servers := mcpManager.GetServers()
for serverName, conn := range servers {
for _, tool := range conn.Tools {
mcpTool := tools.NewMCPTool(mcpManager, serverName, tool)
registry.Register(mcpTool)
logger.DebugCF("agent", "Registered MCP tool",
map[string]interface{}{
"server": serverName,
"tool": tool.Name,
"name": mcpTool.Name(),
})
}
}
}
return registry return registry
} }
@ -162,19 +149,20 @@ func NewAgentLoop(cfg *config.Config, msgBus *bus.MessageBus, provider providers
contextBuilder.SetToolsRegistry(toolsRegistry) contextBuilder.SetToolsRegistry(toolsRegistry)
return &AgentLoop{ return &AgentLoop{
bus: msgBus, bus: msgBus,
provider: provider, provider: provider,
workspace: workspace, workspace: workspace,
model: cfg.Agents.Defaults.Model, model: cfg.Agents.Defaults.Model,
contextWindow: cfg.Agents.Defaults.MaxTokens, // Restore context window for summarization contextWindow: cfg.Agents.Defaults.MaxTokens, // Restore context window for summarization
maxIterations: cfg.Agents.Defaults.MaxToolIterations, maxIterations: cfg.Agents.Defaults.MaxToolIterations,
sessions: sessionsManager, sessions: sessionsManager,
state: stateManager, state: stateManager,
contextBuilder: contextBuilder, contextBuilder: contextBuilder,
tools: toolsRegistry, tools: toolsRegistry,
mcpManager: mcpManager, mcpManager: mcpManager,
mcpConfig: cfg, // Store config for lazy initialization in Run() mcpConfig: cfg, // Store config for lazy initialization in Run()
summarizing: sync.Map{}, subagentManager: subagentManager,
summarizing: sync.Map{},
} }
} }
@ -189,6 +177,34 @@ func (al *AgentLoop) Run(ctx context.Context) error {
map[string]interface{}{ map[string]interface{}{
"error": err.Error(), "error": err.Error(),
}) })
} else {
// Register for both main agent and subagents
servers := al.mcpManager.GetServers()
toolCount := 0
for serverName, conn := range servers {
for _, tool := range conn.Tools {
mcpTool := tools.NewMCPTool(al.mcpManager, serverName, tool)
al.tools.Register(mcpTool)
// Also register for subagent
if al.subagentManager != nil {
al.subagentManager.RegisterTool(tools.NewMCPTool(al.mcpManager, serverName, tool))
}
toolCount++
logger.DebugCF("agent", "Registered MCP tool",
map[string]interface{}{
"server": serverName,
"tool": tool.Name,
"name": mcpTool.Name(),
})
}
}
logger.InfoCF("agent", "MCP tools registered successfully",
map[string]interface{}{
"server_count": len(servers),
"tool_count": toolCount,
})
} }
}) })