byclaw-mcp 0.4.9 → 0.4.10

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 (2) hide show
  1. package/dist/index.js +51 -36
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -40,7 +40,7 @@ async function apiCall(path, options = {}) {
40
40
  });
41
41
  return res.json();
42
42
  }
43
- const server = new index_js_1.Server({ name: 'byclaw', version: '0.4.0' }, { capabilities: { tools: {}, prompts: {} } });
43
+ const server = new index_js_1.Server({ name: 'byclaw', version: '0.4.10' }, { capabilities: { tools: {}, prompts: {} } });
44
44
  // Prompts
45
45
  server.setRequestHandler(types_js_1.ListPromptsRequestSchema, async () => ({
46
46
  prompts: [{
@@ -250,8 +250,12 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
250
250
  });
251
251
  if (result?.ok) {
252
252
  const d = result.data;
253
- const disclosure = d.disclosure || 'ℹ️ Affiliate-Link. byclaw earns a small commission — no extra cost to you.';
254
- const personalityName = d.agent?.personality || d.advisor || '';
253
+ // F1: canonical schema same field names across MCP shop/test_web_search/Web API:
254
+ // type: product_found | clarification_needed | no_match | gift_found | gift_no_results | acknowledgement_legacy
255
+ // picked.affiliate_url (NOT recommendation.url)
256
+ // disclosure (NOT affiliate_notice)
257
+ // message (single, in caller's language; never message_de/message_en)
258
+ const personalityName = d.agent?.personality || '';
255
259
  const advisorLabel = d.advisor_profile?.name || personalityName.charAt(0).toUpperCase() + personalityName.slice(1) || 'Advisor';
256
260
  // ── GIFT MODE ──
257
261
  if (d.status === 'gift_found' && Array.isArray(d.gift_picks) && d.gift_picks.length > 0) {
@@ -268,19 +272,20 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
268
272
  type: 'gift_found',
269
273
  advisor: advisorLabel,
270
274
  advisor_profile: d.advisor_profile || null,
275
+ message: d.message || null,
271
276
  gift_picks: d.gift_picks.map((p) => ({
272
277
  title: p.title,
273
278
  price: p.price,
274
279
  brand: p.brand || '',
275
280
  merchant: p.merchant || '',
276
- reasoning: p.reasoning || '',
277
- url: p.affiliate_url || '',
281
+ reasoning: p.reasoning || null,
282
+ affiliate_url: p.affiliate_url || '',
278
283
  })),
279
284
  gift_intent: {
280
285
  recipient: intent.recipient || '',
281
286
  summary: intent.summary || '',
282
287
  },
283
- affiliate_notice: disclosure,
288
+ disclosure: d.disclosure || null,
284
289
  ...(d.note ? { note: d.note } : {}),
285
290
  }, null, 2) }] };
286
291
  }
@@ -293,7 +298,18 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
293
298
  message: d.message || '',
294
299
  suggested_next: d.suggested_next || [],
295
300
  context_summary: d.context_summary || null,
296
- affiliate_notice: disclosure,
301
+ disclosure: d.disclosure || null,
302
+ ...(d.note ? { note: d.note } : {}),
303
+ }, null, 2) }] };
304
+ }
305
+ // ── ACKNOWLEDGEMENT (F3.a interim) ──
306
+ if (d.status === 'acknowledgement_legacy' || d.status === 'acknowledgement') {
307
+ return { content: [{ type: 'text', text: JSON.stringify({
308
+ type: d.status,
309
+ advisor: advisorLabel,
310
+ advisor_profile: d.advisor_profile || null,
311
+ message: d.message || '',
312
+ disclosure: d.disclosure || null,
297
313
  ...(d.note ? { note: d.note } : {}),
298
314
  }, null, 2) }] };
299
315
  }
@@ -306,47 +322,47 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
306
322
  return null;
307
323
  return fetchImageBase64(p.image_url);
308
324
  }));
309
- // Add picked image
310
- if (allImages[0]) {
325
+ // Add picked image only when we actually have a product_found
326
+ if (d.status === 'product_found' && allImages[0]) {
311
327
  content.push({ type: 'image', data: allImages[0].data, mimeType: allImages[0].mimeType });
312
328
  }
313
- // Add structured data handle no_match vs product_recommendation
329
+ // F1: canonical fields. F6: no message_de/message_en. F2: no fallback to message.
314
330
  if (d.status === 'no_match') {
315
331
  content.push({ type: 'text', text: JSON.stringify({
316
332
  type: 'no_match',
317
333
  advisor: advisorLabel,
318
334
  advisor_profile: d.advisor_profile || null,
319
- message_de: 'Hab leider nichts in deinem Suchbereich gefunden. Probier es mit weniger Filtern oder anderen Begriffen.',
320
- message_en: 'No products found for your search. Try fewer filters or different terms.',
321
- compared: 0,
322
- affiliate_notice: d.disclosure || 'Affiliate disclosure: The links on this page are affiliate links. byclaw.io receives a commission from the retailer when you make a purchase. No additional cost to you.',
335
+ message: d.message || '',
336
+ compared: d.compared || 0,
337
+ disclosure: d.disclosure || null,
323
338
  ...(d.note ? { note: d.note } : {}),
324
339
  }, null, 2) });
325
340
  }
326
341
  else {
342
+ const hasPick = !!d.picked;
327
343
  content.push({ type: 'text', text: JSON.stringify({
328
- type: 'product_recommendation',
344
+ type: d.status || 'product_found',
329
345
  advisor: advisorLabel,
330
346
  advisor_profile: d.advisor_profile || null,
331
- recommendation: {
332
- title: d.picked?.title || '',
333
- price: d.picked?.price ?? '',
334
- brand: d.picked?.brand || '',
335
- merchant: d.picked?.merchant || '',
336
- url: d.picked?.affiliate_url || '',
337
- review: d.review || d.reasoning || '',
338
- },
347
+ picked: hasPick ? {
348
+ title: d.picked.title || '',
349
+ price: d.picked.price ?? null,
350
+ brand: d.picked.brand || '',
351
+ merchant: d.picked.merchant || '',
352
+ affiliate_url: d.picked.affiliate_url || '',
353
+ } : null,
339
354
  alternatives: (d.alternatives || []).slice(0, 3).map((a) => ({
340
355
  title: a.title,
341
356
  price: a.price,
342
357
  brand: a.brand || '',
343
358
  category: a.category || '',
344
359
  merchant: a.merchant || '',
345
- url: a.affiliate_url || '',
360
+ affiliate_url: a.affiliate_url || '',
346
361
  })),
347
362
  compared: d.compared || 0,
348
- reasoning: d.reasoning || '',
349
- affiliate_notice: d.disclosure || 'Affiliate disclosure: The links on this page are affiliate links. byclaw.io receives a commission from the retailer when you make a purchase. No additional cost to you.',
363
+ reasoning: hasPick && d.reasoning ? d.reasoning : null,
364
+ review: hasPick && d.review ? d.review : null,
365
+ disclosure: d.disclosure || null,
350
366
  ...(d.note ? { note: d.note } : {}),
351
367
  }, null, 2) });
352
368
  }
@@ -441,16 +457,13 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
441
457
  return { content: [{ type: 'text', text: JSON.stringify({ type: 'web_search_error', error: result?.error || 'Unknown error', raw: result }, null, 2) }] };
442
458
  }
443
459
  const d = result.data;
444
- // Clarification responses have different fields than product responses
460
+ // Clarification responses
445
461
  if (d.status === 'clarification_needed') {
446
462
  return { content: [{ type: 'text', text: JSON.stringify({
447
463
  type: 'clarification_needed',
448
- endpoint: '/api/agents/shop',
449
464
  advisor: d.advisor_profile?.name || d.agent?.personality || null,
450
465
  advisor_profile: d.advisor_profile || null,
451
466
  message: d.message || null,
452
- message_de: d.message_de || null,
453
- message_en: d.message_en || null,
454
467
  suggested_next: d.suggested_next || [],
455
468
  context_summary: d.context_summary || null,
456
469
  disclosure: d.disclosure || null,
@@ -461,7 +474,6 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
461
474
  if (d.status === 'gift_found' && d.gift_picks) {
462
475
  return { content: [{ type: 'text', text: JSON.stringify({
463
476
  type: 'gift_found',
464
- endpoint: '/api/agents/shop',
465
477
  advisor: d.advisor_profile?.name || d.agent?.personality || null,
466
478
  advisor_profile: d.advisor_profile || null,
467
479
  message: d.message || null,
@@ -471,17 +483,20 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
471
483
  note: d.note || null,
472
484
  }, null, 2) }] };
473
485
  }
486
+ // product_found / no_match / fallback
487
+ // F2: review and reasoning only when picked exists AND fields are present
488
+ // (no fallback to d.message — that produced bit-identical strings on no_match)
489
+ const hasPick = !!d.picked;
474
490
  return { content: [{ type: 'text', text: JSON.stringify({
475
- type: d.status || 'web_search_result',
476
- endpoint: '/api/agents/shop',
491
+ type: d.status || 'no_match',
477
492
  advisor: d.advisor_profile?.name || d.agent?.personality || null,
478
493
  advisor_profile: d.advisor_profile || null,
479
494
  message: d.message || null,
480
- picked: d.picked ? { title: d.picked.title, price: d.picked.price, brand: d.picked.brand, affiliate_url: d.picked.affiliate_url } : null,
495
+ picked: hasPick ? { title: d.picked.title, price: d.picked.price, brand: d.picked.brand, affiliate_url: d.picked.affiliate_url } : null,
481
496
  alternatives: (d.alternatives || []).map((a) => ({ title: a.title, price: a.price, brand: a.brand })),
482
497
  compared: d.compared || 0,
483
- review: d.review || d.message || null,
484
- reasoning: d.reasoning || d.message || null,
498
+ review: hasPick && d.review ? d.review : null,
499
+ reasoning: hasPick && d.reasoning ? d.reasoning : null,
485
500
  disclosure: d.disclosure || null,
486
501
  note: d.note || null,
487
502
  }, null, 2) }] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "byclaw-mcp",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
4
4
  "description": "MCP Server for byclaw.io — Your AI shopping advisor. Connects Claude Desktop and other MCP clients to the byclaw.io product catalog.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {