@hailer/mcp 0.1.16 → 0.2.1
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/dist/app.js +24 -20
- package/dist/core.d.ts +33 -9
- package/dist/core.js +279 -147
- package/dist/mcp/UserContextCache.js +18 -0
- package/dist/mcp/hailer-clients.d.ts +9 -1
- package/dist/mcp/hailer-clients.js +13 -3
- package/dist/mcp/signal-handler.js +1 -1
- package/dist/mcp/tool-registry.d.ts +3 -1
- package/dist/mcp/tool-registry.js +4 -1
- package/dist/mcp/tools/activity.js +43 -34
- package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
- package/dist/mcp/tools/bot-config/constants.js +94 -0
- package/dist/mcp/tools/{bot-config.d.ts → bot-config/core.d.ts} +6 -6
- package/dist/mcp/tools/{bot-config.js → bot-config/core.js} +15 -15
- package/dist/mcp/tools/bot-config/index.d.ts +10 -0
- package/dist/mcp/tools/bot-config/index.js +59 -0
- package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
- package/dist/mcp/tools/bot-config/tools.js +15 -0
- package/dist/mcp/tools/bot-config/types.d.ts +50 -0
- package/dist/mcp/tools/bot-config/types.js +6 -0
- package/dist/mcp/tools/bug-fixer-tools.d.ts +21 -0
- package/dist/mcp/tools/{giuseppe-tools.js → bug-fixer-tools.js} +61 -61
- package/dist/mcp/tools/user.js +10 -29
- package/dist/mcp/tools/workflow.js +36 -2
- package/dist/mcp/utils/data-transformers.d.ts +0 -8
- package/dist/mcp/utils/data-transformers.js +0 -28
- package/dist/mcp/utils/index.d.ts +4 -1
- package/dist/mcp/utils/index.js +17 -3
- package/dist/mcp/utils/pagination.d.ts +40 -0
- package/dist/mcp/utils/pagination.js +55 -0
- package/dist/mcp/utils/response-builder.d.ts +53 -0
- package/dist/mcp/utils/response-builder.js +110 -0
- package/dist/mcp/utils/tool-helpers.d.ts +0 -8
- package/dist/mcp/utils/tool-helpers.js +0 -24
- package/dist/mcp/utils/types.d.ts +1 -33
- package/dist/mcp/webhook-handler.d.ts +2 -2
- package/dist/mcp/webhook-handler.js +5 -3
- package/dist/mcp-server.d.ts +2 -2
- package/dist/mcp-server.js +167 -140
- package/package.json +1 -1
- package/REFACTOR_STATUS.md +0 -127
- package/dist/agents/bot-manager.d.ts +0 -48
- package/dist/agents/bot-manager.js +0 -254
- package/dist/agents/factory.d.ts +0 -150
- package/dist/agents/factory.js +0 -650
- package/dist/agents/giuseppe/ai.d.ts +0 -83
- package/dist/agents/giuseppe/ai.js +0 -466
- package/dist/agents/giuseppe/bot.d.ts +0 -110
- package/dist/agents/giuseppe/bot.js +0 -780
- package/dist/agents/giuseppe/config.d.ts +0 -25
- package/dist/agents/giuseppe/config.js +0 -227
- package/dist/agents/giuseppe/files.d.ts +0 -52
- package/dist/agents/giuseppe/files.js +0 -338
- package/dist/agents/giuseppe/git.d.ts +0 -48
- package/dist/agents/giuseppe/git.js +0 -298
- package/dist/agents/giuseppe/index.d.ts +0 -97
- package/dist/agents/giuseppe/index.js +0 -258
- package/dist/agents/giuseppe/lsp.d.ts +0 -113
- package/dist/agents/giuseppe/lsp.js +0 -485
- package/dist/agents/giuseppe/monitor.d.ts +0 -118
- package/dist/agents/giuseppe/monitor.js +0 -621
- package/dist/agents/giuseppe/prompt.d.ts +0 -5
- package/dist/agents/giuseppe/prompt.js +0 -94
- package/dist/agents/giuseppe/registries/pending-classification.d.ts +0 -28
- package/dist/agents/giuseppe/registries/pending-classification.js +0 -50
- package/dist/agents/giuseppe/registries/pending-fix.d.ts +0 -30
- package/dist/agents/giuseppe/registries/pending-fix.js +0 -42
- package/dist/agents/giuseppe/registries/pending.d.ts +0 -27
- package/dist/agents/giuseppe/registries/pending.js +0 -49
- package/dist/agents/giuseppe/specialist.d.ts +0 -47
- package/dist/agents/giuseppe/specialist.js +0 -237
- package/dist/agents/giuseppe/types.d.ts +0 -123
- package/dist/agents/giuseppe/types.js +0 -9
- package/dist/agents/hailer-expert/index.d.ts +0 -8
- package/dist/agents/hailer-expert/index.js +0 -14
- package/dist/agents/hal/daemon.d.ts +0 -142
- package/dist/agents/hal/daemon.js +0 -1103
- package/dist/agents/hal/definitions.d.ts +0 -55
- package/dist/agents/hal/definitions.js +0 -263
- package/dist/agents/hal/index.d.ts +0 -3
- package/dist/agents/hal/index.js +0 -8
- package/dist/agents/index.d.ts +0 -18
- package/dist/agents/index.js +0 -48
- package/dist/agents/shared/base.d.ts +0 -216
- package/dist/agents/shared/base.js +0 -846
- package/dist/agents/shared/services/agent-registry.d.ts +0 -107
- package/dist/agents/shared/services/agent-registry.js +0 -629
- package/dist/agents/shared/services/conversation-manager.d.ts +0 -50
- package/dist/agents/shared/services/conversation-manager.js +0 -136
- package/dist/agents/shared/services/mcp-client.d.ts +0 -56
- package/dist/agents/shared/services/mcp-client.js +0 -124
- package/dist/agents/shared/services/message-classifier.d.ts +0 -37
- package/dist/agents/shared/services/message-classifier.js +0 -187
- package/dist/agents/shared/services/message-formatter.d.ts +0 -89
- package/dist/agents/shared/services/message-formatter.js +0 -371
- package/dist/agents/shared/services/session-logger.d.ts +0 -106
- package/dist/agents/shared/services/session-logger.js +0 -446
- package/dist/agents/shared/services/tool-executor.d.ts +0 -41
- package/dist/agents/shared/services/tool-executor.js +0 -169
- package/dist/agents/shared/services/workspace-schema-cache.d.ts +0 -125
- package/dist/agents/shared/services/workspace-schema-cache.js +0 -578
- package/dist/agents/shared/specialist.d.ts +0 -91
- package/dist/agents/shared/specialist.js +0 -399
- package/dist/agents/shared/tool-schema-loader.d.ts +0 -62
- package/dist/agents/shared/tool-schema-loader.js +0 -232
- package/dist/agents/shared/types.d.ts +0 -327
- package/dist/agents/shared/types.js +0 -121
- package/dist/client/agents/base.d.ts +0 -207
- package/dist/client/agents/base.js +0 -744
- package/dist/client/agents/definitions.d.ts +0 -53
- package/dist/client/agents/definitions.js +0 -263
- package/dist/client/agents/orchestrator.d.ts +0 -141
- package/dist/client/agents/orchestrator.js +0 -1062
- package/dist/client/agents/specialist.d.ts +0 -86
- package/dist/client/agents/specialist.js +0 -340
- package/dist/client/bot-entrypoint.d.ts +0 -7
- package/dist/client/bot-entrypoint.js +0 -103
- package/dist/client/bot-manager.d.ts +0 -44
- package/dist/client/bot-manager.js +0 -173
- package/dist/client/bot-runner.d.ts +0 -35
- package/dist/client/bot-runner.js +0 -188
- package/dist/client/chat-agent-daemon.d.ts +0 -464
- package/dist/client/chat-agent-daemon.js +0 -1774
- package/dist/client/daemon-factory.d.ts +0 -106
- package/dist/client/daemon-factory.js +0 -301
- package/dist/client/factory.d.ts +0 -111
- package/dist/client/factory.js +0 -314
- package/dist/client/index.d.ts +0 -17
- package/dist/client/index.js +0 -38
- package/dist/client/multi-bot-manager.d.ts +0 -42
- package/dist/client/multi-bot-manager.js +0 -161
- package/dist/client/orchestrator-daemon.d.ts +0 -87
- package/dist/client/orchestrator-daemon.js +0 -444
- package/dist/client/server.d.ts +0 -8
- package/dist/client/server.js +0 -251
- package/dist/client/services/agent-registry.d.ts +0 -108
- package/dist/client/services/agent-registry.js +0 -630
- package/dist/client/services/conversation-manager.d.ts +0 -50
- package/dist/client/services/conversation-manager.js +0 -136
- package/dist/client/services/mcp-client.d.ts +0 -48
- package/dist/client/services/mcp-client.js +0 -105
- package/dist/client/services/message-classifier.d.ts +0 -37
- package/dist/client/services/message-classifier.js +0 -187
- package/dist/client/services/message-formatter.d.ts +0 -84
- package/dist/client/services/message-formatter.js +0 -353
- package/dist/client/services/session-logger.d.ts +0 -106
- package/dist/client/services/session-logger.js +0 -446
- package/dist/client/services/tool-executor.d.ts +0 -41
- package/dist/client/services/tool-executor.js +0 -169
- package/dist/client/services/workspace-schema-cache.d.ts +0 -149
- package/dist/client/services/workspace-schema-cache.js +0 -732
- package/dist/client/specialist-daemon.d.ts +0 -77
- package/dist/client/specialist-daemon.js +0 -197
- package/dist/client/specialists.d.ts +0 -53
- package/dist/client/specialists.js +0 -178
- package/dist/client/tool-schema-loader.d.ts +0 -62
- package/dist/client/tool-schema-loader.js +0 -232
- package/dist/client/types.d.ts +0 -327
- package/dist/client/types.js +0 -121
- package/dist/commands/seed-config.d.ts +0 -9
- package/dist/commands/seed-config.js +0 -372
- package/dist/lib/context-manager.d.ts +0 -111
- package/dist/lib/context-manager.js +0 -431
- package/dist/lib/prompt-length-manager.d.ts +0 -81
- package/dist/lib/prompt-length-manager.js +0 -457
- package/dist/mcp/tools/giuseppe-tools.d.ts +0 -21
- package/dist/modules/bug-reports/bug-config.d.ts +0 -25
- package/dist/modules/bug-reports/bug-config.js +0 -187
- package/dist/modules/bug-reports/bug-monitor.d.ts +0 -108
- package/dist/modules/bug-reports/bug-monitor.js +0 -510
- package/dist/modules/bug-reports/giuseppe-agent.d.ts +0 -58
- package/dist/modules/bug-reports/giuseppe-agent.js +0 -467
- package/dist/modules/bug-reports/giuseppe-ai.d.ts +0 -83
- package/dist/modules/bug-reports/giuseppe-ai.js +0 -466
- package/dist/modules/bug-reports/giuseppe-bot.d.ts +0 -110
- package/dist/modules/bug-reports/giuseppe-bot.js +0 -804
- package/dist/modules/bug-reports/giuseppe-daemon.d.ts +0 -80
- package/dist/modules/bug-reports/giuseppe-daemon.js +0 -617
- package/dist/modules/bug-reports/giuseppe-files.d.ts +0 -64
- package/dist/modules/bug-reports/giuseppe-files.js +0 -375
- package/dist/modules/bug-reports/giuseppe-git.d.ts +0 -48
- package/dist/modules/bug-reports/giuseppe-git.js +0 -298
- package/dist/modules/bug-reports/giuseppe-lsp.d.ts +0 -113
- package/dist/modules/bug-reports/giuseppe-lsp.js +0 -485
- package/dist/modules/bug-reports/giuseppe-prompt.d.ts +0 -5
- package/dist/modules/bug-reports/giuseppe-prompt.js +0 -94
- package/dist/modules/bug-reports/index.d.ts +0 -77
- package/dist/modules/bug-reports/index.js +0 -215
- package/dist/modules/bug-reports/pending-classification-registry.d.ts +0 -28
- package/dist/modules/bug-reports/pending-classification-registry.js +0 -50
- package/dist/modules/bug-reports/pending-fix-registry.d.ts +0 -30
- package/dist/modules/bug-reports/pending-fix-registry.js +0 -42
- package/dist/modules/bug-reports/pending-registry.d.ts +0 -27
- package/dist/modules/bug-reports/pending-registry.js +0 -49
- package/dist/modules/bug-reports/types.d.ts +0 -123
- package/dist/modules/bug-reports/types.js +0 -9
- package/dist/routes/agents.d.ts +0 -44
- package/dist/routes/agents.js +0 -311
- package/dist/services/agent-credential-store.d.ts +0 -73
- package/dist/services/agent-credential-store.js +0 -212
- package/dist/services/bug-monitor.d.ts +0 -23
- package/dist/services/bug-monitor.js +0 -275
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response Builder Utility
|
|
3
|
+
*
|
|
4
|
+
* Centralized response formatting for MCP tools.
|
|
5
|
+
* Eliminates duplication of { type: 'text', text: '...' } patterns.
|
|
6
|
+
*/
|
|
7
|
+
import type { McpResponse } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Build a text response (most common pattern)
|
|
10
|
+
*/
|
|
11
|
+
export declare function textResponse(text: string): McpResponse;
|
|
12
|
+
/**
|
|
13
|
+
* Build an error response
|
|
14
|
+
*/
|
|
15
|
+
export declare function errorResponse(message: string, details?: string): McpResponse;
|
|
16
|
+
/**
|
|
17
|
+
* Build a success response with optional emoji
|
|
18
|
+
*/
|
|
19
|
+
export declare function successResponse(message: string, emoji?: string): McpResponse;
|
|
20
|
+
/**
|
|
21
|
+
* Build a JSON response (formatted with indentation)
|
|
22
|
+
*/
|
|
23
|
+
export declare function jsonResponse(data: unknown, prefix?: string): McpResponse;
|
|
24
|
+
/**
|
|
25
|
+
* Build a paginated response
|
|
26
|
+
*/
|
|
27
|
+
export declare function paginatedResponse(items: unknown[], options: {
|
|
28
|
+
currentPage: number;
|
|
29
|
+
limit: number;
|
|
30
|
+
totalCount?: number;
|
|
31
|
+
title?: string;
|
|
32
|
+
}): McpResponse;
|
|
33
|
+
/**
|
|
34
|
+
* Build a list response with header
|
|
35
|
+
*/
|
|
36
|
+
export declare function listResponse(items: unknown[], header: string, emptyMessage?: string): McpResponse;
|
|
37
|
+
/**
|
|
38
|
+
* Extract error message from unknown error type
|
|
39
|
+
* Centralizes the common pattern: error instanceof Error ? error.message : String(error)
|
|
40
|
+
*/
|
|
41
|
+
export declare function getErrorMessage(error: unknown): string;
|
|
42
|
+
/**
|
|
43
|
+
* Wrap an async operation with standard error handling
|
|
44
|
+
* Returns McpResponse on error, or result on success
|
|
45
|
+
*/
|
|
46
|
+
export declare function withErrorHandling<T>(operation: () => Promise<T>, errorContext?: string): Promise<T | McpResponse>;
|
|
47
|
+
/**
|
|
48
|
+
* Type guard to check if result is an error response
|
|
49
|
+
*/
|
|
50
|
+
export declare function isErrorResponse(result: unknown): result is McpResponse & {
|
|
51
|
+
isError: true;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=response-builder.d.ts.map
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Response Builder Utility
|
|
4
|
+
*
|
|
5
|
+
* Centralized response formatting for MCP tools.
|
|
6
|
+
* Eliminates duplication of { type: 'text', text: '...' } patterns.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.textResponse = textResponse;
|
|
10
|
+
exports.errorResponse = errorResponse;
|
|
11
|
+
exports.successResponse = successResponse;
|
|
12
|
+
exports.jsonResponse = jsonResponse;
|
|
13
|
+
exports.paginatedResponse = paginatedResponse;
|
|
14
|
+
exports.listResponse = listResponse;
|
|
15
|
+
exports.getErrorMessage = getErrorMessage;
|
|
16
|
+
exports.withErrorHandling = withErrorHandling;
|
|
17
|
+
exports.isErrorResponse = isErrorResponse;
|
|
18
|
+
/**
|
|
19
|
+
* Build a text response (most common pattern)
|
|
20
|
+
*/
|
|
21
|
+
function textResponse(text) {
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: 'text', text }]
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build an error response
|
|
28
|
+
*/
|
|
29
|
+
function errorResponse(message, details) {
|
|
30
|
+
const text = details ? `${message}\n\n${details}` : message;
|
|
31
|
+
return {
|
|
32
|
+
content: [{ type: 'text', text }],
|
|
33
|
+
isError: true
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a success response with optional emoji
|
|
38
|
+
*/
|
|
39
|
+
function successResponse(message, emoji = '✅') {
|
|
40
|
+
return textResponse(`${emoji} ${message}`);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build a JSON response (formatted with indentation)
|
|
44
|
+
*/
|
|
45
|
+
function jsonResponse(data, prefix) {
|
|
46
|
+
const json = JSON.stringify(data, null, 2);
|
|
47
|
+
const text = prefix ? `${prefix}\n\n${json}` : json;
|
|
48
|
+
return textResponse(text);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build a paginated response
|
|
52
|
+
*/
|
|
53
|
+
function paginatedResponse(items, options) {
|
|
54
|
+
const { currentPage, limit, totalCount, title } = options;
|
|
55
|
+
const hasMore = items.length === limit;
|
|
56
|
+
let text = '';
|
|
57
|
+
if (title)
|
|
58
|
+
text += `${title}\n\n`;
|
|
59
|
+
text += `📊 **Page ${currentPage + 1}**\n`;
|
|
60
|
+
text += `- Items: ${items.length}\n`;
|
|
61
|
+
if (totalCount !== undefined)
|
|
62
|
+
text += `- Total: ${totalCount}\n`;
|
|
63
|
+
text += `- Has more: ${hasMore ? 'Yes' : 'No'}\n\n`;
|
|
64
|
+
text += JSON.stringify(items, null, 2);
|
|
65
|
+
return textResponse(text);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build a list response with header
|
|
69
|
+
*/
|
|
70
|
+
function listResponse(items, header, emptyMessage = 'No items found') {
|
|
71
|
+
if (items.length === 0) {
|
|
72
|
+
return textResponse(emptyMessage);
|
|
73
|
+
}
|
|
74
|
+
return textResponse(`${header}\n\n${JSON.stringify(items, null, 2)}`);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Extract error message from unknown error type
|
|
78
|
+
* Centralizes the common pattern: error instanceof Error ? error.message : String(error)
|
|
79
|
+
*/
|
|
80
|
+
function getErrorMessage(error) {
|
|
81
|
+
if (error instanceof Error)
|
|
82
|
+
return error.message;
|
|
83
|
+
if (typeof error === 'string')
|
|
84
|
+
return error;
|
|
85
|
+
return String(error);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Wrap an async operation with standard error handling
|
|
89
|
+
* Returns McpResponse on error, or result on success
|
|
90
|
+
*/
|
|
91
|
+
async function withErrorHandling(operation, errorContext) {
|
|
92
|
+
try {
|
|
93
|
+
return await operation();
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
const message = getErrorMessage(error);
|
|
97
|
+
const fullMessage = errorContext ? `${errorContext}: ${message}` : message;
|
|
98
|
+
return errorResponse('Error', fullMessage);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Type guard to check if result is an error response
|
|
103
|
+
*/
|
|
104
|
+
function isErrorResponse(result) {
|
|
105
|
+
return (typeof result === 'object' &&
|
|
106
|
+
result !== null &&
|
|
107
|
+
'isError' in result &&
|
|
108
|
+
result.isError === true);
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=response-builder.js.map
|
|
@@ -91,12 +91,4 @@ export declare function getRequiredWorkspaceId(args: {
|
|
|
91
91
|
* ```
|
|
92
92
|
*/
|
|
93
93
|
export declare function extractErrorMessage(error: unknown): string;
|
|
94
|
-
/**
|
|
95
|
-
* Creates a standard success response with formatted text.
|
|
96
|
-
*/
|
|
97
|
-
export declare function successResponse(text: string): McpResponse;
|
|
98
|
-
/**
|
|
99
|
-
* Creates a standard error response with formatted text.
|
|
100
|
-
*/
|
|
101
|
-
export declare function errorResponse(text: string): McpResponse;
|
|
102
94
|
//# sourceMappingURL=tool-helpers.d.ts.map
|
|
@@ -11,8 +11,6 @@ exports.missingWorkspaceCacheResponse = missingWorkspaceCacheResponse;
|
|
|
11
11
|
exports.getResolvedWorkspaceId = getResolvedWorkspaceId;
|
|
12
12
|
exports.getRequiredWorkspaceId = getRequiredWorkspaceId;
|
|
13
13
|
exports.extractErrorMessage = extractErrorMessage;
|
|
14
|
-
exports.successResponse = successResponse;
|
|
15
|
-
exports.errorResponse = errorResponse;
|
|
16
14
|
const workspace_cache_1 = require("../workspace-cache");
|
|
17
15
|
/**
|
|
18
16
|
* Error thrown when workspace cache is not available
|
|
@@ -154,26 +152,4 @@ function extractErrorMessage(error) {
|
|
|
154
152
|
}
|
|
155
153
|
return String(error);
|
|
156
154
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Creates a standard success response with formatted text.
|
|
159
|
-
*/
|
|
160
|
-
function successResponse(text) {
|
|
161
|
-
return {
|
|
162
|
-
content: [{
|
|
163
|
-
type: "text",
|
|
164
|
-
text,
|
|
165
|
-
}],
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Creates a standard error response with formatted text.
|
|
170
|
-
*/
|
|
171
|
-
function errorResponse(text) {
|
|
172
|
-
return {
|
|
173
|
-
content: [{
|
|
174
|
-
type: "text",
|
|
175
|
-
text: `${text}`,
|
|
176
|
-
}],
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
155
|
//# sourceMappingURL=tool-helpers.js.map
|
|
@@ -133,6 +133,7 @@ export interface McpTextContent {
|
|
|
133
133
|
}
|
|
134
134
|
export interface McpResponse {
|
|
135
135
|
content: McpTextContent[];
|
|
136
|
+
isError?: boolean;
|
|
136
137
|
}
|
|
137
138
|
export interface ActivityListFilters {
|
|
138
139
|
processId?: string;
|
|
@@ -168,13 +169,6 @@ export interface SearchOptions {
|
|
|
168
169
|
limit?: number;
|
|
169
170
|
workspaceId?: string;
|
|
170
171
|
}
|
|
171
|
-
export interface InitData {
|
|
172
|
-
processes: any[];
|
|
173
|
-
users: Record<string, HailerUser>;
|
|
174
|
-
currentUser?: HailerUser;
|
|
175
|
-
workspace?: WorkspaceInfo;
|
|
176
|
-
networks?: any[];
|
|
177
|
-
}
|
|
178
172
|
export interface WorkspaceInfo {
|
|
179
173
|
_id: string;
|
|
180
174
|
name: string;
|
|
@@ -182,32 +176,6 @@ export interface WorkspaceInfo {
|
|
|
182
176
|
members?: string[];
|
|
183
177
|
settings?: Record<string, any>;
|
|
184
178
|
}
|
|
185
|
-
export interface NetworkInfo {
|
|
186
|
-
_id: string;
|
|
187
|
-
name: string;
|
|
188
|
-
workspaces: string[];
|
|
189
|
-
}
|
|
190
|
-
export interface ClientConfig {
|
|
191
|
-
email: string;
|
|
192
|
-
password: string;
|
|
193
|
-
mcpServerApiKey: string;
|
|
194
|
-
apiBaseUrl?: string;
|
|
195
|
-
}
|
|
196
|
-
export interface McpConfig {
|
|
197
|
-
clients: ClientConfig[];
|
|
198
|
-
logging?: {
|
|
199
|
-
level: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
|
|
200
|
-
enableApiLogging: boolean;
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
export interface ApiErrorInfo {
|
|
204
|
-
status: number;
|
|
205
|
-
statusText: string;
|
|
206
|
-
message: string;
|
|
207
|
-
operation: string;
|
|
208
|
-
endpoint: string;
|
|
209
|
-
responseBody?: string;
|
|
210
|
-
}
|
|
211
179
|
export interface SignalData {
|
|
212
180
|
type: string;
|
|
213
181
|
data: any;
|
|
@@ -19,11 +19,11 @@ export declare function verifyWebhookSignature(payload: string, signature: strin
|
|
|
19
19
|
* Production: WEBHOOK_TOKEN env var (injected by AWS Secrets Manager)
|
|
20
20
|
* Development: Falls back to file-based token for local testing
|
|
21
21
|
*/
|
|
22
|
-
export declare function getWebhookToken(): string;
|
|
22
|
+
export declare function getWebhookToken(): string | null;
|
|
23
23
|
/**
|
|
24
24
|
* Get the full webhook path with token (no prefix for security through obscurity)
|
|
25
25
|
*/
|
|
26
|
-
export declare function getWebhookPath(): string;
|
|
26
|
+
export declare function getWebhookPath(): string | null;
|
|
27
27
|
interface WebhookField {
|
|
28
28
|
id: string;
|
|
29
29
|
type: string;
|
|
@@ -107,9 +107,10 @@ function getWebhookToken() {
|
|
|
107
107
|
logger.debug('Using webhook token from environment');
|
|
108
108
|
return process.env.WEBHOOK_TOKEN;
|
|
109
109
|
}
|
|
110
|
-
//
|
|
110
|
+
// Production without WEBHOOK_TOKEN: webhooks disabled (optional feature)
|
|
111
111
|
if (process.env.NODE_ENV === 'production') {
|
|
112
|
-
|
|
112
|
+
logger.info('WEBHOOK_TOKEN not set - webhook endpoint disabled');
|
|
113
|
+
return null;
|
|
113
114
|
}
|
|
114
115
|
const configDir = path.join(process.cwd(), BOT_CONFIG_DIR);
|
|
115
116
|
const secretPath = path.join(configDir, WEBHOOK_SECRET_FILE);
|
|
@@ -140,7 +141,8 @@ function getWebhookToken() {
|
|
|
140
141
|
* Get the full webhook path with token (no prefix for security through obscurity)
|
|
141
142
|
*/
|
|
142
143
|
function getWebhookPath() {
|
|
143
|
-
|
|
144
|
+
const token = getWebhookToken();
|
|
145
|
+
return token ? `/${token}` : null;
|
|
144
146
|
}
|
|
145
147
|
let botUpdateCallback = null;
|
|
146
148
|
function onBotUpdate(callback) {
|
package/dist/mcp-server.d.ts
CHANGED
|
@@ -16,10 +16,10 @@ export interface MCPServerConfig {
|
|
|
16
16
|
port: number;
|
|
17
17
|
corsOrigins: string[];
|
|
18
18
|
toolRegistry: ToolRegistry;
|
|
19
|
-
getDaemonStatus?: () => Array<{
|
|
19
|
+
getDaemonStatus?: () => Record<string, Array<{
|
|
20
20
|
botId: string;
|
|
21
21
|
state: any;
|
|
22
|
-
}
|
|
22
|
+
}>>;
|
|
23
23
|
}
|
|
24
24
|
export declare class MCPServerService {
|
|
25
25
|
private app;
|
package/dist/mcp-server.js
CHANGED
|
@@ -166,23 +166,24 @@ class MCPServerService {
|
|
|
166
166
|
req.logger.debug('No config found for apiKey, returning all tools');
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
-
// Apply
|
|
170
|
-
if
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Filter has groups - remove NUCLEAR if present
|
|
179
|
-
filterConfig.allowedGroups = filterConfig.allowedGroups.filter(g => g !== tool_registry_1.ToolGroup.NUCLEAR);
|
|
180
|
-
}
|
|
181
|
-
// Note: If filter has explicit allowedTools list, NUCLEAR tools won't be in it anyway
|
|
182
|
-
req.logger.debug('NUCLEAR tools blocked (not explicitly enabled)');
|
|
169
|
+
// Apply default tool group filtering
|
|
170
|
+
// - NUCLEAR: Only if ENABLE_NUCLEAR_TOOLS=true
|
|
171
|
+
// - BOT_INTERNAL: Never exposed to MCP clients (autonomous bot tools only)
|
|
172
|
+
if (!filterConfig) {
|
|
173
|
+
// No filter yet - create default excluding NUCLEAR and BOT_INTERNAL
|
|
174
|
+
filterConfig = {
|
|
175
|
+
allowedGroups: [tool_registry_1.ToolGroup.READ, tool_registry_1.ToolGroup.WRITE, tool_registry_1.ToolGroup.PLAYGROUND]
|
|
176
|
+
};
|
|
177
|
+
req.logger.debug('Using default tool filter (excludes NUCLEAR and BOT_INTERNAL)');
|
|
183
178
|
}
|
|
184
|
-
else {
|
|
185
|
-
|
|
179
|
+
else if (filterConfig.allowedGroups) {
|
|
180
|
+
// Filter has groups - always remove BOT_INTERNAL, remove NUCLEAR unless enabled
|
|
181
|
+
filterConfig.allowedGroups = filterConfig.allowedGroups.filter(g => g !== tool_registry_1.ToolGroup.BOT_INTERNAL &&
|
|
182
|
+
(config_1.environment.ENABLE_NUCLEAR_TOOLS || g !== tool_registry_1.ToolGroup.NUCLEAR));
|
|
183
|
+
req.logger.debug('Filtered tool groups', {
|
|
184
|
+
allowedGroups: filterConfig.allowedGroups,
|
|
185
|
+
nuclearEnabled: config_1.environment.ENABLE_NUCLEAR_TOOLS
|
|
186
|
+
});
|
|
186
187
|
}
|
|
187
188
|
result = {
|
|
188
189
|
tools: this.toolRegistry.getToolDefinitions(filterConfig)
|
|
@@ -248,141 +249,167 @@ class MCPServerService {
|
|
|
248
249
|
res.end();
|
|
249
250
|
}
|
|
250
251
|
catch (error) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
req.logger.debug('List bots requested');
|
|
259
|
-
try {
|
|
260
|
-
const { AVAILABLE_BOTS, getBotState } = await Promise.resolve().then(() => __importStar(require('./mcp/tools/bot-config')));
|
|
261
|
-
const state = getBotState();
|
|
262
|
-
const bots = AVAILABLE_BOTS.map(bot => ({
|
|
263
|
-
...bot,
|
|
264
|
-
enabled: state[bot.id] || false
|
|
265
|
-
}));
|
|
266
|
-
res.json({ bots });
|
|
267
|
-
}
|
|
268
|
-
catch (error) {
|
|
269
|
-
req.logger.error('Failed to list bots', { error });
|
|
270
|
-
res.status(500).json({ error: 'Failed to list bots' });
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
// POST /api/bots/:id/enable - Enable a bot
|
|
274
|
-
this.app.post('/api/bots/:id/enable', async (req, res) => {
|
|
275
|
-
const { id } = req.params;
|
|
276
|
-
req.logger.info('Enable bot requested', { botId: id });
|
|
277
|
-
try {
|
|
278
|
-
const { AVAILABLE_BOTS, setBotEnabled } = await Promise.resolve().then(() => __importStar(require('./mcp/tools/bot-config')));
|
|
279
|
-
const bot = AVAILABLE_BOTS.find(b => b.id === id);
|
|
280
|
-
if (!bot) {
|
|
281
|
-
return res.status(404).json({ error: `Unknown bot: ${id}` });
|
|
252
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
253
|
+
// Check for multi-workspace credentials error - return user-friendly error
|
|
254
|
+
// Use HTTP 200 so the JSON-RPC error reaches the client properly
|
|
255
|
+
if (errorMessage.includes('Multi-workspace credentials detected')) {
|
|
256
|
+
req.logger.warn('Multi-workspace credentials blocked', { apiKey: req.query.apiKey });
|
|
257
|
+
this.sendMcpError(res, req.body?.id || null, -32001, errorMessage, 200 // JSON-RPC errors should use HTTP 200 for proper client handling
|
|
258
|
+
);
|
|
282
259
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
catch (error) {
|
|
287
|
-
req.logger.error('Failed to enable bot', { botId: id, error });
|
|
288
|
-
res.status(500).json({ error: 'Failed to enable bot' });
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
// POST /api/bots/:id/disable - Disable a bot
|
|
292
|
-
this.app.post('/api/bots/:id/disable', async (req, res) => {
|
|
293
|
-
const { id } = req.params;
|
|
294
|
-
req.logger.info('Disable bot requested', { botId: id });
|
|
295
|
-
try {
|
|
296
|
-
const { AVAILABLE_BOTS, setBotEnabled } = await Promise.resolve().then(() => __importStar(require('./mcp/tools/bot-config')));
|
|
297
|
-
const bot = AVAILABLE_BOTS.find(b => b.id === id);
|
|
298
|
-
if (!bot) {
|
|
299
|
-
return res.status(404).json({ error: `Unknown bot: ${id}` });
|
|
260
|
+
else {
|
|
261
|
+
req.logger.error('MCP handler error', error, { apiKey: req.query.apiKey });
|
|
262
|
+
this.sendMcpError(res, req.body?.id || null, -32000, `Server error: ${errorMessage}`, 500);
|
|
300
263
|
}
|
|
301
|
-
setBotEnabled(id, false);
|
|
302
|
-
res.json({ success: true, botId: id, enabled: false });
|
|
303
|
-
}
|
|
304
|
-
catch (error) {
|
|
305
|
-
req.logger.error('Failed to disable bot', { botId: id, error });
|
|
306
|
-
res.status(500).json({ error: 'Failed to disable bot' });
|
|
307
264
|
}
|
|
308
265
|
});
|
|
309
|
-
//
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
266
|
+
// ===== Bot Configuration API (only when MCP_CLIENT_ENABLED=true) =====
|
|
267
|
+
if (config_1.environment.MCP_CLIENT_ENABLED) {
|
|
268
|
+
// GET /api/bots - List all bots and their status
|
|
269
|
+
this.app.get('/api/bots', async (req, res) => {
|
|
270
|
+
req.logger.debug('List bots requested');
|
|
271
|
+
try {
|
|
272
|
+
const { AVAILABLE_BOTS, getBotState } = await Promise.resolve().then(() => __importStar(require('./bot-config')));
|
|
273
|
+
const state = getBotState();
|
|
274
|
+
const bots = AVAILABLE_BOTS.map(bot => ({
|
|
275
|
+
...bot,
|
|
276
|
+
enabled: state[bot.id] || false
|
|
277
|
+
}));
|
|
278
|
+
res.json({ bots });
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
req.logger.error('Failed to list bots', { error });
|
|
282
|
+
res.status(500).json({ error: 'Failed to list bots' });
|
|
318
283
|
}
|
|
319
|
-
const currentState = getBotState();
|
|
320
|
-
const newState = !currentState[id];
|
|
321
|
-
setBotEnabled(id, newState);
|
|
322
|
-
res.json({ success: true, botId: id, enabled: newState });
|
|
323
|
-
}
|
|
324
|
-
catch (error) {
|
|
325
|
-
req.logger.error('Failed to toggle bot', { botId: id, error });
|
|
326
|
-
res.status(500).json({ error: 'Failed to toggle bot' });
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
// ===== Bot Config Webhook API =====
|
|
330
|
-
// Get secure webhook path (auto-generated token)
|
|
331
|
-
const webhookPath = (0, webhook_handler_1.getWebhookPath)();
|
|
332
|
-
// POST /webhook/{token} - Receives updates from Hailer workflow webhooks
|
|
333
|
-
this.app.post(webhookPath, (req, res) => {
|
|
334
|
-
req.logger.info('Bot config webhook received', {
|
|
335
|
-
activityId: req.body?._id,
|
|
336
|
-
activityName: req.body?.name,
|
|
337
|
-
workspaceId: req.body?.cid,
|
|
338
284
|
});
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
285
|
+
// POST /api/bots/:id/enable - Enable a bot
|
|
286
|
+
this.app.post('/api/bots/:id/enable', async (req, res) => {
|
|
287
|
+
const { id } = req.params;
|
|
288
|
+
req.logger.info('Enable bot requested', { botId: id });
|
|
289
|
+
try {
|
|
290
|
+
const { AVAILABLE_BOTS, setBotEnabled } = await Promise.resolve().then(() => __importStar(require('./bot-config')));
|
|
291
|
+
const bot = AVAILABLE_BOTS.find(b => b.id === id);
|
|
292
|
+
if (!bot) {
|
|
293
|
+
return res.status(404).json({ error: `Unknown bot: ${id}` });
|
|
294
|
+
}
|
|
295
|
+
setBotEnabled(id, true);
|
|
296
|
+
res.json({ success: true, botId: id, enabled: true });
|
|
348
297
|
}
|
|
349
|
-
|
|
350
|
-
req.logger.
|
|
351
|
-
res.status(
|
|
298
|
+
catch (error) {
|
|
299
|
+
req.logger.error('Failed to enable bot', { botId: id, error });
|
|
300
|
+
res.status(500).json({ error: 'Failed to enable bot' });
|
|
352
301
|
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
302
|
+
});
|
|
303
|
+
// POST /api/bots/:id/disable - Disable a bot
|
|
304
|
+
this.app.post('/api/bots/:id/disable', async (req, res) => {
|
|
305
|
+
const { id } = req.params;
|
|
306
|
+
req.logger.info('Disable bot requested', { botId: id });
|
|
307
|
+
try {
|
|
308
|
+
const { AVAILABLE_BOTS, setBotEnabled } = await Promise.resolve().then(() => __importStar(require('./bot-config')));
|
|
309
|
+
const bot = AVAILABLE_BOTS.find(b => b.id === id);
|
|
310
|
+
if (!bot) {
|
|
311
|
+
return res.status(404).json({ error: `Unknown bot: ${id}` });
|
|
312
|
+
}
|
|
313
|
+
setBotEnabled(id, false);
|
|
314
|
+
res.json({ success: true, botId: id, enabled: false });
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
req.logger.error('Failed to disable bot', { botId: id, error });
|
|
318
|
+
res.status(500).json({ error: 'Failed to disable bot' });
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
// POST /api/bots/:id/toggle - Toggle a bot
|
|
322
|
+
this.app.post('/api/bots/:id/toggle', async (req, res) => {
|
|
323
|
+
const { id } = req.params;
|
|
324
|
+
req.logger.info('Toggle bot requested', { botId: id });
|
|
325
|
+
try {
|
|
326
|
+
const { AVAILABLE_BOTS, getBotState, setBotEnabled } = await Promise.resolve().then(() => __importStar(require('./bot-config')));
|
|
327
|
+
const bot = AVAILABLE_BOTS.find(b => b.id === id);
|
|
328
|
+
if (!bot) {
|
|
329
|
+
return res.status(404).json({ error: `Unknown bot: ${id}` });
|
|
330
|
+
}
|
|
331
|
+
const currentState = getBotState();
|
|
332
|
+
const newState = !currentState[id];
|
|
333
|
+
setBotEnabled(id, newState);
|
|
334
|
+
res.json({ success: true, botId: id, enabled: newState });
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
req.logger.error('Failed to toggle bot', { botId: id, error });
|
|
338
|
+
res.status(500).json({ error: 'Failed to toggle bot' });
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
// ===== Bot Config Webhook API =====
|
|
342
|
+
// Get secure webhook path (auto-generated token) - null if disabled
|
|
343
|
+
const webhookPath = (0, webhook_handler_1.getWebhookPath)();
|
|
344
|
+
if (webhookPath) {
|
|
345
|
+
// POST /webhook/{token} - Receives updates from Hailer workflow webhooks
|
|
346
|
+
this.app.post(webhookPath, (req, res) => {
|
|
347
|
+
req.logger.info('Bot config webhook received', {
|
|
348
|
+
activityId: req.body?._id,
|
|
349
|
+
activityName: req.body?.name,
|
|
350
|
+
workspaceId: req.body?.cid,
|
|
351
|
+
});
|
|
352
|
+
try {
|
|
353
|
+
const result = (0, webhook_handler_1.handleBotConfigWebhook)(req.body);
|
|
354
|
+
if (result.success) {
|
|
355
|
+
req.logger.info('Bot config updated via webhook', {
|
|
356
|
+
action: result.action,
|
|
357
|
+
workspaceId: result.workspaceId,
|
|
358
|
+
botType: result.botType,
|
|
359
|
+
});
|
|
360
|
+
res.status(200).json(result);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
req.logger.warn('Bot config webhook failed', { error: result.error });
|
|
364
|
+
res.status(400).json(result);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
req.logger.error('Bot config webhook error', { error });
|
|
369
|
+
res.status(500).json({
|
|
370
|
+
success: false,
|
|
371
|
+
error: error instanceof Error ? error.message : 'Internal error',
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
// GET /webhook/{token}/status - Status endpoint to see all workspace configs
|
|
376
|
+
this.app.get(`${webhookPath}/status`, (_req, res) => {
|
|
377
|
+
const configs = (0, webhook_handler_1.listWorkspaceConfigs)();
|
|
378
|
+
res.json({
|
|
379
|
+
timestamp: new Date().toISOString(),
|
|
380
|
+
workspaceCount: configs.length,
|
|
381
|
+
workspaces: configs.map((c) => ({
|
|
382
|
+
workspaceId: c.workspaceId,
|
|
383
|
+
workspaceName: c.workspaceName,
|
|
384
|
+
hasOrchestrator: !!c.orchestrator,
|
|
385
|
+
specialistCount: c.specialists.length,
|
|
386
|
+
enabledSpecialists: c.specialists.filter((s) => s.enabled).length,
|
|
387
|
+
lastSynced: c.lastSynced,
|
|
388
|
+
})),
|
|
389
|
+
});
|
|
359
390
|
});
|
|
360
391
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
hasOrchestrator: !!c.orchestrator,
|
|
372
|
-
specialistCount: c.specialists.length,
|
|
373
|
-
enabledSpecialists: c.specialists.filter((s) => s.enabled).length,
|
|
374
|
-
lastSynced: c.lastSynced,
|
|
375
|
-
})),
|
|
392
|
+
else {
|
|
393
|
+
this.logger.info('Webhook endpoint disabled (no WEBHOOK_TOKEN)');
|
|
394
|
+
}
|
|
395
|
+
this.logger.debug('Routes configured', {
|
|
396
|
+
routes: [
|
|
397
|
+
'/health',
|
|
398
|
+
'/daemon/status',
|
|
399
|
+
'/api/mcp',
|
|
400
|
+
'/api/bots'
|
|
401
|
+
]
|
|
376
402
|
});
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
this.logger.debug('Routes configured', {
|
|
406
|
+
routes: [
|
|
407
|
+
'/health',
|
|
408
|
+
'/daemon/status',
|
|
409
|
+
'/api/mcp'
|
|
410
|
+
]
|
|
411
|
+
});
|
|
412
|
+
}
|
|
386
413
|
}
|
|
387
414
|
/**
|
|
388
415
|
* Check if agent has access to a specific tool
|