defmodule AgentCoordinator do @moduledoc """ Agent Coordinator - A Model Context Protocol (MCP) server for multi-agent coordination. Agent Coordinator enables multiple AI agents to work together seamlessly across codebases without conflicts. It provides intelligent task distribution, real-time communication, and cross-codebase coordination through a unified MCP interface. ## Key Features - **Multi-Agent Coordination**: Register multiple AI agents with different capabilities - **Intelligent Task Distribution**: Automatically assigns tasks based on agent capabilities - **Cross-Codebase Support**: Coordinate work across multiple repositories - **Unified MCP Interface**: Single server providing access to multiple external MCP servers - **Automatic Task Tracking**: Every tool usage becomes a tracked task - **Real-Time Communication**: Heartbeat system for agent liveness and coordination ## Quick Start To start the Agent Coordinator: # Start the MCP server ./scripts/mcp_launcher.sh # Or in development mode iex -S mix ## Main Components - `AgentCoordinator.MCPServer` - Core MCP protocol implementation - `AgentCoordinator.TaskRegistry` - Task management and agent coordination - `AgentCoordinator.UnifiedMCPServer` - Unified interface to external MCP servers - `AgentCoordinator.CodebaseRegistry` - Multi-repository support - `AgentCoordinator.VSCodeToolProvider` - VS Code integration tools ## MCP Tools Available ### Agent Coordination - `register_agent` - Register an agent with capabilities - `create_task` - Create tasks with requirements - `get_next_task` - Get assigned tasks - `complete_task` - Mark tasks complete - `get_task_board` - View all agent status - `heartbeat` - Maintain agent liveness ### Codebase Management - `register_codebase` - Register repositories - `create_cross_codebase_task` - Tasks spanning multiple repos - `add_codebase_dependency` - Define repository relationships ### External Tool Access All tools from external MCP servers are automatically available through the unified interface, including filesystem, context7, memory, and other servers. ## Usage Example # Register an agent AgentCoordinator.MCPServer.handle_mcp_request(%{ "method" => "tools/call", "params" => %{ "name" => "register_agent", "arguments" => %{ "name" => "MyAgent", "capabilities" => ["coding", "testing"] } } }) See the documentation in `docs/` for detailed implementation guides. """ alias AgentCoordinator.MCPServer @doc """ Get the version of Agent Coordinator. ## Examples iex> AgentCoordinator.version() "0.1.0" """ def version do Application.spec(:agent_coordinator, :vsn) |> to_string() end @doc """ Get the current status of the Agent Coordinator system. Returns information about active agents, tasks, and external MCP servers. ## Examples iex> AgentCoordinator.status() %{ agents: 2, active_tasks: 1, external_servers: 3, uptime: 12345 } """ def status do with {:ok, board} <- get_task_board(), {:ok, server_status} <- get_server_status() do %{ agents: length(board[:agents] || []), active_tasks: count_active_tasks(board), external_servers: count_active_servers(server_status), uptime: get_uptime() } else _ -> %{status: :error, message: "Unable to retrieve system status"} end end @doc """ Get the current task board showing all agents and their status. Returns information about all registered agents, their current tasks, and overall system status. ## Examples iex> {:ok, board} = AgentCoordinator.get_task_board() iex> is_map(board) true """ def get_task_board do request = %{ "method" => "tools/call", "params" => %{"name" => "get_task_board", "arguments" => %{}}, "jsonrpc" => "2.0", "id" => System.unique_integer() } case MCPServer.handle_mcp_request(request) do %{"result" => %{"content" => [%{"text" => text}]}} -> {:ok, Jason.decode!(text)} %{"error" => error} -> {:error, error} _ -> {:error, "Unexpected response format"} end end @doc """ Register a new agent with the coordination system. ## Parameters - `name` - Agent name (string) - `capabilities` - List of capabilities (["coding", "testing", ...]) - `opts` - Optional parameters (codebase_id, workspace_path, etc.) ## Examples iex> {:ok, result} = AgentCoordinator.register_agent("TestAgent", ["coding"]) iex> is_map(result) true """ def register_agent(name, capabilities, opts \\ []) do args = %{ "name" => name, "capabilities" => capabilities } |> add_optional_arg("codebase_id", opts[:codebase_id]) |> add_optional_arg("workspace_path", opts[:workspace_path]) |> add_optional_arg("cross_codebase_capable", opts[:cross_codebase_capable]) request = %{ "method" => "tools/call", "params" => %{"name" => "register_agent", "arguments" => args}, "jsonrpc" => "2.0", "id" => System.unique_integer() } case MCPServer.handle_mcp_request(request) do %{"result" => %{"content" => [%{"text" => text}]}} -> {:ok, Jason.decode!(text)} %{"error" => error} -> {:error, error} _ -> {:error, "Unexpected response format"} end end @doc """ Create a new task in the coordination system. ## Parameters - `title` - Task title (string) - `description` - Task description (string) - `opts` - Optional parameters (priority, codebase_id, file_paths, etc.) ## Examples iex> {:ok, result} = AgentCoordinator.create_task("Test Task", "Test description") iex> is_map(result) true """ def create_task(title, description, opts \\ []) do args = %{ "title" => title, "description" => description } |> add_optional_arg("priority", opts[:priority]) |> add_optional_arg("codebase_id", opts[:codebase_id]) |> add_optional_arg("file_paths", opts[:file_paths]) |> add_optional_arg("required_capabilities", opts[:required_capabilities]) request = %{ "method" => "tools/call", "params" => %{"name" => "create_task", "arguments" => args}, "jsonrpc" => "2.0", "id" => System.unique_integer() } case MCPServer.handle_mcp_request(request) do %{"result" => %{"content" => [%{"text" => text}]}} -> {:ok, Jason.decode!(text)} %{"error" => error} -> {:error, error} _ -> {:error, "Unexpected response format"} end end # Private helpers defp add_optional_arg(args, _key, nil), do: args defp add_optional_arg(args, key, value), do: Map.put(args, key, value) defp count_active_tasks(%{agents: agents}) do Enum.count(agents, fn agent -> Map.get(agent, "current_task") != nil end) end defp count_active_tasks(_), do: 0 defp count_active_servers(server_status) when is_map(server_status) do Map.get(server_status, :active_servers, 0) end defp count_active_servers(_), do: 0 defp get_server_status do # This would call UnifiedMCPServer to get external server status # For now, return a placeholder {:ok, %{active_servers: 3}} end defp get_uptime do # Get system uptime in seconds {uptime_ms, _} = :erlang.statistics(:wall_clock) div(uptime_ms, 1000) end end