byclaw-mcp 0.4.14 → 0.4.16
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/index.js +52 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -53,16 +53,43 @@ function imageUrlOf(p) {
|
|
|
53
53
|
const url = typeof p?.image_url === 'string' ? p.image_url.trim() : '';
|
|
54
54
|
return url.startsWith('https://') || url.startsWith('http://') ? url : IMAGE_FALLBACK;
|
|
55
55
|
}
|
|
56
|
+
// Hard cap on every backend request. Without it, if the backend is wedged
|
|
57
|
+
// (Anthropic 503 + SDK retry storm, ES lock, …) the MCP process would hang
|
|
58
|
+
// forever and the client (Claude Desktop) would only break out at its own
|
|
59
|
+
// 4 min cap with a "Server disconnected" disconnect — the very symptom
|
|
60
|
+
// Finding 094 described. 60 s is comfortably above normal backend latency
|
|
61
|
+
// (10-15 s for /api/mcp/shop) but below the client timeout, so the user
|
|
62
|
+
// gets a real error message instead of a stall.
|
|
63
|
+
const BACKEND_TIMEOUT_MS = 60000;
|
|
56
64
|
async function apiCall(path, options = {}) {
|
|
57
65
|
const headers = {
|
|
58
66
|
'Authorization': `Bearer ${API_KEY}`,
|
|
59
67
|
'Content-Type': 'application/json',
|
|
60
68
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
try {
|
|
70
|
+
const res = await fetch(`${API_BASE}${path}`, {
|
|
71
|
+
...options,
|
|
72
|
+
signal: AbortSignal.timeout(BACKEND_TIMEOUT_MS),
|
|
73
|
+
headers: { ...headers, ...options.headers },
|
|
74
|
+
});
|
|
75
|
+
return res.json();
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
// AbortError fires when the timeout above kicks in. Translate to an
|
|
79
|
+
// ok=false body the existing call sites already know how to print.
|
|
80
|
+
if (err?.name === 'AbortError' || err?.name === 'TimeoutError') {
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
error: `Backend timeout after ${BACKEND_TIMEOUT_MS / 1000}s (${path})`,
|
|
84
|
+
retryable: true,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
error: `Backend request failed: ${err?.message || 'unknown error'} (${path})`,
|
|
90
|
+
retryable: false,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
66
93
|
}
|
|
67
94
|
const server = new index_js_1.Server({ name: 'byclaw', version: SERVER_VERSION }, { capabilities: { tools: {}, prompts: {} } });
|
|
68
95
|
// Prompts
|
|
@@ -115,6 +142,11 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
115
142
|
required: ['query'],
|
|
116
143
|
},
|
|
117
144
|
},
|
|
145
|
+
{
|
|
146
|
+
name: 'whoami',
|
|
147
|
+
description: TOOL_PREFIX + 'Return the active byclaw agent: its codename (e.g. #1949-H), personality (smartpicker / dealmaker / luxpicker / vibechecker / quickshooter), tagline, tone, and review style. Use when the user asks "which agent am I using", "what persona is searching for me", or "wer entscheidet hier". Cheap, no Anthropic call. Every shop / search_products / test_web_search response also surfaces this in the `agent` and `advisor_profile` fields.',
|
|
148
|
+
inputSchema: { type: 'object', properties: {} },
|
|
149
|
+
},
|
|
118
150
|
{
|
|
119
151
|
name: 'leave_review',
|
|
120
152
|
description: TOOL_PREFIX + 'Write a product review. Only call if the user explicitly asks to leave a review. Only de and en allowed.',
|
|
@@ -295,6 +327,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
295
327
|
return { content: [{ type: 'text', text: JSON.stringify({
|
|
296
328
|
_render_hint: RENDER_HINT,
|
|
297
329
|
type: 'gift_found',
|
|
330
|
+
agent: d.agent || null,
|
|
298
331
|
advisor: advisorLabel,
|
|
299
332
|
advisor_profile: d.advisor_profile || null,
|
|
300
333
|
message: d.message || null,
|
|
@@ -319,6 +352,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
319
352
|
if (d.status === 'clarification_needed') {
|
|
320
353
|
return { content: [{ type: 'text', text: JSON.stringify({
|
|
321
354
|
type: 'clarification_needed',
|
|
355
|
+
agent: d.agent || null,
|
|
322
356
|
advisor: advisorLabel,
|
|
323
357
|
advisor_profile: d.advisor_profile || null,
|
|
324
358
|
message: d.message || '',
|
|
@@ -332,6 +366,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
332
366
|
if (d.status === 'acknowledgement_legacy' || d.status === 'acknowledgement') {
|
|
333
367
|
return { content: [{ type: 'text', text: JSON.stringify({
|
|
334
368
|
type: d.status,
|
|
369
|
+
agent: d.agent || null,
|
|
335
370
|
advisor: advisorLabel,
|
|
336
371
|
advisor_profile: d.advisor_profile || null,
|
|
337
372
|
message: d.message || '',
|
|
@@ -349,6 +384,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
349
384
|
if (d.status === 'no_match') {
|
|
350
385
|
content.push({ type: 'text', text: JSON.stringify({
|
|
351
386
|
type: 'no_match',
|
|
387
|
+
agent: d.agent || null,
|
|
352
388
|
advisor: advisorLabel,
|
|
353
389
|
advisor_profile: d.advisor_profile || null,
|
|
354
390
|
message: d.message || '',
|
|
@@ -362,6 +398,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
362
398
|
content.push({ type: 'text', text: JSON.stringify({
|
|
363
399
|
_render_hint: RENDER_HINT,
|
|
364
400
|
type: d.status || 'product_found',
|
|
401
|
+
agent: d.agent || null,
|
|
365
402
|
advisor: advisorLabel,
|
|
366
403
|
advisor_profile: d.advisor_profile || null,
|
|
367
404
|
picked: hasPick ? {
|
|
@@ -431,6 +468,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
431
468
|
}
|
|
432
469
|
return { content: [{ type: 'text', text: JSON.stringify({ _render_hint: RENDER_HINT, ...result }, null, 2) }] };
|
|
433
470
|
}
|
|
471
|
+
case 'whoami': {
|
|
472
|
+
// Cheap lookup — backend `/api/agents/profile` resolves the agent
|
|
473
|
+
// from the API key and returns name + persona + style fields.
|
|
474
|
+
// No Anthropic call, no DB writes; ~50 ms typical.
|
|
475
|
+
const result = await apiCall('/api/agents/profile');
|
|
476
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
477
|
+
}
|
|
434
478
|
case 'leave_review': {
|
|
435
479
|
const lang = args?.language;
|
|
436
480
|
if (lang !== 'de' && lang !== 'en') {
|
|
@@ -490,6 +534,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
490
534
|
if (d.status === 'clarification_needed') {
|
|
491
535
|
return { content: [{ type: 'text', text: JSON.stringify({
|
|
492
536
|
type: 'clarification_needed',
|
|
537
|
+
agent: d.agent || null,
|
|
493
538
|
advisor: d.advisor_profile?.name || d.agent?.personality || null,
|
|
494
539
|
advisor_profile: d.advisor_profile || null,
|
|
495
540
|
message: d.message || null,
|
|
@@ -504,6 +549,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
504
549
|
return { content: [{ type: 'text', text: JSON.stringify({
|
|
505
550
|
_render_hint: RENDER_HINT,
|
|
506
551
|
type: 'gift_found',
|
|
552
|
+
agent: d.agent || null,
|
|
507
553
|
advisor: d.advisor_profile?.name || d.agent?.personality || null,
|
|
508
554
|
advisor_profile: d.advisor_profile || null,
|
|
509
555
|
message: d.message || null,
|
|
@@ -520,6 +566,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
520
566
|
return { content: [{ type: 'text', text: JSON.stringify({
|
|
521
567
|
_render_hint: RENDER_HINT,
|
|
522
568
|
type: d.status || 'no_match',
|
|
569
|
+
agent: d.agent || null,
|
|
523
570
|
advisor: d.advisor_profile?.name || d.agent?.personality || null,
|
|
524
571
|
advisor_profile: d.advisor_profile || null,
|
|
525
572
|
message: d.message || null,
|
package/package.json
CHANGED