@hailer/mcp 0.1.17 → 0.2.2

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 (200) hide show
  1. package/dist/app.js +27 -20
  2. package/dist/core.d.ts +33 -9
  3. package/dist/core.js +279 -147
  4. package/dist/mcp/UserContextCache.js +18 -0
  5. package/dist/mcp/hailer-clients.d.ts +9 -1
  6. package/dist/mcp/hailer-clients.js +13 -3
  7. package/dist/mcp/signal-handler.js +1 -1
  8. package/dist/mcp/tool-registry.d.ts +3 -1
  9. package/dist/mcp/tool-registry.js +4 -1
  10. package/dist/mcp/tools/activity.js +43 -34
  11. package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
  12. package/dist/mcp/tools/bot-config/constants.js +94 -0
  13. package/dist/mcp/tools/{bot-config.d.ts → bot-config/core.d.ts} +6 -6
  14. package/dist/mcp/tools/{bot-config.js → bot-config/core.js} +15 -15
  15. package/dist/mcp/tools/bot-config/index.d.ts +10 -0
  16. package/dist/mcp/tools/bot-config/index.js +59 -0
  17. package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
  18. package/dist/mcp/tools/bot-config/tools.js +15 -0
  19. package/dist/mcp/tools/bot-config/types.d.ts +50 -0
  20. package/dist/mcp/tools/bot-config/types.js +6 -0
  21. package/dist/mcp/tools/bug-fixer-tools.d.ts +21 -0
  22. package/dist/mcp/tools/{giuseppe-tools.js → bug-fixer-tools.js} +61 -61
  23. package/dist/mcp/tools/user.js +10 -29
  24. package/dist/mcp/tools/workflow.js +36 -2
  25. package/dist/mcp/utils/data-transformers.d.ts +0 -8
  26. package/dist/mcp/utils/data-transformers.js +0 -28
  27. package/dist/mcp/utils/index.d.ts +4 -1
  28. package/dist/mcp/utils/index.js +17 -3
  29. package/dist/mcp/utils/pagination.d.ts +40 -0
  30. package/dist/mcp/utils/pagination.js +55 -0
  31. package/dist/mcp/utils/response-builder.d.ts +53 -0
  32. package/dist/mcp/utils/response-builder.js +110 -0
  33. package/dist/mcp/utils/tool-helpers.d.ts +0 -8
  34. package/dist/mcp/utils/tool-helpers.js +0 -24
  35. package/dist/mcp/utils/types.d.ts +1 -33
  36. package/dist/mcp-server.d.ts +2 -2
  37. package/dist/mcp-server.js +161 -139
  38. package/package.json +1 -1
  39. package/REFACTOR_STATUS.md +0 -127
  40. package/dist/agents/bot-manager.d.ts +0 -48
  41. package/dist/agents/bot-manager.js +0 -254
  42. package/dist/agents/factory.d.ts +0 -150
  43. package/dist/agents/factory.js +0 -650
  44. package/dist/agents/giuseppe/ai.d.ts +0 -83
  45. package/dist/agents/giuseppe/ai.js +0 -466
  46. package/dist/agents/giuseppe/bot.d.ts +0 -110
  47. package/dist/agents/giuseppe/bot.js +0 -780
  48. package/dist/agents/giuseppe/config.d.ts +0 -25
  49. package/dist/agents/giuseppe/config.js +0 -227
  50. package/dist/agents/giuseppe/files.d.ts +0 -52
  51. package/dist/agents/giuseppe/files.js +0 -338
  52. package/dist/agents/giuseppe/git.d.ts +0 -48
  53. package/dist/agents/giuseppe/git.js +0 -298
  54. package/dist/agents/giuseppe/index.d.ts +0 -97
  55. package/dist/agents/giuseppe/index.js +0 -258
  56. package/dist/agents/giuseppe/lsp.d.ts +0 -113
  57. package/dist/agents/giuseppe/lsp.js +0 -485
  58. package/dist/agents/giuseppe/monitor.d.ts +0 -118
  59. package/dist/agents/giuseppe/monitor.js +0 -621
  60. package/dist/agents/giuseppe/prompt.d.ts +0 -5
  61. package/dist/agents/giuseppe/prompt.js +0 -94
  62. package/dist/agents/giuseppe/registries/pending-classification.d.ts +0 -28
  63. package/dist/agents/giuseppe/registries/pending-classification.js +0 -50
  64. package/dist/agents/giuseppe/registries/pending-fix.d.ts +0 -30
  65. package/dist/agents/giuseppe/registries/pending-fix.js +0 -42
  66. package/dist/agents/giuseppe/registries/pending.d.ts +0 -27
  67. package/dist/agents/giuseppe/registries/pending.js +0 -49
  68. package/dist/agents/giuseppe/specialist.d.ts +0 -47
  69. package/dist/agents/giuseppe/specialist.js +0 -237
  70. package/dist/agents/giuseppe/types.d.ts +0 -123
  71. package/dist/agents/giuseppe/types.js +0 -9
  72. package/dist/agents/hailer-expert/index.d.ts +0 -8
  73. package/dist/agents/hailer-expert/index.js +0 -14
  74. package/dist/agents/hal/daemon.d.ts +0 -142
  75. package/dist/agents/hal/daemon.js +0 -1103
  76. package/dist/agents/hal/definitions.d.ts +0 -55
  77. package/dist/agents/hal/definitions.js +0 -263
  78. package/dist/agents/hal/index.d.ts +0 -3
  79. package/dist/agents/hal/index.js +0 -8
  80. package/dist/agents/index.d.ts +0 -18
  81. package/dist/agents/index.js +0 -48
  82. package/dist/agents/shared/base.d.ts +0 -216
  83. package/dist/agents/shared/base.js +0 -846
  84. package/dist/agents/shared/services/agent-registry.d.ts +0 -107
  85. package/dist/agents/shared/services/agent-registry.js +0 -629
  86. package/dist/agents/shared/services/conversation-manager.d.ts +0 -50
  87. package/dist/agents/shared/services/conversation-manager.js +0 -136
  88. package/dist/agents/shared/services/mcp-client.d.ts +0 -56
  89. package/dist/agents/shared/services/mcp-client.js +0 -124
  90. package/dist/agents/shared/services/message-classifier.d.ts +0 -37
  91. package/dist/agents/shared/services/message-classifier.js +0 -187
  92. package/dist/agents/shared/services/message-formatter.d.ts +0 -89
  93. package/dist/agents/shared/services/message-formatter.js +0 -371
  94. package/dist/agents/shared/services/session-logger.d.ts +0 -106
  95. package/dist/agents/shared/services/session-logger.js +0 -446
  96. package/dist/agents/shared/services/tool-executor.d.ts +0 -41
  97. package/dist/agents/shared/services/tool-executor.js +0 -169
  98. package/dist/agents/shared/services/workspace-schema-cache.d.ts +0 -125
  99. package/dist/agents/shared/services/workspace-schema-cache.js +0 -578
  100. package/dist/agents/shared/specialist.d.ts +0 -91
  101. package/dist/agents/shared/specialist.js +0 -399
  102. package/dist/agents/shared/tool-schema-loader.d.ts +0 -62
  103. package/dist/agents/shared/tool-schema-loader.js +0 -232
  104. package/dist/agents/shared/types.d.ts +0 -327
  105. package/dist/agents/shared/types.js +0 -121
  106. package/dist/client/agents/base.d.ts +0 -207
  107. package/dist/client/agents/base.js +0 -744
  108. package/dist/client/agents/definitions.d.ts +0 -53
  109. package/dist/client/agents/definitions.js +0 -263
  110. package/dist/client/agents/orchestrator.d.ts +0 -141
  111. package/dist/client/agents/orchestrator.js +0 -1062
  112. package/dist/client/agents/specialist.d.ts +0 -86
  113. package/dist/client/agents/specialist.js +0 -340
  114. package/dist/client/bot-entrypoint.d.ts +0 -7
  115. package/dist/client/bot-entrypoint.js +0 -103
  116. package/dist/client/bot-manager.d.ts +0 -44
  117. package/dist/client/bot-manager.js +0 -173
  118. package/dist/client/bot-runner.d.ts +0 -35
  119. package/dist/client/bot-runner.js +0 -188
  120. package/dist/client/chat-agent-daemon.d.ts +0 -464
  121. package/dist/client/chat-agent-daemon.js +0 -1774
  122. package/dist/client/daemon-factory.d.ts +0 -106
  123. package/dist/client/daemon-factory.js +0 -301
  124. package/dist/client/factory.d.ts +0 -111
  125. package/dist/client/factory.js +0 -314
  126. package/dist/client/index.d.ts +0 -17
  127. package/dist/client/index.js +0 -38
  128. package/dist/client/multi-bot-manager.d.ts +0 -42
  129. package/dist/client/multi-bot-manager.js +0 -161
  130. package/dist/client/orchestrator-daemon.d.ts +0 -87
  131. package/dist/client/orchestrator-daemon.js +0 -444
  132. package/dist/client/server.d.ts +0 -8
  133. package/dist/client/server.js +0 -251
  134. package/dist/client/services/agent-registry.d.ts +0 -108
  135. package/dist/client/services/agent-registry.js +0 -630
  136. package/dist/client/services/conversation-manager.d.ts +0 -50
  137. package/dist/client/services/conversation-manager.js +0 -136
  138. package/dist/client/services/mcp-client.d.ts +0 -48
  139. package/dist/client/services/mcp-client.js +0 -105
  140. package/dist/client/services/message-classifier.d.ts +0 -37
  141. package/dist/client/services/message-classifier.js +0 -187
  142. package/dist/client/services/message-formatter.d.ts +0 -84
  143. package/dist/client/services/message-formatter.js +0 -353
  144. package/dist/client/services/session-logger.d.ts +0 -106
  145. package/dist/client/services/session-logger.js +0 -446
  146. package/dist/client/services/tool-executor.d.ts +0 -41
  147. package/dist/client/services/tool-executor.js +0 -169
  148. package/dist/client/services/workspace-schema-cache.d.ts +0 -149
  149. package/dist/client/services/workspace-schema-cache.js +0 -732
  150. package/dist/client/specialist-daemon.d.ts +0 -77
  151. package/dist/client/specialist-daemon.js +0 -197
  152. package/dist/client/specialists.d.ts +0 -53
  153. package/dist/client/specialists.js +0 -178
  154. package/dist/client/tool-schema-loader.d.ts +0 -62
  155. package/dist/client/tool-schema-loader.js +0 -232
  156. package/dist/client/types.d.ts +0 -327
  157. package/dist/client/types.js +0 -121
  158. package/dist/commands/seed-config.d.ts +0 -9
  159. package/dist/commands/seed-config.js +0 -372
  160. package/dist/lib/context-manager.d.ts +0 -111
  161. package/dist/lib/context-manager.js +0 -431
  162. package/dist/lib/prompt-length-manager.d.ts +0 -81
  163. package/dist/lib/prompt-length-manager.js +0 -457
  164. package/dist/mcp/tools/giuseppe-tools.d.ts +0 -21
  165. package/dist/modules/bug-reports/bug-config.d.ts +0 -25
  166. package/dist/modules/bug-reports/bug-config.js +0 -187
  167. package/dist/modules/bug-reports/bug-monitor.d.ts +0 -108
  168. package/dist/modules/bug-reports/bug-monitor.js +0 -510
  169. package/dist/modules/bug-reports/giuseppe-agent.d.ts +0 -58
  170. package/dist/modules/bug-reports/giuseppe-agent.js +0 -467
  171. package/dist/modules/bug-reports/giuseppe-ai.d.ts +0 -83
  172. package/dist/modules/bug-reports/giuseppe-ai.js +0 -466
  173. package/dist/modules/bug-reports/giuseppe-bot.d.ts +0 -110
  174. package/dist/modules/bug-reports/giuseppe-bot.js +0 -804
  175. package/dist/modules/bug-reports/giuseppe-daemon.d.ts +0 -80
  176. package/dist/modules/bug-reports/giuseppe-daemon.js +0 -617
  177. package/dist/modules/bug-reports/giuseppe-files.d.ts +0 -64
  178. package/dist/modules/bug-reports/giuseppe-files.js +0 -375
  179. package/dist/modules/bug-reports/giuseppe-git.d.ts +0 -48
  180. package/dist/modules/bug-reports/giuseppe-git.js +0 -298
  181. package/dist/modules/bug-reports/giuseppe-lsp.d.ts +0 -113
  182. package/dist/modules/bug-reports/giuseppe-lsp.js +0 -485
  183. package/dist/modules/bug-reports/giuseppe-prompt.d.ts +0 -5
  184. package/dist/modules/bug-reports/giuseppe-prompt.js +0 -94
  185. package/dist/modules/bug-reports/index.d.ts +0 -77
  186. package/dist/modules/bug-reports/index.js +0 -215
  187. package/dist/modules/bug-reports/pending-classification-registry.d.ts +0 -28
  188. package/dist/modules/bug-reports/pending-classification-registry.js +0 -50
  189. package/dist/modules/bug-reports/pending-fix-registry.d.ts +0 -30
  190. package/dist/modules/bug-reports/pending-fix-registry.js +0 -42
  191. package/dist/modules/bug-reports/pending-registry.d.ts +0 -27
  192. package/dist/modules/bug-reports/pending-registry.js +0 -49
  193. package/dist/modules/bug-reports/types.d.ts +0 -123
  194. package/dist/modules/bug-reports/types.js +0 -9
  195. package/dist/routes/agents.d.ts +0 -44
  196. package/dist/routes/agents.js +0 -311
  197. package/dist/services/agent-credential-store.d.ts +0 -73
  198. package/dist/services/agent-credential-store.js +0 -212
  199. package/dist/services/bug-monitor.d.ts +0 -23
  200. 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;
@@ -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
- }> | null;
22
+ }>>;
23
23
  }
24
24
  export declare class MCPServerService {
25
25
  private app;
@@ -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 NUCLEAR tools blocking if NOT explicitly enabled
170
- if (!config_1.environment.ENABLE_NUCLEAR_TOOLS) {
171
- if (!filterConfig) {
172
- // No filter yet - create one excluding NUCLEAR
173
- filterConfig = {
174
- allowedGroups: [tool_registry_1.ToolGroup.READ, tool_registry_1.ToolGroup.WRITE, tool_registry_1.ToolGroup.PLAYGROUND]
175
- };
176
- }
177
- else if (filterConfig.allowedGroups) {
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
- req.logger.debug('NUCLEAR tools enabled by environment variable');
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,146 +249,167 @@ class MCPServerService {
248
249
  res.end();
249
250
  }
250
251
  catch (error) {
251
- req.logger.error('MCP handler error', error, { apiKey: req.query.apiKey });
252
- this.sendMcpError(res, req.body?.id || null, -32000, `Server error: ${error instanceof Error ? error.message : String(error)}`, 500);
253
- }
254
- });
255
- // ===== Bot Configuration API =====
256
- // GET /api/bots - List all bots and their status
257
- this.app.get('/api/bots', async (req, res) => {
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
- setBotEnabled(id, true);
284
- res.json({ success: true, botId: id, enabled: true });
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
- // POST /api/bots/:id/toggle - Toggle a bot
310
- this.app.post('/api/bots/:id/toggle', async (req, res) => {
311
- const { id } = req.params;
312
- req.logger.info('Toggle bot requested', { botId: id });
313
- try {
314
- const { AVAILABLE_BOTS, getBotState, setBotEnabled } = await Promise.resolve().then(() => __importStar(require('./mcp/tools/bot-config')));
315
- const bot = AVAILABLE_BOTS.find(b => b.id === id);
316
- if (!bot) {
317
- return res.status(404).json({ error: `Unknown bot: ${id}` });
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 });
318
279
  }
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) - null if disabled
331
- const webhookPath = (0, webhook_handler_1.getWebhookPath)();
332
- if (webhookPath) {
333
- // POST /webhook/{token} - Receives updates from Hailer workflow webhooks
334
- this.app.post(webhookPath, (req, res) => {
335
- req.logger.info('Bot config webhook received', {
336
- activityId: req.body?._id,
337
- activityName: req.body?.name,
338
- workspaceId: req.body?.cid,
339
- });
280
+ catch (error) {
281
+ req.logger.error('Failed to list bots', { error });
282
+ res.status(500).json({ error: 'Failed to list bots' });
283
+ }
284
+ });
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 });
340
289
  try {
341
- const result = (0, webhook_handler_1.handleBotConfigWebhook)(req.body);
342
- if (result.success) {
343
- req.logger.info('Bot config updated via webhook', {
344
- action: result.action,
345
- workspaceId: result.workspaceId,
346
- botType: result.botType,
347
- });
348
- res.status(200).json(result);
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}` });
349
294
  }
350
- else {
351
- req.logger.warn('Bot config webhook failed', { error: result.error });
352
- res.status(400).json(result);
295
+ setBotEnabled(id, true);
296
+ res.json({ success: true, botId: id, enabled: true });
297
+ }
298
+ catch (error) {
299
+ req.logger.error('Failed to enable bot', { botId: id, error });
300
+ res.status(500).json({ error: 'Failed to enable bot' });
301
+ }
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}` });
353
312
  }
313
+ setBotEnabled(id, false);
314
+ res.json({ success: true, botId: id, enabled: false });
354
315
  }
355
316
  catch (error) {
356
- req.logger.error('Bot config webhook error', { error });
357
- res.status(500).json({
358
- success: false,
359
- error: error instanceof Error ? error.message : 'Internal error',
360
- });
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' });
361
339
  }
362
340
  });
363
- // GET /webhook/{token}/status - Status endpoint to see all workspace configs
364
- this.app.get(`${webhookPath}/status`, (_req, res) => {
365
- const configs = (0, webhook_handler_1.listWorkspaceConfigs)();
366
- res.json({
367
- timestamp: new Date().toISOString(),
368
- workspaceCount: configs.length,
369
- workspaces: configs.map((c) => ({
370
- workspaceId: c.workspaceId,
371
- workspaceName: c.workspaceName,
372
- hasOrchestrator: !!c.orchestrator,
373
- specialistCount: c.specialists.length,
374
- enabledSpecialists: c.specialists.filter((s) => s.enabled).length,
375
- lastSynced: c.lastSynced,
376
- })),
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
+ });
377
390
  });
391
+ }
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
+ ]
378
402
  });
379
403
  }
380
404
  else {
381
- this.logger.info('Webhook endpoint disabled (no WEBHOOK_TOKEN)');
405
+ this.logger.debug('Routes configured', {
406
+ routes: [
407
+ '/health',
408
+ '/daemon/status',
409
+ '/api/mcp'
410
+ ]
411
+ });
382
412
  }
383
- this.logger.debug('Routes configured', {
384
- routes: [
385
- '/health',
386
- '/daemon/status',
387
- '/api/mcp',
388
- '/api/bots'
389
- ]
390
- });
391
413
  }
392
414
  /**
393
415
  * Check if agent has access to a specific tool
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hailer/mcp",
3
- "version": "0.1.17",
3
+ "version": "0.2.2",
4
4
  "config": {
5
5
  "docker": {
6
6
  "registry": "registry.gitlab.com/hailer-repos/hailer-mcp"