agenthub-multiagent-mcp 1.1.2 ā 1.1.4
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/README.md +170 -151
- package/dist/client.d.ts +3 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -1
- package/dist/client.js.map +1 -1
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -1
- package/dist/client.test.js +16 -1
- package/dist/client.test.js.map +1 -1
- package/dist/e2e.test.d.ts +1 -0
- package/dist/e2e.test.d.ts.map +1 -1
- package/dist/e2e.test.js +3 -1
- package/dist/e2e.test.js.map +1 -1
- package/dist/heartbeat.d.ts +11 -1
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +41 -3
- package/dist/heartbeat.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +13 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/tools.test.js +6 -1
- package/dist/tools/tools.test.js.map +1 -1
- package/package.json +53 -53
- package/src/client.test.ts +223 -208
- package/src/client.ts +293 -286
- package/src/e2e.test.ts +300 -298
- package/src/heartbeat.ts +45 -3
- package/src/index.ts +123 -123
- package/src/tools/index.ts +672 -666
- package/src/tools/tools.test.ts +522 -517
- package/vitest.config.ts +8 -0
package/src/heartbeat.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Background heartbeat manager
|
|
2
|
+
* Background heartbeat manager with enhanced logging for pending tasks/messages
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { ApiClient } from "./client.js";
|
|
@@ -9,6 +9,9 @@ export class HeartbeatManager {
|
|
|
9
9
|
private intervalId?: NodeJS.Timeout;
|
|
10
10
|
private agentId?: string;
|
|
11
11
|
private status: "online" | "busy" = "online";
|
|
12
|
+
private lastPendingTasks = 0;
|
|
13
|
+
private lastUnreadMessages = 0;
|
|
14
|
+
private heartbeatCount = 0;
|
|
12
15
|
|
|
13
16
|
constructor(client: ApiClient) {
|
|
14
17
|
this.client = client;
|
|
@@ -17,13 +20,16 @@ export class HeartbeatManager {
|
|
|
17
20
|
start(agentId: string): void {
|
|
18
21
|
this.stop(); // Clear any existing interval
|
|
19
22
|
this.agentId = agentId;
|
|
23
|
+
this.heartbeatCount = 0;
|
|
24
|
+
this.lastPendingTasks = 0;
|
|
25
|
+
this.lastUnreadMessages = 0;
|
|
20
26
|
|
|
21
27
|
// Send heartbeat every 30 seconds
|
|
22
28
|
this.intervalId = setInterval(async () => {
|
|
23
29
|
if (!this.agentId) return;
|
|
24
30
|
|
|
25
31
|
try {
|
|
26
|
-
await this.
|
|
32
|
+
await this.sendHeartbeat();
|
|
27
33
|
} catch (error) {
|
|
28
34
|
console.error("Heartbeat failed:", error);
|
|
29
35
|
}
|
|
@@ -58,9 +64,45 @@ export class HeartbeatManager {
|
|
|
58
64
|
if (!this.agentId) return;
|
|
59
65
|
|
|
60
66
|
try {
|
|
61
|
-
await this.client.heartbeat(this.agentId, this.status);
|
|
67
|
+
const response = await this.client.heartbeat(this.agentId, this.status);
|
|
68
|
+
this.heartbeatCount++;
|
|
69
|
+
|
|
70
|
+
const { pending_tasks_count, unread_messages_count } = response;
|
|
71
|
+
|
|
72
|
+
// Log if there are new pending tasks
|
|
73
|
+
if (pending_tasks_count > 0 && pending_tasks_count !== this.lastPendingTasks) {
|
|
74
|
+
console.error(`\nš [AgentHub] You have ${pending_tasks_count} pending task(s) waiting! Use get_pending_tasks to view them.\n`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Log if there are new unread messages
|
|
78
|
+
if (unread_messages_count > 0 && unread_messages_count !== this.lastUnreadMessages) {
|
|
79
|
+
console.error(`\nš¬ [AgentHub] You have ${unread_messages_count} unread message(s)! Use check_inbox to read them.\n`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Periodic reminder every 5 heartbeats (2.5 minutes) if there are pending items
|
|
83
|
+
if (this.heartbeatCount % 5 === 0) {
|
|
84
|
+
if (pending_tasks_count > 0 || unread_messages_count > 0) {
|
|
85
|
+
const parts = [];
|
|
86
|
+
if (pending_tasks_count > 0) parts.push(`${pending_tasks_count} pending task(s)`);
|
|
87
|
+
if (unread_messages_count > 0) parts.push(`${unread_messages_count} unread message(s)`);
|
|
88
|
+
console.error(`\nā° [AgentHub] Reminder: You have ${parts.join(" and ")}.\n`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
this.lastPendingTasks = pending_tasks_count;
|
|
93
|
+
this.lastUnreadMessages = unread_messages_count;
|
|
62
94
|
} catch (error) {
|
|
63
95
|
console.error("Heartbeat failed:", error);
|
|
64
96
|
}
|
|
65
97
|
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get the current pending counts (for use by tools)
|
|
101
|
+
*/
|
|
102
|
+
getPendingCounts(): { pendingTasks: number; unreadMessages: number } {
|
|
103
|
+
return {
|
|
104
|
+
pendingTasks: this.lastPendingTasks,
|
|
105
|
+
unreadMessages: this.lastUnreadMessages,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
66
108
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,123 +1,123 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
-
import {
|
|
6
|
-
CallToolRequestSchema,
|
|
7
|
-
ListToolsRequestSchema,
|
|
8
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
-
|
|
10
|
-
import { ApiClient } from "./client.js";
|
|
11
|
-
import { registerTools, handleToolCall } from "./tools/index.js";
|
|
12
|
-
import { HeartbeatManager } from "./heartbeat.js";
|
|
13
|
-
|
|
14
|
-
// Environment configuration
|
|
15
|
-
const AGENTHUB_URL = process.env.AGENTHUB_URL || "http://localhost:8787";
|
|
16
|
-
const AGENTHUB_API_KEY = process.env.AGENTHUB_API_KEY || "";
|
|
17
|
-
const AGENTHUB_AGENT_ID = process.env.AGENTHUB_AGENT_ID || "";
|
|
18
|
-
|
|
19
|
-
// Validate configuration
|
|
20
|
-
if (!AGENTHUB_API_KEY) {
|
|
21
|
-
console.error("Error: AGENTHUB_API_KEY environment variable is required");
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Initialize API client
|
|
26
|
-
const client = new ApiClient(AGENTHUB_URL, AGENTHUB_API_KEY);
|
|
27
|
-
|
|
28
|
-
// Initialize heartbeat manager
|
|
29
|
-
const heartbeat = new HeartbeatManager(client);
|
|
30
|
-
|
|
31
|
-
// Track current agent ID
|
|
32
|
-
let currentAgentId = AGENTHUB_AGENT_ID;
|
|
33
|
-
|
|
34
|
-
// Create MCP server
|
|
35
|
-
const server = new Server(
|
|
36
|
-
{
|
|
37
|
-
name: "agenthub",
|
|
38
|
-
version: "1.1.
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
capabilities: {
|
|
42
|
-
tools: {},
|
|
43
|
-
},
|
|
44
|
-
}
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
// List available tools
|
|
48
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
49
|
-
return {
|
|
50
|
-
tools: registerTools(),
|
|
51
|
-
};
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Handle tool calls
|
|
55
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
56
|
-
const { name, arguments: args } = request.params;
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
const result = await handleToolCall(name, args || {}, client, {
|
|
60
|
-
getCurrentAgentId: () => currentAgentId,
|
|
61
|
-
setCurrentAgentId: (id: string) => {
|
|
62
|
-
currentAgentId = id;
|
|
63
|
-
heartbeat.start(id);
|
|
64
|
-
},
|
|
65
|
-
stopHeartbeat: () => heartbeat.stop(),
|
|
66
|
-
getWorkingDir: () => process.cwd(),
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
content: [
|
|
71
|
-
{
|
|
72
|
-
type: "text",
|
|
73
|
-
text: JSON.stringify(result, null, 2),
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
};
|
|
77
|
-
} catch (error) {
|
|
78
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
79
|
-
return {
|
|
80
|
-
content: [
|
|
81
|
-
{
|
|
82
|
-
type: "text",
|
|
83
|
-
text: `Error: ${message}`,
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
isError: true,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// Graceful shutdown
|
|
92
|
-
process.on("SIGINT", () => {
|
|
93
|
-
heartbeat.stop();
|
|
94
|
-
process.exit(0);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
process.on("SIGTERM", () => {
|
|
98
|
-
heartbeat.stop();
|
|
99
|
-
process.exit(0);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Start server
|
|
103
|
-
async function main() {
|
|
104
|
-
const transport = new StdioServerTransport();
|
|
105
|
-
await server.connect(transport);
|
|
106
|
-
console.error("AgentHub MCP server running");
|
|
107
|
-
|
|
108
|
-
// Auto-register if agent ID is provided
|
|
109
|
-
if (AGENTHUB_AGENT_ID) {
|
|
110
|
-
try {
|
|
111
|
-
await client.registerAgent(AGENTHUB_AGENT_ID);
|
|
112
|
-
heartbeat.start(AGENTHUB_AGENT_ID);
|
|
113
|
-
console.error(`Auto-registered as agent: ${AGENTHUB_AGENT_ID}`);
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error(`Failed to auto-register: ${error}`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
main().catch((error) => {
|
|
121
|
-
console.error("Fatal error:", error);
|
|
122
|
-
process.exit(1);
|
|
123
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
ListToolsRequestSchema,
|
|
8
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
|
|
10
|
+
import { ApiClient } from "./client.js";
|
|
11
|
+
import { registerTools, handleToolCall } from "./tools/index.js";
|
|
12
|
+
import { HeartbeatManager } from "./heartbeat.js";
|
|
13
|
+
|
|
14
|
+
// Environment configuration
|
|
15
|
+
const AGENTHUB_URL = process.env.AGENTHUB_URL || "http://localhost:8787";
|
|
16
|
+
const AGENTHUB_API_KEY = process.env.AGENTHUB_API_KEY || "";
|
|
17
|
+
const AGENTHUB_AGENT_ID = process.env.AGENTHUB_AGENT_ID || "";
|
|
18
|
+
|
|
19
|
+
// Validate configuration
|
|
20
|
+
if (!AGENTHUB_API_KEY) {
|
|
21
|
+
console.error("Error: AGENTHUB_API_KEY environment variable is required");
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Initialize API client
|
|
26
|
+
const client = new ApiClient(AGENTHUB_URL, AGENTHUB_API_KEY);
|
|
27
|
+
|
|
28
|
+
// Initialize heartbeat manager
|
|
29
|
+
const heartbeat = new HeartbeatManager(client);
|
|
30
|
+
|
|
31
|
+
// Track current agent ID
|
|
32
|
+
let currentAgentId = AGENTHUB_AGENT_ID;
|
|
33
|
+
|
|
34
|
+
// Create MCP server
|
|
35
|
+
const server = new Server(
|
|
36
|
+
{
|
|
37
|
+
name: "agenthub",
|
|
38
|
+
version: "1.1.4",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
capabilities: {
|
|
42
|
+
tools: {},
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// List available tools
|
|
48
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
49
|
+
return {
|
|
50
|
+
tools: registerTools(),
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Handle tool calls
|
|
55
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
56
|
+
const { name, arguments: args } = request.params;
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const result = await handleToolCall(name, args || {}, client, {
|
|
60
|
+
getCurrentAgentId: () => currentAgentId,
|
|
61
|
+
setCurrentAgentId: (id: string) => {
|
|
62
|
+
currentAgentId = id;
|
|
63
|
+
heartbeat.start(id);
|
|
64
|
+
},
|
|
65
|
+
stopHeartbeat: () => heartbeat.stop(),
|
|
66
|
+
getWorkingDir: () => process.cwd(),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
72
|
+
type: "text",
|
|
73
|
+
text: JSON.stringify(result, null, 2),
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
} catch (error) {
|
|
78
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
79
|
+
return {
|
|
80
|
+
content: [
|
|
81
|
+
{
|
|
82
|
+
type: "text",
|
|
83
|
+
text: `Error: ${message}`,
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
isError: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Graceful shutdown
|
|
92
|
+
process.on("SIGINT", () => {
|
|
93
|
+
heartbeat.stop();
|
|
94
|
+
process.exit(0);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
process.on("SIGTERM", () => {
|
|
98
|
+
heartbeat.stop();
|
|
99
|
+
process.exit(0);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Start server
|
|
103
|
+
async function main() {
|
|
104
|
+
const transport = new StdioServerTransport();
|
|
105
|
+
await server.connect(transport);
|
|
106
|
+
console.error("AgentHub MCP server running");
|
|
107
|
+
|
|
108
|
+
// Auto-register if agent ID is provided
|
|
109
|
+
if (AGENTHUB_AGENT_ID) {
|
|
110
|
+
try {
|
|
111
|
+
await client.registerAgent(AGENTHUB_AGENT_ID);
|
|
112
|
+
heartbeat.start(AGENTHUB_AGENT_ID);
|
|
113
|
+
console.error(`Auto-registered as agent: ${AGENTHUB_AGENT_ID}`);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error(`Failed to auto-register: ${error}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
main().catch((error) => {
|
|
121
|
+
console.error("Fatal error:", error);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
});
|