@hailer/mcp 0.2.7 → 1.0.20

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 (39) hide show
  1. package/.claude/skills/client-bot-architecture/skill.md +340 -0
  2. package/.claude/skills/publish-hailer-app/SKILL.md +11 -0
  3. package/dist/app.d.ts +1 -1
  4. package/dist/app.js +116 -84
  5. package/dist/bot/chat-bot.d.ts +31 -0
  6. package/dist/bot/chat-bot.js +356 -0
  7. package/dist/cli.js +0 -0
  8. package/dist/config.d.ts +15 -2
  9. package/dist/config.js +53 -3
  10. package/dist/lib/logger.js +11 -11
  11. package/dist/mcp/hailer-clients.js +12 -11
  12. package/dist/mcp/tool-registry.d.ts +4 -0
  13. package/dist/mcp/tool-registry.js +78 -1
  14. package/dist/mcp/tools/activity.js +47 -0
  15. package/dist/mcp/tools/discussion.js +44 -1
  16. package/dist/mcp/tools/metrics.d.ts +13 -0
  17. package/dist/mcp/tools/metrics.js +546 -0
  18. package/dist/mcp/tools/user.d.ts +1 -0
  19. package/dist/mcp/tools/user.js +94 -1
  20. package/dist/mcp/tools/workflow.js +109 -40
  21. package/dist/mcp/webhook-handler.js +7 -4
  22. package/dist/mcp-server.js +22 -6
  23. package/dist/stdio-server.d.ts +14 -0
  24. package/dist/stdio-server.js +101 -0
  25. package/package.json +6 -6
  26. package/scripts/test-hal-tools.ts +154 -0
  27. package/test-billing-server.js +136 -0
  28. package/dist/lib/discussion-lock.d.ts +0 -42
  29. package/dist/lib/discussion-lock.js +0 -110
  30. package/dist/mcp/tools/bot-config/constants.d.ts +0 -23
  31. package/dist/mcp/tools/bot-config/constants.js +0 -94
  32. package/dist/mcp/tools/bot-config/core.d.ts +0 -253
  33. package/dist/mcp/tools/bot-config/core.js +0 -2456
  34. package/dist/mcp/tools/bot-config/index.d.ts +0 -10
  35. package/dist/mcp/tools/bot-config/index.js +0 -59
  36. package/dist/mcp/tools/bot-config/tools.d.ts +0 -7
  37. package/dist/mcp/tools/bot-config/tools.js +0 -15
  38. package/dist/mcp/tools/bot-config/types.d.ts +0 -50
  39. package/dist/mcp/tools/bot-config/types.js +0 -6
@@ -0,0 +1,340 @@
1
+ # Client Bot Architecture Reference
2
+
3
+ Load this skill when working on the client bot system (bot-manager, daemon, token billing, MCP tool execution).
4
+
5
+ **Full Documentation:** See `docs/client-bots/` for comprehensive guides:
6
+ - [index.md](../../../docs/client-bots/index.md) - Overview
7
+ - [architecture.md](../../../docs/client-bots/architecture.md) - Data flows, initialization
8
+ - [services.md](../../../docs/client-bots/services.md) - All 11 services
9
+ - [token-costs.md](../../../docs/client-bots/token-costs.md) - AI + Hailer costs
10
+ - [memory-context.md](../../../docs/client-bots/memory-context.md) - 3-layer context
11
+ - [configuration.md](../../../docs/client-bots/configuration.md) - Env vars, config files
12
+ - [edge-cases.md](../../../docs/client-bots/edge-cases.md) - Race conditions, gotchas
13
+
14
+ ---
15
+
16
+ ## Architecture Overview
17
+
18
+ The client bot system is a multi-bot orchestration platform for Hailer workspaces:
19
+ - **HAL Orchestrator** - Main bot that monitors chats, classifies messages, coordinates specialists
20
+ - **Specialist Bots** - Focused bots for specific tasks (invoked by HAL)
21
+ - **Bot Manager** - Manages multiple bot connections and credentials
22
+ - **Token Billing** - Real-time per-workspace cost tracking
23
+
24
+ ---
25
+
26
+ ## Key Files
27
+
28
+ | File | Purpose |
29
+ |------|---------|
30
+ | `src/agents/bot-manager.ts` | Multi-bot connection pool, credential management |
31
+ | `src/agents/hal/daemon.ts` | HAL orchestrator, message routing, specialist coordination |
32
+ | `src/agents/shared/base.ts` | ChatAgentDaemon base class, core processing loop |
33
+ | `src/agents/shared/services/token-billing.ts` | Per-workspace token burning |
34
+ | `src/bot-config/context.ts` | Per-workspace singleton, Agent Directory discovery |
35
+ | `src/mcp/hailer-clients.ts` | HailerClient pool, signal subscriptions |
36
+ | `src/mcp/tools/activity.ts` | list_activities, create_activity, update_activity |
37
+ | `src/mcp/tools/discussion.ts` | join_discussion, fetch_messages, add_message |
38
+
39
+ ---
40
+
41
+ ## Message Processing Flow
42
+
43
+ ```
44
+ User message in workspace
45
+
46
+ [Signal: messenger.new] → HailerClientManager
47
+
48
+ ChatAgentDaemon.handleSignal()
49
+
50
+ MessageClassifier.extractIncomingMessage()
51
+ → Priority: HIGH (DM, @mention, reply) or NORMAL
52
+
53
+ processMessage(IncomingMessage)
54
+ → Check token balance (first message)
55
+ → Load memory from Session Log (cold start)
56
+ → Build per-discussion conversation
57
+
58
+ Call LLM with conversation + tools
59
+
60
+ handleLlmResponse(response)
61
+ ├─ Tool calls? → executeToolsAndContinue()
62
+ │ ├─ Execute via MCP
63
+ │ ├─ Add results to conversation
64
+ │ └─ Call LLM again (loop)
65
+ ├─ Specialist invite? → inviteSpecialist()
66
+ ├─ IGNORE? → Remove from context
67
+ └─ RESPOND? → postResponse()
68
+ └─ Resolve tags (@mentions, #activities)
69
+ └─ Send via messenger.send
70
+ └─ Burn tokens (fire-and-forget)
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Tool Execution Pipeline
76
+
77
+ ```typescript
78
+ // 1. LLM returns tool_use blocks
79
+ const toolUseBlocks = response.content.filter(b => b.type === "tool_use");
80
+
81
+ // 2. Preprocess each tool input (inject context)
82
+ preprocessToolInput(toolName, input) {
83
+ // Inject discussionId, sourceActivityId, etc.
84
+ return modified_input;
85
+ }
86
+
87
+ // 3. Execute via MCP service
88
+ const toolResults = await toolExecutor.executeTools(toolUseBlocks, {
89
+ session,
90
+ preprocessToolInput
91
+ });
92
+
93
+ // 4. Add results to conversation
94
+ conversation.push({ role: "user", content: toolResults });
95
+
96
+ // 5. Call LLM again with results
97
+ // 6. Track tokens per response
98
+ ```
99
+
100
+ **Cost Concern:** Each tool response (workflow schemas, activity lists) adds input tokens at model rate.
101
+
102
+ ---
103
+
104
+ ## Token Billing
105
+
106
+ **Pricing (Claude Haiku 4.5):**
107
+ ```typescript
108
+ const HAIKU_PRICING = {
109
+ inputPerMillion: 1.00,
110
+ outputPerMillion: 5.00,
111
+ cacheWritePerMillion: 1.25, // 25% more than input
112
+ cacheReadPerMillion: 0.10, // 90% discount
113
+ };
114
+ ```
115
+
116
+ **Normalized Token Formula:**
117
+ ```
118
+ normalizedTokens =
119
+ inputTokens * 0.20 +
120
+ outputTokens * 1.0 +
121
+ cacheCreationTokens * 0.25 +
122
+ cacheReadTokens * 0.02
123
+ ```
124
+
125
+ **API Calls:**
126
+ - `v3.mcp.getTokenBalance(workspaceId)` - Balance check before session
127
+ - `v3.mcp.deductTokens({...})` - Fire-and-forget token burn
128
+
129
+ **Graceful Degradation:**
130
+ - Balance check returns "OK" if service unavailable
131
+ - Token burn is async, doesn't block response
132
+
133
+ **Cost Optimization:**
134
+ Set `DISABLE_SESSION_LOG=true` to save ~1620 tokens per conversation:
135
+ - Skips SESSION_LOG persistence (20 tokens)
136
+ - Uses truncation instead of LLM summarization (~1000 tokens)
137
+ - Skips metadata extraction (~600 tokens)
138
+ - Uses discussion messages for cold start (FREE)
139
+
140
+ ---
141
+
142
+ ## Specialist Coordination
143
+
144
+ **HAL can invoke specialists via XML pattern:**
145
+ ```xml
146
+ <invite specialist="key">handoff context</invite>
147
+ ```
148
+
149
+ **Specialist Registry:**
150
+ ```typescript
151
+ specialists: Map<string, Specialist>
152
+ activeSpecialistsInDiscussion: Map<string, Set<string>>
153
+ ```
154
+
155
+ **Handoff Flow:**
156
+ 1. HAL detects task needs specialist
157
+ 2. Calls `invite_discussion_members` with specialist userId
158
+ 3. Posts handoff message with `[hailerTag|Name](userId)` mention
159
+ 4. Specialist receives notification, joins discussion
160
+
161
+ ---
162
+
163
+ ## Per-Discussion Isolation
164
+
165
+ **Conversation Manager:**
166
+ - LRU cache of 100 most recent discussions
167
+ - Each discussion has independent conversation history
168
+ - Auto-truncates when >50 messages (keeps last 30)
169
+ - Prevents context pollution across chats
170
+
171
+ **Cost Optimization (`DISABLE_SESSION_LOG=true`):**
172
+ - Cold start: Fetches discussion messages (FREE) instead of SESSION_LOG
173
+ - Context overflow: Truncates (0 tokens) instead of LLM summarization (~1000 tokens)
174
+ - Session end: Skips persistence (saves 20 tokens + ~600 metadata extraction)
175
+
176
+ **Session Tracking:**
177
+ ```typescript
178
+ interface ActivitySession {
179
+ discussionId: string;
180
+ activityId: string;
181
+ activityName: string;
182
+ metrics: { inputTokens, outputTokens, cacheTokens, apiCalls };
183
+ conversation: string[]; // ["SenderName: message preview"]
184
+ actions: string[]; // ["Responded", "Executed tool X"]
185
+ }
186
+ ```
187
+
188
+ **Idle Cleanup:**
189
+ - Timer every 30 seconds
190
+ - Sessions inactive 1 hour auto-flushed
191
+ - Flush writes to Session Log workflow
192
+
193
+ ---
194
+
195
+ ## Cross-Discussion Memory
196
+
197
+ **Context Persistence (5 min TTL):**
198
+ ```typescript
199
+ lastKnownActivityId: string | null;
200
+ lastKnownActivityTime: number;
201
+ ```
202
+
203
+ **Used for:**
204
+ - Auto-inject `sourceActivityId` in `join_discussion`
205
+ - "Came from" wormhole links when inviting users
206
+ - Timeout-based expiration
207
+
208
+ ---
209
+
210
+ ## Bot Manager
211
+
212
+ **Connection Pool:**
213
+ ```typescript
214
+ class MultiBotManager {
215
+ botClients: Map<string, BotClient>;
216
+
217
+ initializeBotClient(email, password, apiKey): Promise<string>
218
+ removeBotClient(userId): Promise<void>
219
+ getBotClient(userId): BotClient | undefined
220
+ }
221
+ ```
222
+
223
+ **BotClient Structure:**
224
+ ```typescript
225
+ interface BotClient {
226
+ userId: string;
227
+ firstName: string;
228
+ lastName: string;
229
+ config: BotClientConfig;
230
+ client: HailerClient;
231
+ signalHandler: SignalHandler;
232
+ workspaceCache?: WorkspaceCache;
233
+ }
234
+ ```
235
+
236
+ **Initialization:**
237
+ 1. Load bot configs
238
+ 2. Create HailerClient via API key
239
+ 3. Fetch workspace cache (`v2.core.init`)
240
+ 4. Check Agent Directory for custom display names
241
+ 5. Register signal handlers
242
+
243
+ ---
244
+
245
+ ## Agent Directory Discovery
246
+
247
+ **Schema Discovery:**
248
+ 1. List all workflows
249
+ 2. Find "Agent Directory" workflow
250
+ 3. Extract "Deployed"/"Retired" phases
251
+ 4. Map field keys to field IDs
252
+ 5. Cache for dynamic lookups
253
+
254
+ **BotContext Singleton (per workspace):**
255
+ ```typescript
256
+ getBotContext(workspaceId) → {
257
+ agentDirectoryWorkflowId,
258
+ deployedPhaseId,
259
+ retiredPhaseId,
260
+ fields: { hailerProfile, email, password, botType }
261
+ }
262
+ ```
263
+
264
+ ---
265
+
266
+ ## System Prompt Caching (50% cost reduction)
267
+
268
+ **HAL uses Anthropic prompt caching:**
269
+ - Static content (identity, specialist list template) → `ephemeral` cache
270
+ - Dynamic content (current specialists, pending fixes) → appended fresh
271
+ - Format: `Anthropic.TextBlockParam[]`
272
+
273
+ ---
274
+
275
+ ## Error Handling
276
+
277
+ | Error Type | Handling |
278
+ |------------|----------|
279
+ | Tool execution | Return `is_error: true`, LLM sees and can retry |
280
+ | Message processing | Log, remove from context, silent fail |
281
+ | Billing errors | Graceful degradation, return "OK" |
282
+ | Signal errors | Early dedup, invalid messages cleaned |
283
+
284
+ ---
285
+
286
+ ## Structured Outputs Mode (Token Optimization)
287
+
288
+ **Problem:** Native tool definitions cost ~100K tokens per request (22 tool schemas sent every API call).
289
+
290
+ **Solution:** Use Anthropic's structured outputs beta to replace tool schemas with compact JSON action schema.
291
+
292
+ **Enable:**
293
+ ```bash
294
+ USE_STRUCTURED_OUTPUTS=true npm run daemon
295
+ ```
296
+
297
+ **Key Files:**
298
+ | File | Purpose |
299
+ |------|---------|
300
+ | `src/agents/shared/schemas/action-schema.ts` | Action type definitions, JSON schema |
301
+ | `src/agents/shared/services/structured-output-executor.ts` | Action parsing and execution |
302
+
303
+ **How It Works:**
304
+ 1. Instead of `tools: [...]` array, uses `output_format: { type: "json_schema", schema: {...} }`
305
+ 2. Claude outputs JSON with action type and params
306
+ 3. `StructuredOutputExecutor` parses and executes via existing MCP tools
307
+ 4. Multi-turn loops work the same way
308
+
309
+ **Action Schema:**
310
+ ```typescript
311
+ interface ActionOutput {
312
+ thinking?: string; // Brief reasoning
313
+ action: BotAction; // "respond" | "list_activities" | etc.
314
+ params?: Record<string, unknown>; // Tool-specific params
315
+ response_text?: string; // For "respond" action
316
+ specialist_key?: string; // For "invite_specialist" action
317
+ }
318
+ ```
319
+
320
+ **Savings:**
321
+ - ~100K tokens saved per request
322
+ - At Haiku rates ($0.80/M): ~$0.08 saved per request
323
+ - 1000 requests/day = ~$80/day saved
324
+
325
+ **Trade-offs:**
326
+ - Beta feature (may have edge cases)
327
+ - Grammar compilation on first use (cached for 24h)
328
+ - Slightly different error handling
329
+
330
+ ---
331
+
332
+ ## Key Design Patterns
333
+
334
+ 1. **Per-Discussion Isolation** - Independent conversation per chat
335
+ 2. **Multi-Tenant** - BotContext, schema cache, billing per workspace
336
+ 3. **Signal-Driven** - Listen to `messenger.new`, early dedup
337
+ 4. **Graceful Degradation** - Billing/memory failures don't block
338
+ 5. **Fire-and-Forget Billing** - Async token burn, no blocking
339
+ 6. **Tool Preprocessing** - Inject context before MCP execution
340
+ 7. **Structured Outputs** - Optional token optimization via JSON action schema
@@ -82,12 +82,23 @@ Required structure:
82
82
 
83
83
  ### Step 4: Publish
84
84
 
85
+ **Option 1: Production Only**
85
86
  ```javascript
86
87
  publish_hailer_app({
87
88
  projectDirectory: "/path/to/app"
88
89
  })
89
90
  ```
90
91
 
92
+ **Option 2: Production + Marketplace**
93
+ ```javascript
94
+ publish_hailer_app({
95
+ projectDirectory: "/path/to/app",
96
+ publishToMarket: true
97
+ })
98
+ ```
99
+
100
+ **IMPORTANT:** The `publishToMarket: true` parameter is REQUIRED to publish the app to the Hailer Marketplace. Without it, the app is published only to your production environment.
101
+
91
102
  ### Step 5: Verify
92
103
 
93
104
  ```javascript
package/dist/app.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { Core } from './core';
2
- declare const core: Core;
2
+ declare const core: Core | null;
3
3
  export default core;
4
4
  //# sourceMappingURL=app.d.ts.map
package/dist/app.js CHANGED
@@ -3,7 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("./core");
4
4
  const config_1 = require("./config");
5
5
  const logger_1 = require("./lib/logger");
6
+ const tool_registry_1 = require("./mcp/tool-registry");
7
+ const stdio_server_1 = require("./stdio-server");
6
8
  const logger = (0, logger_1.createLogger)({ component: 'app' });
9
+ // Detect transport mode:
10
+ // - MCP_TRANSPORT=stdio - explicit stdio mode
11
+ // - MCP_TRANSPORT=http - explicit HTTP mode
12
+ // - No TTY on stdin - Claude Desktop spawned process, use stdio
13
+ // - TTY on stdin - manual terminal run, use HTTP
14
+ const transportMode = process.env.MCP_TRANSPORT || (process.stdin.isTTY ? 'http' : 'stdio');
15
+ const isStdioMode = transportMode === 'stdio';
16
+ logger.info('Transport mode detected', {
17
+ mode: transportMode,
18
+ isTTY: process.stdin.isTTY,
19
+ isStdioMode
20
+ });
7
21
  const file_1 = require("./mcp/tools/file");
8
22
  const activity_1 = require("./mcp/tools/activity");
9
23
  const discussion_1 = require("./mcp/tools/discussion");
@@ -13,79 +27,87 @@ const insight_1 = require("./mcp/tools/insight");
13
27
  const app_1 = require("./mcp/tools/app");
14
28
  // Bot config and bug-fixer tools are dynamically imported only when MCP_CLIENT_ENABLED=true
15
29
  // This allows the npm package to work without these modules
16
- const core = new core_1.Core();
30
+ // For stdio mode, create standalone ToolRegistry
31
+ // For HTTP mode, use Core which has its own ToolRegistry
32
+ const toolRegistry = isStdioMode ? new tool_registry_1.ToolRegistry({ enableNuclearTools: config_1.environment.ENABLE_NUCLEAR_TOOLS }) : null;
33
+ const core = isStdioMode ? null : new core_1.Core();
34
+ // Helper to add tool to the appropriate registry
35
+ const addTool = (tool) => {
36
+ if (toolRegistry) {
37
+ toolRegistry.addTool(tool);
38
+ }
39
+ else if (core) {
40
+ core.addTool(tool);
41
+ }
42
+ };
17
43
  logger.info('Registering tools...');
18
44
  logger.info('Nuclear tools status', { enabled: config_1.environment.ENABLE_NUCLEAR_TOOLS });
19
- core.addTool(file_1.uploadFilesTool);
20
- core.addTool(file_1.downloadFileTool);
21
- core.addTool(activity_1.listActivitiesTool);
22
- core.addTool(activity_1.showActivityByIdTool);
23
- core.addTool(activity_1.createActivityTool);
24
- core.addTool(activity_1.updateActivityTool);
25
- // core.addTool(searchActivitiesTool);
26
- // core.addTool(filterActivitiesTool);
27
- // core.addTool(activityToolsGuideTool);
28
- core.addTool(discussion_1.listMyDiscussionsTool);
29
- core.addTool(discussion_1.fetchDiscussionMessagesTool);
30
- core.addTool(discussion_1.fetchPreviousDiscussionMessagesTool);
31
- core.addTool(discussion_1.joinDiscussionTool);
32
- core.addTool(discussion_1.leaveDiscussionTool);
33
- core.addTool(discussion_1.addDiscussionMessageTool);
34
- core.addTool(discussion_1.inviteDiscussionMembersTool);
35
- core.addTool(discussion_1.getActivityFromDiscussionTool);
36
- core.addTool(user_1.searchWorkspaceUsersTool);
37
- // core.addTool(hailerGetInitTool);
38
- // core.addTool(validateUserIdTool);
39
- core.addTool(workflow_1.getWorkflowSchemaTool);
40
- core.addTool(workflow_1.listWorkflowPhasesTool);
41
- core.addTool(workflow_1.listWorkflowsTool);
42
- core.addTool(workflow_1.installWorkflowTool);
45
+ addTool(file_1.uploadFilesTool);
46
+ addTool(file_1.downloadFileTool);
47
+ addTool(activity_1.listActivitiesTool);
48
+ addTool(activity_1.showActivityByIdTool);
49
+ addTool(activity_1.createActivityTool);
50
+ addTool(activity_1.updateActivityTool);
51
+ addTool(discussion_1.listMyDiscussionsTool);
52
+ addTool(discussion_1.fetchDiscussionMessagesTool);
53
+ addTool(discussion_1.fetchPreviousDiscussionMessagesTool);
54
+ addTool(discussion_1.joinDiscussionTool);
55
+ addTool(discussion_1.leaveDiscussionTool);
56
+ addTool(discussion_1.addDiscussionMessageTool);
57
+ addTool(discussion_1.inviteDiscussionMembersTool);
58
+ addTool(discussion_1.getActivityFromDiscussionTool);
59
+ addTool(user_1.searchWorkspaceUsersTool);
60
+ addTool(user_1.getWorkspaceBalanceTool);
61
+ addTool(workflow_1.getWorkflowSchemaTool);
62
+ addTool(workflow_1.listWorkflowPhasesTool);
63
+ addTool(workflow_1.listWorkflowsTool);
64
+ addTool(workflow_1.installWorkflowTool);
43
65
  if (config_1.environment.ENABLE_NUCLEAR_TOOLS) {
44
- core.addTool(workflow_1.removeWorkflowTool);
66
+ addTool(workflow_1.removeWorkflowTool);
45
67
  }
46
- core.addTool(workflow_1.updateWorkflowFieldTool);
47
- core.addTool(workflow_1.updateWorkflowPhaseTool);
48
- core.addTool(workflow_1.testFunctionFieldTool);
49
- core.addTool(workflow_1.listWorkflowsMinimalTool);
50
- core.addTool(workflow_1.countActivitiesTool);
51
- core.addTool(insight_1.createInsightTool);
52
- core.addTool(insight_1.previewInsightTool);
53
- core.addTool(insight_1.getInsightDataTool);
54
- core.addTool(insight_1.updateInsightTool);
68
+ addTool(workflow_1.updateWorkflowFieldTool);
69
+ addTool(workflow_1.updateWorkflowPhaseTool);
70
+ addTool(workflow_1.testFunctionFieldTool);
71
+ addTool(workflow_1.listWorkflowsMinimalTool);
72
+ addTool(workflow_1.countActivitiesTool);
73
+ addTool(insight_1.createInsightTool);
74
+ addTool(insight_1.previewInsightTool);
75
+ addTool(insight_1.getInsightDataTool);
76
+ addTool(insight_1.updateInsightTool);
55
77
  if (config_1.environment.ENABLE_NUCLEAR_TOOLS) {
56
- core.addTool(insight_1.removeInsightTool);
78
+ addTool(insight_1.removeInsightTool);
57
79
  }
58
- core.addTool(insight_1.listInsightsTool);
59
- core.addTool(app_1.createAppTool);
60
- core.addTool(app_1.listAppsTool);
61
- core.addTool(app_1.updateAppTool);
80
+ addTool(insight_1.listInsightsTool);
81
+ addTool(app_1.createAppTool);
82
+ addTool(app_1.listAppsTool);
83
+ addTool(app_1.updateAppTool);
62
84
  if (config_1.environment.ENABLE_NUCLEAR_TOOLS) {
63
- core.addTool(app_1.removeAppTool);
85
+ addTool(app_1.removeAppTool);
64
86
  }
65
- core.addTool(app_1.addAppMemberTool);
66
- core.addTool(app_1.removeAppMemberTool);
67
- core.addTool(app_1.scaffoldHailerAppTool);
68
- core.addTool(app_1.publishHailerAppTool);
87
+ addTool(app_1.addAppMemberTool);
88
+ addTool(app_1.removeAppMemberTool);
89
+ addTool(app_1.scaffoldHailerAppTool);
90
+ addTool(app_1.publishHailerAppTool);
69
91
  // Marketplace template tools
70
- core.addTool(app_1.listTemplatesTool);
71
- core.addTool(app_1.createTemplateTool);
72
- core.addTool(app_1.installTemplateTool);
73
- core.addTool(app_1.getTemplateTool);
74
- core.addTool(app_1.publishTemplateTool);
75
- core.addTool(app_1.getProductTool);
76
- core.addTool(app_1.getProductManifestTool);
92
+ addTool(app_1.listTemplatesTool);
93
+ addTool(app_1.createTemplateTool);
94
+ addTool(app_1.installTemplateTool);
95
+ addTool(app_1.getTemplateTool);
96
+ addTool(app_1.publishTemplateTool);
97
+ addTool(app_1.getProductTool);
98
+ addTool(app_1.getProductManifestTool);
77
99
  // Marketplace app tools
78
- core.addTool(app_1.publishAppTool);
79
- core.addTool(app_1.installMarketplaceAppTool);
100
+ addTool(app_1.publishAppTool);
101
+ addTool(app_1.installMarketplaceAppTool);
80
102
  // Bot-internal tools - dynamically imported only when MCP_CLIENT_ENABLED=true
81
103
  // This allows npm package to work without bot-config and bug-fixer modules
82
- if (config_1.environment.MCP_CLIENT_ENABLED) {
104
+ if (config_1.environment.MCP_CLIENT_ENABLED && !isStdioMode) {
83
105
  // Dynamic import bot-config tools
84
106
  const { listBotsConfigTool, enableBotTool, disableBotTool, checkSpecialistStatusTool } = require('./bot-config');
85
- core.addTool(listBotsConfigTool);
86
- core.addTool(enableBotTool);
87
- core.addTool(disableBotTool);
88
- core.addTool(checkSpecialistStatusTool);
107
+ addTool(listBotsConfigTool);
108
+ addTool(enableBotTool);
109
+ addTool(disableBotTool);
110
+ addTool(checkSpecialistStatusTool);
89
111
  // Dynamic import bug-fixer tools
90
112
  const {
91
113
  // Low-level tools
@@ -93,34 +115,44 @@ if (config_1.environment.MCP_CLIENT_ENABLED) {
93
115
  // High-level workflow tools (LLM-driven)
94
116
  bugFixerAnalyzeBugTool, bugFixerStartFixTool, bugFixerMarkDeclinedTool, bugFixerPublishFixTool, bugFixerRetryFixTool, markBugDeclinedTool, markBugFixedTool } = require('./mcp/tools/bug-fixer-tools');
95
117
  // Low-level tools
96
- core.addTool(bugFixerFindAppTool);
97
- core.addTool(bugFixerListFilesTool);
98
- core.addTool(bugFixerReadFileTool);
99
- core.addTool(bugFixerWriteFileTool);
100
- core.addTool(bugFixerApplyFixTool);
101
- core.addTool(bugFixerRunBuildTool);
102
- core.addTool(bugFixerGitStatusTool);
103
- core.addTool(bugFixerGitPullTool);
104
- core.addTool(bugFixerGitCommitTool);
105
- core.addTool(bugFixerGitPushTool);
106
- core.addTool(bugFixerGitRevertTool);
107
- core.addTool(bugFixerPublishAppTool);
118
+ addTool(bugFixerFindAppTool);
119
+ addTool(bugFixerListFilesTool);
120
+ addTool(bugFixerReadFileTool);
121
+ addTool(bugFixerWriteFileTool);
122
+ addTool(bugFixerApplyFixTool);
123
+ addTool(bugFixerRunBuildTool);
124
+ addTool(bugFixerGitStatusTool);
125
+ addTool(bugFixerGitPullTool);
126
+ addTool(bugFixerGitCommitTool);
127
+ addTool(bugFixerGitPushTool);
128
+ addTool(bugFixerGitRevertTool);
129
+ addTool(bugFixerPublishAppTool);
108
130
  // High-level workflow tools (LLM-driven)
109
- core.addTool(bugFixerAnalyzeBugTool);
110
- core.addTool(bugFixerStartFixTool);
111
- core.addTool(bugFixerMarkDeclinedTool);
112
- core.addTool(bugFixerPublishFixTool);
113
- core.addTool(bugFixerRetryFixTool);
114
- core.addTool(markBugDeclinedTool);
115
- core.addTool(markBugFixedTool);
131
+ addTool(bugFixerAnalyzeBugTool);
132
+ addTool(bugFixerStartFixTool);
133
+ addTool(bugFixerMarkDeclinedTool);
134
+ addTool(bugFixerPublishFixTool);
135
+ addTool(bugFixerRetryFixTool);
136
+ addTool(markBugDeclinedTool);
137
+ addTool(markBugFixedTool);
116
138
  logger.info('Bot-internal tools registered (MCP_CLIENT_ENABLED=true)');
117
139
  }
118
140
  logger.info('All tools registered successfully');
119
- // Start the application
120
- core.start().catch((error) => {
121
- logger.error('Failed to start Hailer MCP application', error);
122
- process.exit(1);
123
- });
124
- // Export core for testing and external access
141
+ // Start the appropriate server based on transport mode
142
+ if (isStdioMode && toolRegistry) {
143
+ // Stdio mode for Claude Desktop
144
+ (0, stdio_server_1.startStdioServer)(toolRegistry).catch((error) => {
145
+ logger.error('Failed to start stdio MCP server', error);
146
+ process.exit(1);
147
+ });
148
+ }
149
+ else if (core) {
150
+ // HTTP mode for other clients
151
+ core.start().catch((error) => {
152
+ logger.error('Failed to start Hailer MCP application', error);
153
+ process.exit(1);
154
+ });
155
+ }
156
+ // Export core for testing and external access (may be null in stdio mode)
125
157
  exports.default = core;
126
158
  //# sourceMappingURL=app.js.map
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Simple Hailer Chat Bot
3
+ *
4
+ * Listens to discussions via WebSocket, responds using Anthropic Claude API
5
+ * with access to ALL MCP tools via the ToolRegistry.
6
+ */
7
+ interface BotConfig {
8
+ email: string;
9
+ password: string;
10
+ apiBaseUrl: string;
11
+ anthropicApiKey: string;
12
+ botName?: string;
13
+ model?: string;
14
+ }
15
+ export declare class HailerChatBot {
16
+ private clientManager;
17
+ private hailerApi;
18
+ private anthropic;
19
+ private botUserId;
20
+ private apiKey;
21
+ private config;
22
+ private toolRegistry;
23
+ constructor(config: BotConfig);
24
+ private registerAllTools;
25
+ start(): Promise<void>;
26
+ private handleMessage;
27
+ private generateResponse;
28
+ stop(): Promise<void>;
29
+ }
30
+ export default HailerChatBot;
31
+ //# sourceMappingURL=chat-bot.d.ts.map