cd839c7f0c
Implement Model Context Protocol (MCP) support so Flynn can spawn MCP server processes, discover their tools, and make them available to the agent alongside builtin tools. - McpClient: wraps @modelcontextprotocol/sdk with StdioClientTransport for process lifecycle, tool discovery (listTools), and invocation (callTool) - McpManager: lifecycle management for multiple MCP servers with startAll/stopAll/restart, tool bridging into ToolRegistry - Bridge: converts MCP tools to Flynn Tool interface with mcp:<server>:<tool> namespacing to avoid collisions with builtin tools - Config: add env and cwd fields to mcp server schema - ToolRegistry: add unregister() method for MCP server cleanup - Daemon: wire McpManager into startup and shutdown lifecycle - Tests: 28 new tests (bridge, manager, registry unregister)
59 lines
1.2 KiB
TypeScript
59 lines
1.2 KiB
TypeScript
import type { Tool, ToolInputSchema } from './types.js';
|
|
|
|
export interface AnthropicToolDef {
|
|
name: string;
|
|
description: string;
|
|
input_schema: ToolInputSchema;
|
|
}
|
|
|
|
export interface OpenAIToolDef {
|
|
type: 'function';
|
|
function: {
|
|
name: string;
|
|
description: string;
|
|
parameters: ToolInputSchema;
|
|
};
|
|
}
|
|
|
|
export class ToolRegistry {
|
|
private tools: Map<string, Tool> = new Map();
|
|
|
|
register(tool: Tool): void {
|
|
if (this.tools.has(tool.name)) {
|
|
throw new Error(`Tool '${tool.name}' is already registered`);
|
|
}
|
|
this.tools.set(tool.name, tool);
|
|
}
|
|
|
|
unregister(name: string): boolean {
|
|
return this.tools.delete(name);
|
|
}
|
|
|
|
get(name: string): Tool | undefined {
|
|
return this.tools.get(name);
|
|
}
|
|
|
|
list(): Tool[] {
|
|
return Array.from(this.tools.values());
|
|
}
|
|
|
|
toAnthropicFormat(): AnthropicToolDef[] {
|
|
return this.list().map(t => ({
|
|
name: t.name,
|
|
description: t.description,
|
|
input_schema: t.inputSchema,
|
|
}));
|
|
}
|
|
|
|
toOpenAIFormat(): OpenAIToolDef[] {
|
|
return this.list().map(t => ({
|
|
type: 'function' as const,
|
|
function: {
|
|
name: t.name,
|
|
description: t.description,
|
|
parameters: t.inputSchema,
|
|
},
|
|
}));
|
|
}
|
|
}
|