@tenpo/mcp 0.2.2 → 0.2.4
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/README.md +3 -0
- package/dist/index.js +51 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -237,6 +237,9 @@ That's the first line. **First run auto-issues a free API key** (500 calls/month
|
|
|
237
237
|
|
|
238
238
|
The second line goes into your AI host's config:
|
|
239
239
|
|
|
240
|
+
> ⚠️ **After editing the config, fully restart your AI host.**
|
|
241
|
+
> MCP servers are loaded at host startup — `claude mcp add`, saving Claude Desktop's config, or editing Cursor's MCP settings will register Tenpo, but the new tools won't appear in your running session until you **quit and relaunch the app** (Cmd+Q on Mac, fully close on Windows). This is a host-side limitation, not a Tenpo one.
|
|
242
|
+
|
|
240
243
|
<details>
|
|
241
244
|
<summary><b>Claude Desktop</b> · <code>claude_desktop_config.json</code></summary>
|
|
242
245
|
|
package/dist/index.js
CHANGED
|
@@ -370,6 +370,48 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
370
370
|
}));
|
|
371
371
|
return { tools: [...TOOLS, ...dynamicEntries] };
|
|
372
372
|
});
|
|
373
|
+
/**
|
|
374
|
+
* Format a backend tool result as MCP CallTool content.
|
|
375
|
+
*
|
|
376
|
+
* Many Tenpo tools return `data.chat_message` — a pre-formatted, chat-ready
|
|
377
|
+
* string the host AI should display verbatim. Surface that as the PRIMARY
|
|
378
|
+
* text block; append the structured JSON afterward so the host AI can still
|
|
379
|
+
* introspect (e.g. for follow-up tool calls or to read `instruction_for_host_ai`).
|
|
380
|
+
*
|
|
381
|
+
* This stops the old "double-encoded JSON inside JSON" UX where the host AI
|
|
382
|
+
* saw nothing but a stringified blob.
|
|
383
|
+
*/
|
|
384
|
+
function formatToolResult(result) {
|
|
385
|
+
const r = result;
|
|
386
|
+
// Error path
|
|
387
|
+
if (r && r.ok === false) {
|
|
388
|
+
return {
|
|
389
|
+
content: [
|
|
390
|
+
{ type: "text", text: `Error: ${r.error ?? "Tool execution failed"}` },
|
|
391
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
392
|
+
],
|
|
393
|
+
isError: true,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
// chat_message can live at:
|
|
397
|
+
// data.chat_message — MCP-direct tools (onboarding, can_help_with, etc.)
|
|
398
|
+
// data.details.chat_message — gateway tools wrapped via jsonResult()
|
|
399
|
+
const chatMessage = r?.data?.details?.chat_message ??
|
|
400
|
+
r?.data?.chat_message;
|
|
401
|
+
if (typeof chatMessage === "string" && chatMessage.length > 0) {
|
|
402
|
+
// Primary: the chat-ready message. Secondary: structured JSON for introspection.
|
|
403
|
+
return {
|
|
404
|
+
content: [
|
|
405
|
+
{ type: "text", text: chatMessage },
|
|
406
|
+
{ type: "text", text: JSON.stringify(result, null, 2) },
|
|
407
|
+
],
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
// No chat_message — return JSON directly (no recursion!)
|
|
411
|
+
return {
|
|
412
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
413
|
+
};
|
|
414
|
+
}
|
|
373
415
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
374
416
|
await ensureApiKey();
|
|
375
417
|
const { name, arguments: args = {} } = request.params;
|
|
@@ -380,7 +422,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
380
422
|
method: "POST",
|
|
381
423
|
body: args,
|
|
382
424
|
});
|
|
383
|
-
return
|
|
425
|
+
return formatToolResult(result);
|
|
384
426
|
}
|
|
385
427
|
case "tenpo_run_tool": {
|
|
386
428
|
const a = args;
|
|
@@ -390,7 +432,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
390
432
|
method: "POST",
|
|
391
433
|
body: a.args ?? {},
|
|
392
434
|
});
|
|
393
|
-
return
|
|
435
|
+
return formatToolResult(result);
|
|
394
436
|
}
|
|
395
437
|
case "tenpo_classify_intent": {
|
|
396
438
|
const a = args;
|
|
@@ -449,7 +491,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
449
491
|
if (!a.resource)
|
|
450
492
|
throw new Error("resource name required");
|
|
451
493
|
const result = await tenpoFetch(`/api/v1/resources/${encodeURIComponent(a.resource)}`);
|
|
452
|
-
return
|
|
494
|
+
return formatToolResult(result);
|
|
453
495
|
}
|
|
454
496
|
case "tenpo_get_prompt": {
|
|
455
497
|
const a = args;
|
|
@@ -464,7 +506,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
464
506
|
path += `?${params.toString()}`;
|
|
465
507
|
}
|
|
466
508
|
const result = await tenpoFetch(path);
|
|
467
|
-
return
|
|
509
|
+
return formatToolResult(result);
|
|
468
510
|
}
|
|
469
511
|
case "tenpo_list_prompts": {
|
|
470
512
|
const a = args;
|
|
@@ -472,7 +514,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
472
514
|
? `/api/v1/prompts?q=${encodeURIComponent(a.q)}`
|
|
473
515
|
: `/api/v1/prompts`;
|
|
474
516
|
const result = await tenpoFetch(path);
|
|
475
|
-
return
|
|
517
|
+
return formatToolResult(result);
|
|
476
518
|
}
|
|
477
519
|
case "tenpo_connect_integration": {
|
|
478
520
|
const a = args;
|
|
@@ -483,13 +525,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
483
525
|
method: "POST",
|
|
484
526
|
body: { integration_id: a.integration_id, credentials: a.credentials },
|
|
485
527
|
});
|
|
486
|
-
return
|
|
528
|
+
return formatToolResult(result);
|
|
487
529
|
}
|
|
488
530
|
const result = await tenpoFetch("/api/v1/connect/start", {
|
|
489
531
|
method: "POST",
|
|
490
532
|
body: { integration_id: a.integration_id },
|
|
491
533
|
});
|
|
492
|
-
return
|
|
534
|
+
return formatToolResult(result);
|
|
493
535
|
}
|
|
494
536
|
case "tenpo_remember": {
|
|
495
537
|
const a = args;
|
|
@@ -500,7 +542,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
500
542
|
method: "POST",
|
|
501
543
|
body: { content, scope: a.scope ?? a.memory_type ?? "fact", mode: a.mode ?? "append" },
|
|
502
544
|
});
|
|
503
|
-
return
|
|
545
|
+
return formatToolResult(result);
|
|
504
546
|
}
|
|
505
547
|
// tenpo_pattern_detect, tenpo_fetch_url, tenpo_write_md, tenpo_route_skills,
|
|
506
548
|
// tenpo_overview cases DROPPED — host AI's native capabilities cover them.
|
|
@@ -515,7 +557,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
515
557
|
throw new Error(`Unknown tool: ${name}. Use tenpo_route to discover available tools.`);
|
|
516
558
|
}
|
|
517
559
|
const result = await tenpoFetch(`/api/v1/tools/${encodeURIComponent(name)}`, { method: "POST", body: args });
|
|
518
|
-
return
|
|
560
|
+
return formatToolResult(result);
|
|
519
561
|
}
|
|
520
562
|
}
|
|
521
563
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tenpo/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Tenpo — the operator that runs alongside your store. Connects to 45+ commerce platforms (Shopify, Klaviyo, Meta Ads, GA4, Stripe…) and gives any AI host (Claude Desktop, Cursor, Claude Code, ChatGPT) deterministic answers about your sales, ads, email, inventory, suppliers, customers, finance, and competitors. Free tier, no card required.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://tenpo.ai",
|