@bluehawks/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/.eslintrc.json +36 -0
  2. package/.prettierrc +8 -0
  3. package/README.md +288 -0
  4. package/dist/cli/app.d.ts +12 -0
  5. package/dist/cli/app.d.ts.map +1 -0
  6. package/dist/cli/app.js +201 -0
  7. package/dist/cli/app.js.map +1 -0
  8. package/dist/cli/commands/index.d.ts +56 -0
  9. package/dist/cli/commands/index.d.ts.map +1 -0
  10. package/dist/cli/commands/index.js +201 -0
  11. package/dist/cli/commands/index.js.map +1 -0
  12. package/dist/config/constants.d.ts +32 -0
  13. package/dist/config/constants.d.ts.map +1 -0
  14. package/dist/config/constants.js +39 -0
  15. package/dist/config/constants.js.map +1 -0
  16. package/dist/config/index.d.ts +4 -0
  17. package/dist/config/index.d.ts.map +1 -0
  18. package/dist/config/index.js +4 -0
  19. package/dist/config/index.js.map +1 -0
  20. package/dist/config/schema.d.ts +56 -0
  21. package/dist/config/schema.d.ts.map +1 -0
  22. package/dist/config/schema.js +28 -0
  23. package/dist/config/schema.js.map +1 -0
  24. package/dist/config/settings.d.ts +20 -0
  25. package/dist/config/settings.d.ts.map +1 -0
  26. package/dist/config/settings.js +102 -0
  27. package/dist/config/settings.js.map +1 -0
  28. package/dist/core/agents/agent.d.ts +33 -0
  29. package/dist/core/agents/agent.d.ts.map +1 -0
  30. package/dist/core/agents/agent.js +156 -0
  31. package/dist/core/agents/agent.js.map +1 -0
  32. package/dist/core/agents/index.d.ts +3 -0
  33. package/dist/core/agents/index.d.ts.map +1 -0
  34. package/dist/core/agents/index.js +3 -0
  35. package/dist/core/agents/index.js.map +1 -0
  36. package/dist/core/agents/orchestrator.d.ts +56 -0
  37. package/dist/core/agents/orchestrator.d.ts.map +1 -0
  38. package/dist/core/agents/orchestrator.js +151 -0
  39. package/dist/core/agents/orchestrator.js.map +1 -0
  40. package/dist/core/api/client.d.ts +46 -0
  41. package/dist/core/api/client.d.ts.map +1 -0
  42. package/dist/core/api/client.js +223 -0
  43. package/dist/core/api/client.js.map +1 -0
  44. package/dist/core/api/index.d.ts +3 -0
  45. package/dist/core/api/index.d.ts.map +1 -0
  46. package/dist/core/api/index.js +3 -0
  47. package/dist/core/api/index.js.map +1 -0
  48. package/dist/core/api/types.d.ts +126 -0
  49. package/dist/core/api/types.d.ts.map +1 -0
  50. package/dist/core/api/types.js +16 -0
  51. package/dist/core/api/types.js.map +1 -0
  52. package/dist/core/hooks/index.d.ts +3 -0
  53. package/dist/core/hooks/index.d.ts.map +1 -0
  54. package/dist/core/hooks/index.js +3 -0
  55. package/dist/core/hooks/index.js.map +1 -0
  56. package/dist/core/hooks/manager.d.ts +43 -0
  57. package/dist/core/hooks/manager.d.ts.map +1 -0
  58. package/dist/core/hooks/manager.js +178 -0
  59. package/dist/core/hooks/manager.js.map +1 -0
  60. package/dist/core/hooks/types.d.ts +68 -0
  61. package/dist/core/hooks/types.d.ts.map +1 -0
  62. package/dist/core/hooks/types.js +6 -0
  63. package/dist/core/hooks/types.js.map +1 -0
  64. package/dist/core/mcp/client.d.ts +48 -0
  65. package/dist/core/mcp/client.d.ts.map +1 -0
  66. package/dist/core/mcp/client.js +139 -0
  67. package/dist/core/mcp/client.js.map +1 -0
  68. package/dist/core/mcp/index.d.ts +3 -0
  69. package/dist/core/mcp/index.d.ts.map +1 -0
  70. package/dist/core/mcp/index.js +3 -0
  71. package/dist/core/mcp/index.js.map +1 -0
  72. package/dist/core/mcp/manager.d.ts +46 -0
  73. package/dist/core/mcp/manager.d.ts.map +1 -0
  74. package/dist/core/mcp/manager.js +133 -0
  75. package/dist/core/mcp/manager.js.map +1 -0
  76. package/dist/core/plugins/index.d.ts +3 -0
  77. package/dist/core/plugins/index.d.ts.map +1 -0
  78. package/dist/core/plugins/index.js +3 -0
  79. package/dist/core/plugins/index.js.map +1 -0
  80. package/dist/core/plugins/loader.d.ts +63 -0
  81. package/dist/core/plugins/loader.d.ts.map +1 -0
  82. package/dist/core/plugins/loader.js +258 -0
  83. package/dist/core/plugins/loader.js.map +1 -0
  84. package/dist/core/plugins/types.d.ts +95 -0
  85. package/dist/core/plugins/types.d.ts.map +1 -0
  86. package/dist/core/plugins/types.js +6 -0
  87. package/dist/core/plugins/types.js.map +1 -0
  88. package/dist/core/session/index.d.ts +3 -0
  89. package/dist/core/session/index.d.ts.map +1 -0
  90. package/dist/core/session/index.js +3 -0
  91. package/dist/core/session/index.js.map +1 -0
  92. package/dist/core/session/manager.d.ts +57 -0
  93. package/dist/core/session/manager.d.ts.map +1 -0
  94. package/dist/core/session/manager.js +182 -0
  95. package/dist/core/session/manager.js.map +1 -0
  96. package/dist/core/session/storage.d.ts +42 -0
  97. package/dist/core/session/storage.d.ts.map +1 -0
  98. package/dist/core/session/storage.js +138 -0
  99. package/dist/core/session/storage.js.map +1 -0
  100. package/dist/core/tools/definitions/file.d.ts +6 -0
  101. package/dist/core/tools/definitions/file.d.ts.map +1 -0
  102. package/dist/core/tools/definitions/file.js +276 -0
  103. package/dist/core/tools/definitions/file.js.map +1 -0
  104. package/dist/core/tools/definitions/git.d.ts +6 -0
  105. package/dist/core/tools/definitions/git.d.ts.map +1 -0
  106. package/dist/core/tools/definitions/git.js +294 -0
  107. package/dist/core/tools/definitions/git.js.map +1 -0
  108. package/dist/core/tools/definitions/index.d.ts +11 -0
  109. package/dist/core/tools/definitions/index.d.ts.map +1 -0
  110. package/dist/core/tools/definitions/index.js +22 -0
  111. package/dist/core/tools/definitions/index.js.map +1 -0
  112. package/dist/core/tools/definitions/search.d.ts +6 -0
  113. package/dist/core/tools/definitions/search.d.ts.map +1 -0
  114. package/dist/core/tools/definitions/search.js +223 -0
  115. package/dist/core/tools/definitions/search.js.map +1 -0
  116. package/dist/core/tools/definitions/shell.d.ts +6 -0
  117. package/dist/core/tools/definitions/shell.d.ts.map +1 -0
  118. package/dist/core/tools/definitions/shell.js +190 -0
  119. package/dist/core/tools/definitions/shell.js.map +1 -0
  120. package/dist/core/tools/definitions/web.d.ts +6 -0
  121. package/dist/core/tools/definitions/web.d.ts.map +1 -0
  122. package/dist/core/tools/definitions/web.js +104 -0
  123. package/dist/core/tools/definitions/web.js.map +1 -0
  124. package/dist/core/tools/executor.d.ts +24 -0
  125. package/dist/core/tools/executor.d.ts.map +1 -0
  126. package/dist/core/tools/executor.js +111 -0
  127. package/dist/core/tools/executor.js.map +1 -0
  128. package/dist/core/tools/index.d.ts +4 -0
  129. package/dist/core/tools/index.d.ts.map +1 -0
  130. package/dist/core/tools/index.js +4 -0
  131. package/dist/core/tools/index.js.map +1 -0
  132. package/dist/core/tools/registry.d.ts +23 -0
  133. package/dist/core/tools/registry.d.ts.map +1 -0
  134. package/dist/core/tools/registry.js +28 -0
  135. package/dist/core/tools/registry.js.map +1 -0
  136. package/dist/index.d.ts +7 -0
  137. package/dist/index.d.ts.map +1 -0
  138. package/dist/index.js +352 -0
  139. package/dist/index.js.map +1 -0
  140. package/package.json +62 -0
  141. package/src/cli/app.tsx +319 -0
  142. package/src/cli/commands/index.ts +261 -0
  143. package/src/config/constants.ts +45 -0
  144. package/src/config/index.ts +3 -0
  145. package/src/config/schema.ts +36 -0
  146. package/src/config/settings.ts +121 -0
  147. package/src/core/agents/agent.ts +205 -0
  148. package/src/core/agents/index.ts +2 -0
  149. package/src/core/agents/orchestrator.ts +223 -0
  150. package/src/core/api/client.ts +300 -0
  151. package/src/core/api/index.ts +2 -0
  152. package/src/core/api/types.ts +149 -0
  153. package/src/core/hooks/index.ts +2 -0
  154. package/src/core/hooks/manager.ts +212 -0
  155. package/src/core/hooks/types.ts +116 -0
  156. package/src/core/mcp/client.ts +198 -0
  157. package/src/core/mcp/index.ts +2 -0
  158. package/src/core/mcp/manager.ts +153 -0
  159. package/src/core/plugins/index.ts +2 -0
  160. package/src/core/plugins/loader.ts +312 -0
  161. package/src/core/plugins/types.ts +111 -0
  162. package/src/core/session/index.ts +2 -0
  163. package/src/core/session/manager.ts +246 -0
  164. package/src/core/session/storage.ts +184 -0
  165. package/src/core/tools/definitions/file.ts +312 -0
  166. package/src/core/tools/definitions/git.ts +326 -0
  167. package/src/core/tools/definitions/index.ts +24 -0
  168. package/src/core/tools/definitions/search.ts +266 -0
  169. package/src/core/tools/definitions/shell.ts +228 -0
  170. package/src/core/tools/definitions/web.ts +113 -0
  171. package/src/core/tools/executor.ts +145 -0
  172. package/src/core/tools/index.ts +3 -0
  173. package/src/core/tools/registry.ts +44 -0
  174. package/src/index.ts +407 -0
  175. package/tsconfig.json +40 -0
  176. package/vitest.config.ts +13 -0
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Bluehawks CLI - Hooks Types
3
+ * Type definitions for the hooks system
4
+ */
5
+
6
+ export type HookEvent =
7
+ | 'SessionStart'
8
+ | 'UserPromptSubmit'
9
+ | 'PreToolUse'
10
+ | 'PostToolUse'
11
+ | 'PostToolUseFailure'
12
+ | 'Stop'
13
+ | 'SessionEnd';
14
+
15
+ export interface HookContext {
16
+ sessionId: string;
17
+ projectPath: string;
18
+ model: string;
19
+ timestamp: string;
20
+ }
21
+
22
+ export interface SessionStartInput extends HookContext {
23
+ cwd: string;
24
+ }
25
+
26
+ export interface UserPromptSubmitInput extends HookContext {
27
+ prompt: string;
28
+ }
29
+
30
+ export interface PreToolUseInput extends HookContext {
31
+ toolName: string;
32
+ toolInput: Record<string, unknown>;
33
+ }
34
+
35
+ export interface PostToolUseInput extends HookContext {
36
+ toolName: string;
37
+ toolInput: Record<string, unknown>;
38
+ toolOutput: string;
39
+ duration: number;
40
+ }
41
+
42
+ export interface PostToolUseFailureInput extends HookContext {
43
+ toolName: string;
44
+ toolInput: Record<string, unknown>;
45
+ error: string;
46
+ }
47
+
48
+ export interface StopInput extends HookContext {
49
+ reason: 'completed' | 'cancelled' | 'error';
50
+ messageCount: number;
51
+ }
52
+
53
+ export interface SessionEndInput extends HookContext {
54
+ duration: number;
55
+ tokensUsed: number;
56
+ }
57
+
58
+ export type HookInput =
59
+ | SessionStartInput
60
+ | UserPromptSubmitInput
61
+ | PreToolUseInput
62
+ | PostToolUseInput
63
+ | PostToolUseFailureInput
64
+ | StopInput
65
+ | SessionEndInput;
66
+
67
+ export interface HookOutput {
68
+ // Block the action (for Pre* hooks)
69
+ block?: boolean;
70
+ blockReason?: string;
71
+
72
+ // Modify the input (for Pre* hooks)
73
+ modifiedInput?: Record<string, unknown>;
74
+
75
+ // Add content to the conversation
76
+ addContent?: string;
77
+
78
+ // Custom data to pass to the next hook
79
+ data?: Record<string, unknown>;
80
+ }
81
+
82
+ export interface HookHandler {
83
+ // Unique identifier for this handler
84
+ id: string;
85
+
86
+ // Human-readable name
87
+ name: string;
88
+
89
+ // Which event this hook handles
90
+ event: HookEvent;
91
+
92
+ // Command to execute (shell command)
93
+ command?: string;
94
+
95
+ // Inline handler function
96
+ handler?: (input: HookInput) => Promise<HookOutput | void>;
97
+
98
+ // Whether to run asynchronously (don't block)
99
+ async?: boolean;
100
+
101
+ // Timeout in milliseconds
102
+ timeout?: number;
103
+
104
+ // Matcher pattern (for tool-specific hooks)
105
+ matcher?: string | RegExp;
106
+ }
107
+
108
+ export interface HooksConfig {
109
+ SessionStart?: HookHandler[];
110
+ UserPromptSubmit?: HookHandler[];
111
+ PreToolUse?: HookHandler[];
112
+ PostToolUse?: HookHandler[];
113
+ PostToolUseFailure?: HookHandler[];
114
+ Stop?: HookHandler[];
115
+ SessionEnd?: HookHandler[];
116
+ }
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Bluehawks CLI - MCP Client
3
+ * Model Context Protocol client for connecting to external data sources
4
+ */
5
+
6
+ import { spawn, type ChildProcess } from 'node:child_process';
7
+ import * as readline from 'node:readline';
8
+
9
+ export interface MCPServerConfig {
10
+ command: string;
11
+ args?: string[];
12
+ env?: Record<string, string>;
13
+ }
14
+
15
+ export interface MCPTool {
16
+ name: string;
17
+ description: string;
18
+ inputSchema: {
19
+ type: string;
20
+ properties?: Record<string, unknown>;
21
+ required?: string[];
22
+ };
23
+ }
24
+
25
+ export interface MCPResource {
26
+ uri: string;
27
+ name: string;
28
+ description?: string;
29
+ mimeType?: string;
30
+ }
31
+
32
+ interface JsonRpcRequest {
33
+ jsonrpc: '2.0';
34
+ id: number;
35
+ method: string;
36
+ params?: Record<string, unknown>;
37
+ }
38
+
39
+ interface JsonRpcResponse {
40
+ jsonrpc: '2.0';
41
+ id: number;
42
+ result?: unknown;
43
+ error?: { code: number; message: string };
44
+ }
45
+
46
+ export class MCPClient {
47
+ private serverName: string;
48
+ private process: ChildProcess | null = null;
49
+ private requestId = 0;
50
+ private pendingRequests = new Map<number, {
51
+ resolve: (value: unknown) => void;
52
+ reject: (error: Error) => void;
53
+ }>();
54
+ private tools: MCPTool[] = [];
55
+ private resources: MCPResource[] = [];
56
+ private reader: readline.Interface | null = null;
57
+
58
+ constructor(serverName: string) {
59
+ this.serverName = serverName;
60
+ }
61
+
62
+ async connect(config: MCPServerConfig): Promise<void> {
63
+ return new Promise((resolve, reject) => {
64
+ this.process = spawn(config.command, config.args || [], {
65
+ stdio: ['pipe', 'pipe', 'pipe'],
66
+ env: { ...process.env, ...config.env },
67
+ });
68
+
69
+ if (!this.process.stdout || !this.process.stdin) {
70
+ reject(new Error('Failed to create MCP process'));
71
+ return;
72
+ }
73
+
74
+ this.reader = readline.createInterface({
75
+ input: this.process.stdout,
76
+ });
77
+
78
+ this.reader.on('line', (line) => {
79
+ try {
80
+ const response = JSON.parse(line) as JsonRpcResponse;
81
+ const pending = this.pendingRequests.get(response.id);
82
+ if (pending) {
83
+ this.pendingRequests.delete(response.id);
84
+ if (response.error) {
85
+ pending.reject(new Error(response.error.message));
86
+ } else {
87
+ pending.resolve(response.result);
88
+ }
89
+ }
90
+ } catch {
91
+ // Ignore non-JSON output
92
+ }
93
+ });
94
+
95
+ this.process.on('error', (err) => {
96
+ reject(err);
97
+ });
98
+
99
+ // Initialize the MCP connection
100
+ this.sendRequest('initialize', {
101
+ protocolVersion: '2024-11-05',
102
+ capabilities: {},
103
+ clientInfo: { name: 'bluehawks-cli', version: '1.0.0' },
104
+ }).then(() => {
105
+ // Send initialized notification
106
+ this.sendNotification('notifications/initialized');
107
+ resolve();
108
+ }).catch(reject);
109
+ });
110
+ }
111
+
112
+ private sendRequest(method: string, params?: Record<string, unknown>): Promise<unknown> {
113
+ return new Promise((resolve, reject) => {
114
+ if (!this.process?.stdin) {
115
+ reject(new Error('MCP process not connected'));
116
+ return;
117
+ }
118
+
119
+ const id = ++this.requestId;
120
+ const request: JsonRpcRequest = {
121
+ jsonrpc: '2.0',
122
+ id,
123
+ method,
124
+ params,
125
+ };
126
+
127
+ this.pendingRequests.set(id, { resolve, reject });
128
+ this.process.stdin.write(JSON.stringify(request) + '\n');
129
+
130
+ // Timeout after 30 seconds
131
+ setTimeout(() => {
132
+ if (this.pendingRequests.has(id)) {
133
+ this.pendingRequests.delete(id);
134
+ reject(new Error(`Request ${method} timed out`));
135
+ }
136
+ }, 30000);
137
+ });
138
+ }
139
+
140
+ private sendNotification(method: string, params?: Record<string, unknown>): void {
141
+ if (!this.process?.stdin) return;
142
+
143
+ const notification = {
144
+ jsonrpc: '2.0',
145
+ method,
146
+ params,
147
+ };
148
+ this.process.stdin.write(JSON.stringify(notification) + '\n');
149
+ }
150
+
151
+ async listTools(): Promise<MCPTool[]> {
152
+ const result = await this.sendRequest('tools/list') as { tools: MCPTool[] };
153
+ this.tools = result.tools || [];
154
+ return this.tools;
155
+ }
156
+
157
+ async listResources(): Promise<MCPResource[]> {
158
+ const result = await this.sendRequest('resources/list') as { resources: MCPResource[] };
159
+ this.resources = result.resources || [];
160
+ return this.resources;
161
+ }
162
+
163
+ async callTool(name: string, args: Record<string, unknown>): Promise<unknown> {
164
+ const result = await this.sendRequest('tools/call', {
165
+ name,
166
+ arguments: args,
167
+ });
168
+ return result;
169
+ }
170
+
171
+ async readResource(uri: string): Promise<{ contents: unknown[] }> {
172
+ const result = await this.sendRequest('resources/read', { uri });
173
+ return result as { contents: unknown[] };
174
+ }
175
+
176
+ getTools(): MCPTool[] {
177
+ return this.tools;
178
+ }
179
+
180
+ getResources(): MCPResource[] {
181
+ return this.resources;
182
+ }
183
+
184
+ getServerName(): string {
185
+ return this.serverName;
186
+ }
187
+
188
+ async disconnect(): Promise<void> {
189
+ if (this.reader) {
190
+ this.reader.close();
191
+ }
192
+ if (this.process) {
193
+ this.process.kill();
194
+ this.process = null;
195
+ }
196
+ this.pendingRequests.clear();
197
+ }
198
+ }
@@ -0,0 +1,2 @@
1
+ export * from './client.js';
2
+ export * from './manager.js';
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Bluehawks CLI - MCP Manager
3
+ * Manages MCP server connections and integrates tools
4
+ */
5
+
6
+ import * as fs from 'node:fs/promises';
7
+ import * as path from 'node:path';
8
+ import * as os from 'node:os';
9
+ import { MCPClient, type MCPServerConfig, type MCPTool } from './client.js';
10
+ import { toolRegistry } from '../tools/index.js';
11
+ import type { ToolDefinition } from '../api/types.js';
12
+
13
+ export interface MCPConfig {
14
+ mcpServers?: Record<string, MCPServerConfig>;
15
+ }
16
+
17
+ export class MCPManager {
18
+ private clients: Map<string, MCPClient> = new Map();
19
+
20
+ constructor() {
21
+ // Manager initialized - config will be loaded on connectAll
22
+ }
23
+
24
+ /**
25
+ * Load MCP configuration from file
26
+ */
27
+ async loadConfig(): Promise<MCPConfig | null> {
28
+ const paths = [
29
+ path.join(process.cwd(), '.mcp.json'),
30
+ path.join(os.homedir(), '.bluehawks', '.mcp.json'),
31
+ ];
32
+
33
+ for (const configPath of paths) {
34
+ try {
35
+ const content = await fs.readFile(configPath, 'utf-8');
36
+ return JSON.parse(content) as MCPConfig;
37
+ } catch {
38
+ continue;
39
+ }
40
+ }
41
+ return null;
42
+ }
43
+
44
+ /**
45
+ * Connect to all configured MCP servers
46
+ */
47
+ async connectAll(): Promise<void> {
48
+ const config = await this.loadConfig();
49
+ if (!config?.mcpServers) {
50
+ return;
51
+ }
52
+
53
+ for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
54
+ try {
55
+ await this.connect(name, serverConfig);
56
+ } catch (error) {
57
+ console.error(`Failed to connect to MCP server ${name}:`, error);
58
+ }
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Connect to a specific MCP server
64
+ */
65
+ async connect(name: string, config: MCPServerConfig): Promise<MCPClient> {
66
+ const client = new MCPClient(name);
67
+ await client.connect(config);
68
+
69
+ // List and register tools
70
+ const tools = await client.listTools();
71
+ for (const tool of tools) {
72
+ this.registerMCPTool(name, tool);
73
+ }
74
+
75
+ this.clients.set(name, client);
76
+ return client;
77
+ }
78
+
79
+ /**
80
+ * Register an MCP tool as a Bluehawks tool
81
+ */
82
+ private registerMCPTool(serverName: string, mcpTool: MCPTool): void {
83
+ const toolName = `mcp_${serverName}_${mcpTool.name}`;
84
+
85
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
+ const definition: ToolDefinition = {
87
+ type: 'function',
88
+ function: {
89
+ name: toolName,
90
+ description: `[MCP:${serverName}] ${mcpTool.description}`,
91
+ parameters: mcpTool.inputSchema as ToolDefinition['function']['parameters'],
92
+ },
93
+ };
94
+
95
+
96
+ const clients = this.clients;
97
+ toolRegistry.register({
98
+ name: toolName,
99
+ definition,
100
+ execute: async (args: Record<string, unknown>) => {
101
+ const client = clients.get(serverName);
102
+ if (!client) {
103
+ return `MCP server ${serverName} not connected`;
104
+ }
105
+ try {
106
+ const result = await client.callTool(mcpTool.name, args);
107
+ return typeof result === 'string' ? result : JSON.stringify(result, null, 2);
108
+ } catch (error) {
109
+ return `MCP tool error: ${error instanceof Error ? error.message : String(error)}`;
110
+ }
111
+ },
112
+ safeToAutoRun: false, // MCP tools require approval by default
113
+ });
114
+ }
115
+
116
+ /**
117
+ * Get all connected clients
118
+ */
119
+ getClients(): Map<string, MCPClient> {
120
+ return this.clients;
121
+ }
122
+
123
+ /**
124
+ * Get a specific client
125
+ */
126
+ getClient(name: string): MCPClient | undefined {
127
+ return this.clients.get(name);
128
+ }
129
+
130
+ /**
131
+ * Disconnect all MCP servers
132
+ */
133
+ async disconnectAll(): Promise<void> {
134
+ for (const client of this.clients.values()) {
135
+ await client.disconnect();
136
+ }
137
+ this.clients.clear();
138
+ }
139
+
140
+ /**
141
+ * Disconnect a specific server
142
+ */
143
+ async disconnect(name: string): Promise<void> {
144
+ const client = this.clients.get(name);
145
+ if (client) {
146
+ await client.disconnect();
147
+ this.clients.delete(name);
148
+ }
149
+ }
150
+ }
151
+
152
+ // Singleton instance
153
+ export const mcpManager = new MCPManager();
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ export * from './loader.js';