Fix VS Code MCP server initialization crash and multi-agent architecture
CRITICAL FIX:
- Removed auto-registration during initialization that was causing crashes
- Fixed pattern match error with Inbox.start_link (already_started case)
- Changed architecture to require explicit agent registration with unique IDs
MULTI-AGENT SUPPORT:
- Agents must now register themselves with unique identifiers (e.g., 'Green Platypus')
- register_agent tool now works without requiring prior agent_id
- All other tools require agent_id parameter to identify the calling agent
- Proper error handling for missing agent_id in tool calls
ARCHITECTURE CHANGE:
- One MCP server instance serves multiple agents (as per VS Code design)
- Removed auto-registration of 'GitHub Copilot' agent during initialization
- Each agent must explicitly call register_agent before using other tools
This fixes the VS Code connection error:
MatchError: no match of right hand side value: {:error, {:already_started, #PID<0.215.0>}}
This commit is contained in:
@@ -26,7 +26,7 @@ defmodule AgentCoordinator.MCPServer do
|
||||
@mcp_tools [
|
||||
%{
|
||||
"name" => "register_agent",
|
||||
"description" => "Register a new agent with the coordination system",
|
||||
"description" => "Register a new agent with the coordination system. Each agent must choose a unique identifier (e.g., 'Green Platypus', 'Blue Koala') and include their agent_id in all subsequent tool calls to identify themselves.",
|
||||
"inputSchema" => %{
|
||||
"type" => "object",
|
||||
"properties" => %{
|
||||
@@ -381,36 +381,57 @@ defmodule AgentCoordinator.MCPServer do
|
||||
|
||||
def handle_call({:mcp_request, request}, from, state) do
|
||||
# Extract agent context for automatic heartbeat management
|
||||
agent_context = extract_agent_context(request, from, state)
|
||||
case extract_agent_context(request, from, state) do
|
||||
{:error, error_message} ->
|
||||
# Return error if agent context extraction fails (unless this is register_agent)
|
||||
method = Map.get(request, "method")
|
||||
if method == "tools/call" and
|
||||
Map.get(request, "params", %{}) |> Map.get("name") == "register_agent" do
|
||||
# Allow register_agent to proceed without agent_id
|
||||
response = process_mcp_request(request)
|
||||
{:reply, response, state}
|
||||
else
|
||||
error_response = %{
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => Map.get(request, "id"),
|
||||
"error" => %{
|
||||
"code" => -32602,
|
||||
"message" => error_message
|
||||
}
|
||||
}
|
||||
{:reply, error_response, state}
|
||||
end
|
||||
|
||||
# Send pre-operation heartbeat if we have agent context
|
||||
if agent_context[:agent_id] do
|
||||
TaskRegistry.heartbeat_agent(agent_context[:agent_id])
|
||||
update_session_activity(agent_context[:agent_id])
|
||||
end
|
||||
agent_context ->
|
||||
# Send pre-operation heartbeat if we have agent context
|
||||
if agent_context[:agent_id] do
|
||||
TaskRegistry.heartbeat_agent(agent_context[:agent_id])
|
||||
update_session_activity(agent_context[:agent_id])
|
||||
end
|
||||
|
||||
# Process the request
|
||||
response = process_mcp_request(request)
|
||||
# Process the request
|
||||
response = process_mcp_request(request)
|
||||
|
||||
# Send post-operation heartbeat and update session activity
|
||||
if agent_context[:agent_id] do
|
||||
TaskRegistry.heartbeat_agent(agent_context[:agent_id])
|
||||
update_session_activity(agent_context[:agent_id])
|
||||
# Send post-operation heartbeat and update session activity
|
||||
if agent_context[:agent_id] do
|
||||
TaskRegistry.heartbeat_agent(agent_context[:agent_id])
|
||||
update_session_activity(agent_context[:agent_id])
|
||||
|
||||
# Add heartbeat metadata to successful responses
|
||||
enhanced_response = case response do
|
||||
%{"result" => _} = success ->
|
||||
Map.put(success, "_heartbeat_metadata", %{
|
||||
agent_id: agent_context[:agent_id],
|
||||
timestamp: DateTime.utc_now()
|
||||
})
|
||||
error_result ->
|
||||
error_result
|
||||
end
|
||||
# Add heartbeat metadata to successful responses
|
||||
enhanced_response = case response do
|
||||
%{"result" => _} = success ->
|
||||
Map.put(success, "_heartbeat_metadata", %{
|
||||
agent_id: agent_context[:agent_id],
|
||||
timestamp: DateTime.utc_now()
|
||||
})
|
||||
error_result ->
|
||||
error_result
|
||||
end
|
||||
|
||||
{:reply, enhanced_response, state}
|
||||
else
|
||||
{:reply, response, state}
|
||||
{:reply, enhanced_response, state}
|
||||
else
|
||||
{:reply, response, state}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -515,8 +536,14 @@ defmodule AgentCoordinator.MCPServer do
|
||||
# Add agent to codebase registry
|
||||
CodebaseRegistry.add_agent_to_codebase(agent.codebase_id, agent.id)
|
||||
|
||||
# Start inbox for the agent
|
||||
{:ok, _pid} = Inbox.start_link(agent.id)
|
||||
# Start inbox for the agent (handle already started case)
|
||||
case Inbox.start_link(agent.id) do
|
||||
{:ok, _pid} -> :ok
|
||||
{:error, {:already_started, _pid}} -> :ok
|
||||
{:error, reason} ->
|
||||
Logger.warning("Failed to start inbox for agent #{agent.id}: #{inspect(reason)}")
|
||||
:ok
|
||||
end
|
||||
|
||||
# Track the session if we have caller info
|
||||
track_agent_session(agent.id, name, capabilities)
|
||||
@@ -1364,34 +1391,9 @@ defmodule AgentCoordinator.MCPServer do
|
||||
agent_id = request["params"]["arguments"]["agent_id"]
|
||||
%{agent_id: agent_id}
|
||||
|
||||
# If no explicit agent_id, try to auto-register a default agent
|
||||
# If no explicit agent_id, return error - agents must register first
|
||||
true ->
|
||||
default_agent_context()
|
||||
end
|
||||
end
|
||||
|
||||
defp default_agent_context do
|
||||
# Create or use a default agent session for GitHub Copilot
|
||||
default_agent_id = "github_copilot_session"
|
||||
|
||||
# Check if we already have this agent in our session tracking
|
||||
case Process.get({:agent_session, default_agent_id}) do
|
||||
nil ->
|
||||
# Auto-register GitHub Copilot as an agent
|
||||
case register_agent(%{
|
||||
"name" => "GitHub Copilot",
|
||||
"capabilities" => ["coding", "analysis", "review", "documentation"]
|
||||
}) do
|
||||
{:ok, %{agent_id: agent_id}} ->
|
||||
%{agent_id: agent_id}
|
||||
|
||||
_ ->
|
||||
# Fallback to default ID even if registration fails
|
||||
%{agent_id: default_agent_id}
|
||||
end
|
||||
|
||||
_session_info ->
|
||||
%{agent_id: default_agent_id}
|
||||
{:error, "Missing agent_id. Agents must register themselves using register_agent before calling other tools."}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -10,12 +10,6 @@
|
||||
"auto_restart": true,
|
||||
"description": "Context7 library documentation server"
|
||||
},
|
||||
"mcp_figma": {
|
||||
"url": "http://127.0.0.1:3845/mcp",
|
||||
"type": "http",
|
||||
"auto_restart": true,
|
||||
"description": "Figma design integration server"
|
||||
},
|
||||
"mcp_filesystem": {
|
||||
"type": "stdio",
|
||||
"command": "bunx",
|
||||
|
||||
Reference in New Issue
Block a user