Consolidate MCP server: remove voice bridge, add schedule/terminal/worktree tools

Merge agent-management and agent MCP into a unified server with shared
utilities. Remove the voice-mcp-bridge in favor of direct MCP tool
registration. Add schedule, terminal, and worktree management tools to
the MCP server for CLI parity. Include e2e parity tests.
This commit is contained in:
Mohamed Boudra
2026-04-11 12:46:42 +07:00
parent 4de2766114
commit cff41d78ab
28 changed files with 2647 additions and 777 deletions
@@ -76,6 +76,7 @@ export type AgentManagerOptions = {
idFactory?: () => string;
registry?: AgentStorage;
onAgentAttention?: AgentAttentionCallback;
mcpBaseUrl?: string;
logger: Logger;
};
@@ -331,6 +332,7 @@ export class AgentManager {
private readonly registry?: AgentStorage;
private readonly previousStatuses = new Map<string, AgentLifecycleStatus>();
private readonly backgroundTasks = new Set<Promise<void>>();
private mcpBaseUrl: string | null;
private onAgentAttention?: AgentAttentionCallback;
private logger: Logger;
@@ -345,6 +347,7 @@ export class AgentManager {
this.idFactory = options?.idFactory ?? (() => randomUUID());
this.registry = options?.registry;
this.onAgentAttention = options?.onAgentAttention;
this.mcpBaseUrl = options?.mcpBaseUrl ?? null;
this.logger = options.logger.child({ module: "agent", component: "agent-manager" });
if (options?.clients) {
for (const [provider, client] of Object.entries(options.clients)) {
@@ -363,6 +366,10 @@ export class AgentManager {
this.onAgentAttention = callback;
}
setMcpBaseUrl(url: string | null): void {
this.mcpBaseUrl = url;
}
public getMetricsSnapshot(): AgentMetricsSnapshot {
const byLifecycle: Record<string, number> = {};
let withActiveForegroundTurn = 0;
@@ -731,9 +738,21 @@ export class AgentManager {
agentId?: string,
options?: { labels?: Record<string, string> },
): Promise<ManagedAgent> {
// Generate agent ID early so we can use it in MCP config
const resolvedAgentId = validateAgentId(agentId ?? this.idFactory(), "createAgent");
const normalizedConfig = await this.normalizeConfig(config);
const injectedConfig =
this.mcpBaseUrl == null
? config
: {
...config,
mcpServers: {
paseo: {
type: "http" as const,
url: `${this.mcpBaseUrl}?callerAgentId=${resolvedAgentId}`,
},
...(config.mcpServers ?? {}),
},
};
const normalizedConfig = await this.normalizeConfig(injectedConfig);
const launchContext = this.buildLaunchContext(resolvedAgentId);
const client = this.requireClient(normalizedConfig.provider);
const available = await client.isAvailable();