@animalabs/agent-framework 0.1.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.
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/dist/src/agent.d.ts +130 -0
- package/dist/src/agent.d.ts.map +1 -0
- package/dist/src/agent.js +406 -0
- package/dist/src/agent.js.map +1 -0
- package/dist/src/api/mcp-server.d.ts +37 -0
- package/dist/src/api/mcp-server.d.ts.map +1 -0
- package/dist/src/api/mcp-server.js +598 -0
- package/dist/src/api/mcp-server.js.map +1 -0
- package/dist/src/api/server.d.ts +83 -0
- package/dist/src/api/server.d.ts.map +1 -0
- package/dist/src/api/server.js +785 -0
- package/dist/src/api/server.js.map +1 -0
- package/dist/src/api/types.d.ts +395 -0
- package/dist/src/api/types.d.ts.map +1 -0
- package/dist/src/api/types.js +5 -0
- package/dist/src/api/types.js.map +1 -0
- package/dist/src/framework.d.ts +309 -0
- package/dist/src/framework.d.ts.map +1 -0
- package/dist/src/framework.js +2309 -0
- package/dist/src/framework.js.map +1 -0
- package/dist/src/gate/event-gate.d.ts +75 -0
- package/dist/src/gate/event-gate.d.ts.map +1 -0
- package/dist/src/gate/event-gate.js +503 -0
- package/dist/src/gate/event-gate.js.map +1 -0
- package/dist/src/gate/index.d.ts +3 -0
- package/dist/src/gate/index.d.ts.map +1 -0
- package/dist/src/gate/index.js +2 -0
- package/dist/src/gate/index.js.map +1 -0
- package/dist/src/gate/types.d.ts +82 -0
- package/dist/src/gate/types.d.ts.map +1 -0
- package/dist/src/gate/types.js +9 -0
- package/dist/src/gate/types.js.map +1 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcpl/channel-registry.d.ts +141 -0
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -0
- package/dist/src/mcpl/channel-registry.js +647 -0
- package/dist/src/mcpl/channel-registry.js.map +1 -0
- package/dist/src/mcpl/checkpoint-manager.d.ts +79 -0
- package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -0
- package/dist/src/mcpl/checkpoint-manager.js +430 -0
- package/dist/src/mcpl/checkpoint-manager.js.map +1 -0
- package/dist/src/mcpl/errors.d.ts +52 -0
- package/dist/src/mcpl/errors.d.ts.map +1 -0
- package/dist/src/mcpl/errors.js +93 -0
- package/dist/src/mcpl/errors.js.map +1 -0
- package/dist/src/mcpl/feature-set-manager.d.ts +91 -0
- package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -0
- package/dist/src/mcpl/feature-set-manager.js +250 -0
- package/dist/src/mcpl/feature-set-manager.js.map +1 -0
- package/dist/src/mcpl/hook-orchestrator.d.ts +51 -0
- package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -0
- package/dist/src/mcpl/hook-orchestrator.js +217 -0
- package/dist/src/mcpl/hook-orchestrator.js.map +1 -0
- package/dist/src/mcpl/index.d.ts +14 -0
- package/dist/src/mcpl/index.d.ts.map +1 -0
- package/dist/src/mcpl/index.js +21 -0
- package/dist/src/mcpl/index.js.map +1 -0
- package/dist/src/mcpl/inference-router.d.ts +67 -0
- package/dist/src/mcpl/inference-router.d.ts.map +1 -0
- package/dist/src/mcpl/inference-router.js +249 -0
- package/dist/src/mcpl/inference-router.js.map +1 -0
- package/dist/src/mcpl/push-handler.d.ts +60 -0
- package/dist/src/mcpl/push-handler.d.ts.map +1 -0
- package/dist/src/mcpl/push-handler.js +162 -0
- package/dist/src/mcpl/push-handler.js.map +1 -0
- package/dist/src/mcpl/scope-manager.d.ts +76 -0
- package/dist/src/mcpl/scope-manager.d.ts.map +1 -0
- package/dist/src/mcpl/scope-manager.js +213 -0
- package/dist/src/mcpl/scope-manager.js.map +1 -0
- package/dist/src/mcpl/server-connection.d.ts +174 -0
- package/dist/src/mcpl/server-connection.d.ts.map +1 -0
- package/dist/src/mcpl/server-connection.js +559 -0
- package/dist/src/mcpl/server-connection.js.map +1 -0
- package/dist/src/mcpl/server-registry.d.ts +63 -0
- package/dist/src/mcpl/server-registry.d.ts.map +1 -0
- package/dist/src/mcpl/server-registry.js +119 -0
- package/dist/src/mcpl/server-registry.js.map +1 -0
- package/dist/src/mcpl/types.d.ts +755 -0
- package/dist/src/mcpl/types.d.ts.map +1 -0
- package/dist/src/mcpl/types.js +48 -0
- package/dist/src/mcpl/types.js.map +1 -0
- package/dist/src/module-registry.d.ts +93 -0
- package/dist/src/module-registry.d.ts.map +1 -0
- package/dist/src/module-registry.js +386 -0
- package/dist/src/module-registry.js.map +1 -0
- package/dist/src/modules/api/index.d.ts +22 -0
- package/dist/src/modules/api/index.d.ts.map +1 -0
- package/dist/src/modules/api/index.js +63 -0
- package/dist/src/modules/api/index.js.map +1 -0
- package/dist/src/modules/discord/discord-js-client.d.ts +58 -0
- package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -0
- package/dist/src/modules/discord/discord-js-client.js +273 -0
- package/dist/src/modules/discord/discord-js-client.js.map +1 -0
- package/dist/src/modules/discord/index.d.ts +82 -0
- package/dist/src/modules/discord/index.d.ts.map +1 -0
- package/dist/src/modules/discord/index.js +959 -0
- package/dist/src/modules/discord/index.js.map +1 -0
- package/dist/src/modules/discord/types.d.ts +327 -0
- package/dist/src/modules/discord/types.d.ts.map +1 -0
- package/dist/src/modules/discord/types.js +5 -0
- package/dist/src/modules/discord/types.js.map +1 -0
- package/dist/src/modules/index.d.ts +11 -0
- package/dist/src/modules/index.d.ts.map +1 -0
- package/dist/src/modules/index.js +7 -0
- package/dist/src/modules/index.js.map +1 -0
- package/dist/src/modules/workspace/index.d.ts +59 -0
- package/dist/src/modules/workspace/index.d.ts.map +1 -0
- package/dist/src/modules/workspace/index.js +831 -0
- package/dist/src/modules/workspace/index.js.map +1 -0
- package/dist/src/modules/workspace/sync.d.ts +48 -0
- package/dist/src/modules/workspace/sync.d.ts.map +1 -0
- package/dist/src/modules/workspace/sync.js +253 -0
- package/dist/src/modules/workspace/sync.js.map +1 -0
- package/dist/src/modules/workspace/types.d.ts +166 -0
- package/dist/src/modules/workspace/types.d.ts.map +1 -0
- package/dist/src/modules/workspace/types.js +5 -0
- package/dist/src/modules/workspace/types.js.map +1 -0
- package/dist/src/modules/workspace/watcher.d.ts +43 -0
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -0
- package/dist/src/modules/workspace/watcher.js +120 -0
- package/dist/src/modules/workspace/watcher.js.map +1 -0
- package/dist/src/queue.d.ts +50 -0
- package/dist/src/queue.d.ts.map +1 -0
- package/dist/src/queue.js +95 -0
- package/dist/src/queue.js.map +1 -0
- package/dist/src/safe-slice.d.ts +8 -0
- package/dist/src/safe-slice.d.ts.map +1 -0
- package/dist/src/safe-slice.js +18 -0
- package/dist/src/safe-slice.js.map +1 -0
- package/dist/src/types/agent.d.ts +118 -0
- package/dist/src/types/agent.d.ts.map +1 -0
- package/dist/src/types/agent.js +2 -0
- package/dist/src/types/agent.js.map +1 -0
- package/dist/src/types/events.d.ts +220 -0
- package/dist/src/types/events.d.ts.map +1 -0
- package/dist/src/types/events.js +2 -0
- package/dist/src/types/events.js.map +1 -0
- package/dist/src/types/framework.d.ts +184 -0
- package/dist/src/types/framework.d.ts.map +1 -0
- package/dist/src/types/framework.js +2 -0
- package/dist/src/types/framework.js.map +1 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +7 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/inference-log.d.ts +64 -0
- package/dist/src/types/inference-log.d.ts.map +1 -0
- package/dist/src/types/inference-log.js +5 -0
- package/dist/src/types/inference-log.js.map +1 -0
- package/dist/src/types/module.d.ts +302 -0
- package/dist/src/types/module.d.ts.map +1 -0
- package/dist/src/types/module.js +2 -0
- package/dist/src/types/module.js.map +1 -0
- package/dist/src/types/trace.d.ts +173 -0
- package/dist/src/types/trace.d.ts.map +1 -0
- package/dist/src/types/trace.js +2 -0
- package/dist/src/types/trace.js.map +1 -0
- package/dist/test/event-gate.test.d.ts +2 -0
- package/dist/test/event-gate.test.d.ts.map +1 -0
- package/dist/test/event-gate.test.js +535 -0
- package/dist/test/event-gate.test.js.map +1 -0
- package/dist/test/framework.test.d.ts +5 -0
- package/dist/test/framework.test.d.ts.map +1 -0
- package/dist/test/framework.test.js +738 -0
- package/dist/test/framework.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +58 -0
- package/src/agent.ts +512 -0
- package/src/api/mcp-server.ts +687 -0
- package/src/api/server.ts +1023 -0
- package/src/api/types.ts +542 -0
- package/src/framework.ts +2784 -0
- package/src/gate/event-gate.ts +623 -0
- package/src/gate/index.ts +12 -0
- package/src/gate/types.ts +112 -0
- package/src/index.ts +63 -0
- package/src/mcpl/channel-registry.ts +824 -0
- package/src/mcpl/checkpoint-manager.ts +545 -0
- package/src/mcpl/errors.ts +114 -0
- package/src/mcpl/feature-set-manager.ts +333 -0
- package/src/mcpl/hook-orchestrator.ts +281 -0
- package/src/mcpl/index.ts +134 -0
- package/src/mcpl/inference-router.ts +335 -0
- package/src/mcpl/push-handler.ts +232 -0
- package/src/mcpl/scope-manager.ts +262 -0
- package/src/mcpl/server-connection.ts +694 -0
- package/src/mcpl/server-registry.ts +144 -0
- package/src/mcpl/types.ts +991 -0
- package/src/module-registry.ts +547 -0
- package/src/modules/api/index.ts +94 -0
- package/src/modules/discord/discord-js-client.ts +353 -0
- package/src/modules/discord/index.ts +1146 -0
- package/src/modules/discord/types.ts +465 -0
- package/src/modules/index.ts +43 -0
- package/src/modules/workspace/index.ts +969 -0
- package/src/modules/workspace/sync.ts +314 -0
- package/src/modules/workspace/types.ts +202 -0
- package/src/modules/workspace/watcher.ts +142 -0
- package/src/queue.ts +106 -0
- package/src/safe-slice.ts +18 -0
- package/src/types/agent.ts +119 -0
- package/src/types/events.ts +252 -0
- package/src/types/framework.ts +211 -0
- package/src/types/index.ts +6 -0
- package/src/types/inference-log.ts +64 -0
- package/src/types/module.ts +367 -0
- package/src/types/trace.ts +196 -0
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server for Claude Code integration
|
|
3
|
+
*
|
|
4
|
+
* Exposes agent framework capabilities as MCP tools that can be called
|
|
5
|
+
* from Claude Code or other MCP clients.
|
|
6
|
+
*
|
|
7
|
+
* Communicates with the WebSocket API server to perform operations.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import WebSocket from 'ws';
|
|
11
|
+
import { createInterface } from 'node:readline';
|
|
12
|
+
import type { ApiRequest, ApiResponse, ApiEvent } from './types.js';
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// MCP Protocol Types
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
interface JsonRpcRequest {
|
|
19
|
+
jsonrpc: '2.0';
|
|
20
|
+
id: string | number;
|
|
21
|
+
method: string;
|
|
22
|
+
params?: unknown;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface JsonRpcResponse {
|
|
26
|
+
jsonrpc: '2.0';
|
|
27
|
+
id: string | number | null;
|
|
28
|
+
result?: unknown;
|
|
29
|
+
error?: {
|
|
30
|
+
code: number;
|
|
31
|
+
message: string;
|
|
32
|
+
data?: unknown;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface JsonRpcNotification {
|
|
37
|
+
jsonrpc: '2.0';
|
|
38
|
+
method: string;
|
|
39
|
+
params?: unknown;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface McpTool {
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: 'object';
|
|
47
|
+
properties: Record<string, unknown>;
|
|
48
|
+
required?: string[];
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface McpToolCall {
|
|
53
|
+
name: string;
|
|
54
|
+
arguments: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// MCP Server Implementation
|
|
59
|
+
// ============================================================================
|
|
60
|
+
|
|
61
|
+
export class McpServer {
|
|
62
|
+
private ws: WebSocket | null = null;
|
|
63
|
+
private wsUrl: string;
|
|
64
|
+
private requestId = 0;
|
|
65
|
+
private pendingRequests = new Map<
|
|
66
|
+
string,
|
|
67
|
+
{ resolve: (value: unknown) => void; reject: (error: Error) => void }
|
|
68
|
+
>();
|
|
69
|
+
private connected = false;
|
|
70
|
+
private reconnecting = false;
|
|
71
|
+
private reconnectInterval = 2000; // Retry every 2s
|
|
72
|
+
private closing = false;
|
|
73
|
+
|
|
74
|
+
constructor(wsUrl: string = 'ws://localhost:8765/ws') {
|
|
75
|
+
this.wsUrl = wsUrl;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Start the MCP server (stdio mode).
|
|
80
|
+
*/
|
|
81
|
+
async start(): Promise<void> {
|
|
82
|
+
// Connect to WebSocket API
|
|
83
|
+
await this.connectWs();
|
|
84
|
+
|
|
85
|
+
// Set up stdio interface
|
|
86
|
+
const rl = createInterface({
|
|
87
|
+
input: process.stdin,
|
|
88
|
+
output: process.stdout,
|
|
89
|
+
terminal: false,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
rl.on('line', (line) => {
|
|
93
|
+
this.handleInput(line);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
rl.on('close', () => {
|
|
97
|
+
this.close();
|
|
98
|
+
process.exit(0);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Handle SIGINT gracefully
|
|
102
|
+
process.on('SIGINT', () => {
|
|
103
|
+
this.close();
|
|
104
|
+
process.exit(0);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private async connectWs(): Promise<void> {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
this.ws = new WebSocket(this.wsUrl);
|
|
111
|
+
|
|
112
|
+
this.ws.on('open', () => {
|
|
113
|
+
this.connected = true;
|
|
114
|
+
this.reconnecting = false;
|
|
115
|
+
resolve();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
this.ws.on('message', (data) => {
|
|
119
|
+
this.handleWsMessage(data.toString());
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
this.ws.on('close', () => {
|
|
123
|
+
this.connected = false;
|
|
124
|
+
if (!this.closing) {
|
|
125
|
+
this.scheduleReconnect();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
this.ws.on('error', (error) => {
|
|
130
|
+
if (!this.connected) {
|
|
131
|
+
// Connection failed - reject so we can retry
|
|
132
|
+
reject(error);
|
|
133
|
+
} else {
|
|
134
|
+
// Connected but got an error - just log it
|
|
135
|
+
this.sendNotification('notifications/message', {
|
|
136
|
+
level: 'error',
|
|
137
|
+
logger: 'agent-framework',
|
|
138
|
+
data: `WebSocket error: ${error.message}`,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private scheduleReconnect(): void {
|
|
146
|
+
if (this.reconnecting || this.closing) return;
|
|
147
|
+
this.reconnecting = true;
|
|
148
|
+
|
|
149
|
+
setTimeout(() => {
|
|
150
|
+
if (this.closing) return;
|
|
151
|
+
this.connectWs().catch(() => {
|
|
152
|
+
this.reconnecting = false;
|
|
153
|
+
this.scheduleReconnect();
|
|
154
|
+
});
|
|
155
|
+
}, this.reconnectInterval);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private handleWsMessage(data: string): void {
|
|
159
|
+
try {
|
|
160
|
+
const message = JSON.parse(data) as ApiResponse | ApiEvent;
|
|
161
|
+
|
|
162
|
+
if (message.type === 'response' && 'id' in message && message.id) {
|
|
163
|
+
// Handle response to our request
|
|
164
|
+
const pending = this.pendingRequests.get(message.id);
|
|
165
|
+
if (pending) {
|
|
166
|
+
this.pendingRequests.delete(message.id);
|
|
167
|
+
if (message.success) {
|
|
168
|
+
pending.resolve(message.data);
|
|
169
|
+
} else {
|
|
170
|
+
pending.reject(new Error(message.error ?? 'Unknown error'));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} else if (message.type === 'event') {
|
|
174
|
+
// Forward events as MCP notifications
|
|
175
|
+
this.sendNotification('notifications/message', {
|
|
176
|
+
level: 'info',
|
|
177
|
+
logger: 'agent-framework',
|
|
178
|
+
data: `Event: ${message.event} - ${JSON.stringify(message.data)}`,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
} catch {
|
|
182
|
+
// Ignore parse errors
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private handleInput(line: string): void {
|
|
187
|
+
try {
|
|
188
|
+
const message = JSON.parse(line);
|
|
189
|
+
|
|
190
|
+
// Check if this is a notification (no id) or a request (has id)
|
|
191
|
+
if (!('id' in message) || message.id === undefined) {
|
|
192
|
+
// This is a notification - handle silently without response
|
|
193
|
+
// Common notifications: notifications/initialized, notifications/cancelled
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// This is a request - process and respond
|
|
198
|
+
this.handleRequest(message as JsonRpcRequest);
|
|
199
|
+
} catch {
|
|
200
|
+
this.sendError(null, -32700, 'Parse error');
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private async handleRequest(request: JsonRpcRequest): Promise<void> {
|
|
205
|
+
try {
|
|
206
|
+
switch (request.method) {
|
|
207
|
+
case 'initialize':
|
|
208
|
+
this.sendResult(request.id, {
|
|
209
|
+
protocolVersion: '2024-11-05',
|
|
210
|
+
capabilities: {
|
|
211
|
+
tools: {},
|
|
212
|
+
},
|
|
213
|
+
serverInfo: {
|
|
214
|
+
name: 'agent-framework',
|
|
215
|
+
version: '0.1.0',
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
break;
|
|
219
|
+
|
|
220
|
+
case 'initialized':
|
|
221
|
+
// Client acknowledgment, no response needed
|
|
222
|
+
break;
|
|
223
|
+
|
|
224
|
+
case 'tools/list':
|
|
225
|
+
this.sendResult(request.id, { tools: this.getTools() });
|
|
226
|
+
break;
|
|
227
|
+
|
|
228
|
+
case 'tools/call':
|
|
229
|
+
await this.handleToolCall(request);
|
|
230
|
+
break;
|
|
231
|
+
|
|
232
|
+
case 'ping':
|
|
233
|
+
this.sendResult(request.id, {});
|
|
234
|
+
break;
|
|
235
|
+
|
|
236
|
+
default:
|
|
237
|
+
this.sendError(request.id, -32601, `Method not found: ${request.method}`);
|
|
238
|
+
}
|
|
239
|
+
} catch (error) {
|
|
240
|
+
this.sendError(
|
|
241
|
+
request.id,
|
|
242
|
+
-32603,
|
|
243
|
+
error instanceof Error ? error.message : String(error)
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private getTools(): McpTool[] {
|
|
249
|
+
return [
|
|
250
|
+
{
|
|
251
|
+
name: 'agent_send_message',
|
|
252
|
+
description:
|
|
253
|
+
'Send a message to the agent framework. This will add the message to the conversation and optionally trigger inference.',
|
|
254
|
+
inputSchema: {
|
|
255
|
+
type: 'object',
|
|
256
|
+
properties: {
|
|
257
|
+
participant: {
|
|
258
|
+
type: 'string',
|
|
259
|
+
description: 'Name of the participant sending the message (e.g., "user")',
|
|
260
|
+
},
|
|
261
|
+
content: {
|
|
262
|
+
type: 'string',
|
|
263
|
+
description: 'The message content',
|
|
264
|
+
},
|
|
265
|
+
triggerInference: {
|
|
266
|
+
type: 'boolean',
|
|
267
|
+
description: 'Whether to trigger agent inference after sending (default: true)',
|
|
268
|
+
},
|
|
269
|
+
targetAgents: {
|
|
270
|
+
type: 'array',
|
|
271
|
+
items: { type: 'string' },
|
|
272
|
+
description: 'Specific agents to trigger (optional, defaults to all)',
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
required: ['participant', 'content'],
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'agent_list_messages',
|
|
280
|
+
description: 'List recent messages in the conversation',
|
|
281
|
+
inputSchema: {
|
|
282
|
+
type: 'object',
|
|
283
|
+
properties: {
|
|
284
|
+
limit: {
|
|
285
|
+
type: 'number',
|
|
286
|
+
description: 'Maximum number of messages to return (default: 50)',
|
|
287
|
+
},
|
|
288
|
+
offset: {
|
|
289
|
+
type: 'number',
|
|
290
|
+
description: 'Offset from the most recent message (default: 0)',
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: 'agent_request_inference',
|
|
297
|
+
description: 'Request the agent to run inference and generate a response',
|
|
298
|
+
inputSchema: {
|
|
299
|
+
type: 'object',
|
|
300
|
+
properties: {
|
|
301
|
+
agentName: {
|
|
302
|
+
type: 'string',
|
|
303
|
+
description: 'Specific agent to run (optional, defaults to all)',
|
|
304
|
+
},
|
|
305
|
+
reason: {
|
|
306
|
+
type: 'string',
|
|
307
|
+
description: 'Reason for the inference request',
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
name: 'branch_list',
|
|
314
|
+
description: 'List all branches in the agent framework',
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: 'object',
|
|
317
|
+
properties: {},
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
name: 'branch_create',
|
|
322
|
+
description: 'Create a new branch from the current state',
|
|
323
|
+
inputSchema: {
|
|
324
|
+
type: 'object',
|
|
325
|
+
properties: {
|
|
326
|
+
name: {
|
|
327
|
+
type: 'string',
|
|
328
|
+
description: 'Name for the new branch',
|
|
329
|
+
},
|
|
330
|
+
switchTo: {
|
|
331
|
+
type: 'boolean',
|
|
332
|
+
description: 'Whether to switch to the new branch after creation (default: false)',
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
required: ['name'],
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
name: 'branch_switch',
|
|
340
|
+
description: 'Switch to a different branch',
|
|
341
|
+
inputSchema: {
|
|
342
|
+
type: 'object',
|
|
343
|
+
properties: {
|
|
344
|
+
name: {
|
|
345
|
+
type: 'string',
|
|
346
|
+
description: 'Name of the branch to switch to',
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
required: ['name'],
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
name: 'branch_current',
|
|
354
|
+
description: 'Get the name of the current branch',
|
|
355
|
+
inputSchema: {
|
|
356
|
+
type: 'object',
|
|
357
|
+
properties: {},
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
name: 'branch_delete',
|
|
362
|
+
description: 'Delete a branch (cannot delete current or main branch)',
|
|
363
|
+
inputSchema: {
|
|
364
|
+
type: 'object',
|
|
365
|
+
properties: {
|
|
366
|
+
name: {
|
|
367
|
+
type: 'string',
|
|
368
|
+
description: 'Name of the branch to delete',
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
required: ['name'],
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
name: 'agent_list',
|
|
376
|
+
description: 'List all agents in the framework',
|
|
377
|
+
inputSchema: {
|
|
378
|
+
type: 'object',
|
|
379
|
+
properties: {},
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: 'agent_context',
|
|
384
|
+
description: "Get an agent's current context (compiled messages)",
|
|
385
|
+
inputSchema: {
|
|
386
|
+
type: 'object',
|
|
387
|
+
properties: {
|
|
388
|
+
agentName: {
|
|
389
|
+
type: 'string',
|
|
390
|
+
description: 'Name of the agent',
|
|
391
|
+
},
|
|
392
|
+
maxTokens: {
|
|
393
|
+
type: 'number',
|
|
394
|
+
description: 'Maximum tokens to include (optional)',
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
required: ['agentName'],
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
name: 'module_list',
|
|
402
|
+
description: 'List all modules registered with the framework',
|
|
403
|
+
inputSchema: {
|
|
404
|
+
type: 'object',
|
|
405
|
+
properties: {},
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
name: 'module_state',
|
|
410
|
+
description: "Get a module's current state",
|
|
411
|
+
inputSchema: {
|
|
412
|
+
type: 'object',
|
|
413
|
+
properties: {
|
|
414
|
+
moduleName: {
|
|
415
|
+
type: 'string',
|
|
416
|
+
description: 'Name of the module',
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
required: ['moduleName'],
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
name: 'store_states',
|
|
424
|
+
description: 'List all states in the store',
|
|
425
|
+
inputSchema: {
|
|
426
|
+
type: 'object',
|
|
427
|
+
properties: {
|
|
428
|
+
namespace: {
|
|
429
|
+
type: 'string',
|
|
430
|
+
description: "Filter by namespace prefix (e.g., 'agents/', 'modules/')",
|
|
431
|
+
},
|
|
432
|
+
limit: {
|
|
433
|
+
type: 'number',
|
|
434
|
+
description: 'Maximum number of states to return (default: 50)',
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
name: 'store_search',
|
|
441
|
+
description: 'Search through store states by namespace and/or content pattern',
|
|
442
|
+
inputSchema: {
|
|
443
|
+
type: 'object',
|
|
444
|
+
properties: {
|
|
445
|
+
namespace: {
|
|
446
|
+
type: 'string',
|
|
447
|
+
description: 'Filter by namespace prefix',
|
|
448
|
+
},
|
|
449
|
+
contentPattern: {
|
|
450
|
+
type: 'string',
|
|
451
|
+
description: 'Regex pattern to match against state content (JSON stringified)',
|
|
452
|
+
},
|
|
453
|
+
limit: {
|
|
454
|
+
type: 'number',
|
|
455
|
+
description: 'Maximum number of results (default: 20)',
|
|
456
|
+
},
|
|
457
|
+
offset: {
|
|
458
|
+
type: 'number',
|
|
459
|
+
description: 'Skip first N results for pagination (default: 0)',
|
|
460
|
+
},
|
|
461
|
+
previewLength: {
|
|
462
|
+
type: 'number',
|
|
463
|
+
description: 'Preview length in characters (default: 300)',
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
name: 'store_inspect',
|
|
470
|
+
description: 'Inspect a specific state in the store',
|
|
471
|
+
inputSchema: {
|
|
472
|
+
type: 'object',
|
|
473
|
+
properties: {
|
|
474
|
+
stateId: {
|
|
475
|
+
type: 'string',
|
|
476
|
+
description: 'ID of the state to inspect',
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
required: ['stateId'],
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
// Inference logging tools
|
|
483
|
+
{
|
|
484
|
+
name: 'inference_tail',
|
|
485
|
+
description: 'Get the most recent inference log entries. Shows raw LLM requests and responses for debugging.',
|
|
486
|
+
inputSchema: {
|
|
487
|
+
type: 'object',
|
|
488
|
+
properties: {
|
|
489
|
+
count: {
|
|
490
|
+
type: 'number',
|
|
491
|
+
description: 'Number of recent entries to return (default: 10)',
|
|
492
|
+
},
|
|
493
|
+
agentName: {
|
|
494
|
+
type: 'string',
|
|
495
|
+
description: 'Filter by agent name (optional)',
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
name: 'inference_inspect',
|
|
502
|
+
description: 'Inspect a specific inference log entry by sequence number. Returns full raw request and response.',
|
|
503
|
+
inputSchema: {
|
|
504
|
+
type: 'object',
|
|
505
|
+
properties: {
|
|
506
|
+
sequence: {
|
|
507
|
+
type: 'number',
|
|
508
|
+
description: 'Sequence number of the log entry to inspect',
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
required: ['sequence'],
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
name: 'inference_search',
|
|
516
|
+
description: 'Search through inference logs by agent, pattern, or error status. Useful for debugging specific issues.',
|
|
517
|
+
inputSchema: {
|
|
518
|
+
type: 'object',
|
|
519
|
+
properties: {
|
|
520
|
+
agentName: {
|
|
521
|
+
type: 'string',
|
|
522
|
+
description: 'Filter by agent name',
|
|
523
|
+
},
|
|
524
|
+
pattern: {
|
|
525
|
+
type: 'string',
|
|
526
|
+
description: 'Regex pattern to search in log content',
|
|
527
|
+
},
|
|
528
|
+
errorsOnly: {
|
|
529
|
+
type: 'boolean',
|
|
530
|
+
description: 'Only show failed inferences',
|
|
531
|
+
},
|
|
532
|
+
limit: {
|
|
533
|
+
type: 'number',
|
|
534
|
+
description: 'Maximum number of results (default: 20)',
|
|
535
|
+
},
|
|
536
|
+
offset: {
|
|
537
|
+
type: 'number',
|
|
538
|
+
description: 'Skip first N results for pagination (default: 0)',
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
];
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
private async handleToolCall(request: JsonRpcRequest): Promise<void> {
|
|
547
|
+
const params = request.params as { name: string; arguments: Record<string, unknown> };
|
|
548
|
+
const { name, arguments: args } = params;
|
|
549
|
+
|
|
550
|
+
// Map MCP tool names to API commands
|
|
551
|
+
const toolToCommand: Record<string, string> = {
|
|
552
|
+
agent_send_message: 'message.send',
|
|
553
|
+
agent_list_messages: 'message.list',
|
|
554
|
+
agent_request_inference: 'inference.request',
|
|
555
|
+
branch_list: 'branch.list',
|
|
556
|
+
branch_create: 'branch.create',
|
|
557
|
+
branch_switch: 'branch.switch',
|
|
558
|
+
branch_current: 'branch.current',
|
|
559
|
+
branch_delete: 'branch.delete',
|
|
560
|
+
agent_list: 'agent.list',
|
|
561
|
+
agent_context: 'agent.context',
|
|
562
|
+
module_list: 'module.list',
|
|
563
|
+
module_state: 'module.state',
|
|
564
|
+
store_states: 'store.states',
|
|
565
|
+
store_search: 'store.search',
|
|
566
|
+
store_inspect: 'store.inspect',
|
|
567
|
+
inference_tail: 'inference.tail',
|
|
568
|
+
inference_inspect: 'inference.inspect',
|
|
569
|
+
inference_search: 'inference.search',
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const command = toolToCommand[name];
|
|
573
|
+
if (!command) {
|
|
574
|
+
this.sendError(request.id, -32602, `Unknown tool: ${name}`);
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
try {
|
|
579
|
+
const result = await this.sendApiRequest(command, args);
|
|
580
|
+
this.sendResult(request.id, {
|
|
581
|
+
content: [
|
|
582
|
+
{
|
|
583
|
+
type: 'text',
|
|
584
|
+
text: JSON.stringify(result, null, 2),
|
|
585
|
+
},
|
|
586
|
+
],
|
|
587
|
+
});
|
|
588
|
+
} catch (error) {
|
|
589
|
+
this.sendResult(request.id, {
|
|
590
|
+
content: [
|
|
591
|
+
{
|
|
592
|
+
type: 'text',
|
|
593
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
594
|
+
},
|
|
595
|
+
],
|
|
596
|
+
isError: true,
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
private sendApiRequest(
|
|
602
|
+
command: string,
|
|
603
|
+
params: Record<string, unknown>
|
|
604
|
+
): Promise<unknown> {
|
|
605
|
+
return new Promise((resolve, reject) => {
|
|
606
|
+
if (!this.ws || !this.connected) {
|
|
607
|
+
reject(new Error('Not connected to API server'));
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
const id = `mcp-${++this.requestId}`;
|
|
612
|
+
this.pendingRequests.set(id, { resolve, reject });
|
|
613
|
+
|
|
614
|
+
const request: ApiRequest = {
|
|
615
|
+
type: 'request',
|
|
616
|
+
id,
|
|
617
|
+
command,
|
|
618
|
+
params,
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
this.ws.send(JSON.stringify(request));
|
|
622
|
+
|
|
623
|
+
// Timeout after 30 seconds
|
|
624
|
+
setTimeout(() => {
|
|
625
|
+
if (this.pendingRequests.has(id)) {
|
|
626
|
+
this.pendingRequests.delete(id);
|
|
627
|
+
reject(new Error('Request timeout'));
|
|
628
|
+
}
|
|
629
|
+
}, 30000);
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
private sendResult(id: string | number, result: unknown): void {
|
|
634
|
+
const response: JsonRpcResponse = {
|
|
635
|
+
jsonrpc: '2.0',
|
|
636
|
+
id,
|
|
637
|
+
result,
|
|
638
|
+
};
|
|
639
|
+
this.send(response);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
private sendError(id: string | number | null, code: number, message: string): void {
|
|
643
|
+
const response: JsonRpcResponse = {
|
|
644
|
+
jsonrpc: '2.0',
|
|
645
|
+
id,
|
|
646
|
+
error: { code, message },
|
|
647
|
+
};
|
|
648
|
+
this.send(response);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
private sendNotification(method: string, params: unknown): void {
|
|
652
|
+
const notification: JsonRpcNotification = {
|
|
653
|
+
jsonrpc: '2.0',
|
|
654
|
+
method,
|
|
655
|
+
params,
|
|
656
|
+
};
|
|
657
|
+
this.send(notification);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
private send(message: JsonRpcResponse | JsonRpcNotification): void {
|
|
661
|
+
process.stdout.write(JSON.stringify(message) + '\n');
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
close(): void {
|
|
665
|
+
this.closing = true;
|
|
666
|
+
if (this.ws) {
|
|
667
|
+
this.ws.close();
|
|
668
|
+
this.ws = null;
|
|
669
|
+
}
|
|
670
|
+
this.connected = false;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// ============================================================================
|
|
675
|
+
// CLI Entry Point
|
|
676
|
+
// ============================================================================
|
|
677
|
+
|
|
678
|
+
// Run if executed directly
|
|
679
|
+
const isMain = process.argv[1]?.endsWith('mcp-server.js');
|
|
680
|
+
if (isMain) {
|
|
681
|
+
const wsUrl = process.env.AGENT_FRAMEWORK_WS_URL ?? 'ws://localhost:8765/ws';
|
|
682
|
+
const server = new McpServer(wsUrl);
|
|
683
|
+
server.start().catch((error) => {
|
|
684
|
+
console.error('Failed to start MCP server:', error);
|
|
685
|
+
process.exit(1);
|
|
686
|
+
});
|
|
687
|
+
}
|