@tenpo/mcp 0.2.1 → 0.2.3

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 (3) hide show
  1. package/README.md +58 -43
  2. package/dist/index.js +54 -15
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -9,7 +9,6 @@ Tenpo runs your dashboards *for* you — across every platform, every minute, in
9
9
 
10
10
  [![npm](https://img.shields.io/npm/v/@tenpo/mcp.svg?style=flat-square&color=000)](https://www.npmjs.com/package/@tenpo/mcp)
11
11
  [![license](https://img.shields.io/badge/license-MIT-000.svg?style=flat-square)](LICENSE)
12
- [![docs](https://img.shields.io/badge/docs-tenpo.ai-000.svg?style=flat-square)](https://tenpo.ai)
13
12
 
14
13
  [**Get started in 2 lines →**](#install-in-2-lines) · [**See it think →**](#how-tenpo-thinks) · [**What it covers →**](#what-tenpo-covers)
15
14
 
@@ -35,14 +34,13 @@ When you ask Tenpo something, it doesn't look up a pre-calculated answer. It que
35
34
 
36
35
  It's like having a business partner who:
37
36
 
38
- - Has memorised every order, product, customer, campaign, and supplier
39
- - Monitors your store 24/7, even when you're asleep
37
+ - Has memorised every order, product, customer, campaign, and supplier — once you connect them
40
38
  - Spots problems before they become expensive
41
39
  - Connects dots no human analyst would realistically cross-reference
42
40
  - Knows *when to act* and *when to ask*
43
41
  - Gets smarter about your specific business the longer you work together
44
42
 
45
- You bring an AI host (Claude, Cursor, ChatGPT). Tenpo brings the synapses. **Your AI does the thinking, Tenpo provides the truth.**
43
+ You bring an AI host (Claude Desktop, Cursor, Claude Code, Codex, Hermes, OpenClaw — anything that speaks MCP). Tenpo brings the synapses. **Your AI does the thinking, Tenpo provides the truth.**
46
44
 
47
45
  ---
48
46
 
@@ -158,19 +156,19 @@ What's my true ROAS after COGS + shipping + fees · which campaigns to pause rig
158
156
 
159
157
  <tr><td><b>Customers</b></td><td>
160
158
 
161
- Who's about to churn · predicted next order date per customer · top 1% / 10% / 25% concentration risk · cross-sell next-best-product · win-back the right customers at the right time · respond to support tickets in Gorgias/Zendesk · reply to reviews on Trustpilot/Okendo/Judge.me
159
+ Who's about to churn · predicted next order date per customer · top 1% / 10% / 25% concentration risk · cross-sell next-best-product · win-back the right customers at the right time · respond to support tickets in Gorgias / Zendesk · reply to reviews on Trustpilot / Okendo / Judge.me
162
160
 
163
161
  </td></tr>
164
162
 
165
163
  <tr><td><b>Finance & Operations</b></td><td>
166
164
 
167
- P&L waterfall (gross → COGS → fees → ad spend → operating profit) · what's leaking at each step · process Stripe refunds · push invoices to Xero/QuickBooks · create shipping labels · track shipments · sales-tax nexus monitoring · payout holds and disputes
165
+ P&L waterfall (gross → COGS → fees → ad spend → operating profit) · what's leaking at each step · process Stripe refunds · push invoices to Xero / QuickBooks · create shipping labels · track shipments · sales-tax nexus monitoring · payout holds and disputes
168
166
 
169
167
  </td></tr>
170
168
 
171
169
  <tr><td><b>Competitors</b></td><td>
172
170
 
173
- What's [competitor] priced at right now · who dropped prices this week · what emails are top brands sending this month · new SKUs they launched · their promo cadence · benchmark my AOV / LTV / repurchase rate against peers in my category (k-anonymous)
171
+ What's [competitor] priced at right now · who dropped prices this week · what emails are top brands sending this month · new SKUs they launched · their promo cadence · benchmark my AOV / LTV / repurchase rate against peers in my category (anonymous, k≥3 merchants)
174
172
 
175
173
  </td></tr>
176
174
 
@@ -182,7 +180,7 @@ Every Monday morning, send me a store overview · when revenue drops 30%, ping m
182
180
 
183
181
  </table>
184
182
 
185
- Eight headline sectors. Behind them: **45+ platform integrations, 229 tools your AI can call, 155 specialist skills loaded on demand, and 17 background patterns Tenpo watches for continuously.**
183
+ Eight headline sectors. Behind them: **47 platform integrations, 229 tools your AI can call, and 100+ specialist skills loaded automatically based on what you ask.**
186
184
 
187
185
  ---
188
186
 
@@ -209,23 +207,23 @@ When you ask about pricing, it thinks in a **Velocity × Margin matrix**. When y
209
207
 
210
208
  ---
211
209
 
212
- ## Proactive monitoringTenpo watching when you're not
210
+ ## Background watchersfor connected stores
213
211
 
214
- Every 15 minutes no AI required, just pure logicTenpo runs background checks:
212
+ Once you've connected at least one integration, Tenpo runs background checks on your data automatically no tier upgrade required, no manual setup:
215
213
 
216
- | Watch | What it catches |
214
+ | Watcher | What it catches |
217
215
  |---|---|
218
216
  | **Stock risk** | Products getting dangerously close to selling out before the next supplier delivery |
219
- | **Revenue anomaly** | Unexplained drops in week-over-week revenue |
220
- | **Supplier delays** | POs that didn't arrive by their expected date |
221
- | **Customer churn wave** | Regular customers who've gone quiet |
222
- | **Dead stock growth** | Products sitting in your warehouse not moving |
223
- | **Wasted ad spend** | Campaigns running below breakeven ROAS, ads on out-of-stock products |
224
- | **Concentration risk** | Too much revenue from too few customers |
217
+ | **Revenue cliff** | Unexplained week-over-week revenue drops |
218
+ | **Refund spike** | Today's refund count exceeding the recent baseline |
219
+ | **ROAS death** | Ad campaigns running below breakeven |
220
+ | **Dead stock with active ads** | Ad spend on SKUs that haven't sold in 14+ days while inventory sits |
221
+ | **Payment failure spike** | Stripe / processor anomalies signalling card-data drift or outages |
222
+ | **Inventory desync** | DB stock says "available", Shopify says "out" — pipeline drift |
225
223
 
226
- When it spots something, you get a notification on your preferred channel — Telegram, WhatsApp, Slack, email. When the situation resolves itself, the alert closes automatically.
224
+ When a watcher fires, you get a notification on the channel you set up — Telegram, WhatsApp, Slack, or email. When the situation resolves itself, the alert closes automatically.
227
225
 
228
- By the time you open your phone in the morning, Tenpo has already been watching your store all night.
226
+ > **What this needs:** at least one connected store + a notification channel set up. Watchers don't run for accounts that registered but never connected anything (we don't burn cycles on empty data).
229
227
 
230
228
  ---
231
229
 
@@ -235,10 +233,13 @@ By the time you open your phone in the morning, Tenpo has already been watching
235
233
  npx -y @tenpo/mcp
236
234
  ```
237
235
 
238
- That's the first line. First run auto-issues a free API key (500 calls/day, no expiry, no card).
236
+ That's the first line. **First run auto-issues a free API key** (500 calls/month, no expiry, no card, no signup form). The key prints once in the host's stderr — copy it into your config so it's reused next time.
239
237
 
240
238
  The second line goes into your AI host's config:
241
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
+
242
243
  <details>
243
244
  <summary><b>Claude Desktop</b> · <code>claude_desktop_config.json</code></summary>
244
245
 
@@ -253,7 +254,7 @@ The second line goes into your AI host's config:
253
254
  }
254
255
  ```
255
256
 
256
- Restart Claude Desktop. The first call prints your key — paste it into `env.TENPO_API_KEY` to keep using the same one:
257
+ Restart Claude Desktop. The first call prints your auto-generated key — paste it into `env.TENPO_API_KEY` to keep using the same one across restarts:
257
258
 
258
259
  ```json
259
260
  {
@@ -276,6 +277,8 @@ Restart Claude Desktop. The first call prints your key — paste it into `env.TE
276
277
  claude mcp add tenpo --command "npx -y @tenpo/mcp"
277
278
  ```
278
279
 
280
+ The first call auto-issues your key. Add it to the env if you want it persisted across machines.
281
+
279
282
  </details>
280
283
 
281
284
  <details>
@@ -295,12 +298,23 @@ Settings → MCP → Add new global MCP server:
295
298
  }
296
299
  ```
297
300
 
301
+ Leave `TENPO_API_KEY` blank on first run — it'll be auto-issued and printed. Then paste it in.
302
+
298
303
  </details>
299
304
 
300
305
  <details>
301
- <summary><b>Codex, ChatGPT Desktop, Hermes, OpenClaw, or any MCP-compatible host</b></summary>
306
+ <summary><b>Codex · OpenClaw · Hermes · or any MCP-compatible host</b></summary>
307
+
308
+ Standard stdio transport. Point the client at `npx -y @tenpo/mcp`. The package is a small stdio↔HTTPS proxy — works in any MCP host.
302
309
 
303
- Standard stdio transport. Point the client at `npx -y @tenpo/mcp` with `TENPO_API_KEY` in env. The MCP package is a 15 KB stdio↔HTTPS proxy — works anywhere.
310
+ You don't need to provide an API key on first run. The MCP package will:
311
+
312
+ 1. See no `TENPO_API_KEY` in env
313
+ 2. Call the public `/api/v1/connect/issue-key` endpoint
314
+ 3. Print your new key to stderr in a framed banner
315
+ 4. Use it for the rest of the session
316
+
317
+ Save the key from that banner into `env.TENPO_API_KEY` so subsequent runs reuse it (otherwise a new key is issued each time).
304
318
 
305
319
  </details>
306
320
 
@@ -312,25 +326,27 @@ Once installed, just talk to your AI as you normally would. Say *"connect my sto
312
326
 
313
327
  Tenpo supports any storefront. Just say which one you're on:
314
328
 
315
- | Native, paste-token (90 seconds) | Native OAuth (3 min) | Custom adapters (5 min) | Anything else |
329
+ | Native, paste-token (90 sec) | Native OAuth (3 min) | Custom adapters (5 min) | Anything else |
316
330
  |---|---|---|---|
317
331
  | Shopify, WooCommerce | Amazon, Etsy | Squarespace, Wix, BigCommerce, Magento, Adobe Commerce, Salesforce Commerce Cloud, Webflow | CSV / JSON import — accepts Shopify, Woo, and Stripe export formats as-is |
318
332
 
319
- After your store connects, layer in the platforms that matter to you — Klaviyo, Mailchimp, Omnisend, Meta Ads, Google Ads, TikTok Ads, Google Analytics 4, Stripe, Gorgias, Zendesk, Xero, QuickBooks, Slack, Telegram, WhatsApp, 40+ others. Each one is a one-line ask: *"connect my Klaviyo."*
333
+ After your store connects, layer in the platforms that matter to you — Klaviyo, Mailchimp, Omnisend, Meta Ads, Google Ads, TikTok Ads, Google Analytics 4, Stripe, Gorgias, Zendesk, Xero, QuickBooks, Slack, Telegram, WhatsApp, 30+ others. Each one is a one-line ask: *"connect my Klaviyo."*
320
334
 
321
335
  ---
322
336
 
323
337
  ## Pricing
324
338
 
325
- | Tier | Daily calls | Cost | What you get |
339
+ | Tier | Cap | Price | What you get |
326
340
  |---|---|---|---|
327
- | **Free** | 500 / day | $0 | Every tool. Every integration. 1 connected store. No expiry. No card. |
328
- | **Pro Monthly** | 5,000 / day | $19 / mo | Everything in Free, higher limits, priority support |
329
- | **Pro Yearly** | Unlimited | $190 / yr | Everything in Pro, no daily cap, save $38 |
341
+ | **Free** | 500 calls / **month** | $0 | Every tool. Every integration. 1 connected store. No expiry. No card. |
342
+ | **Pro Monthly** | **Unlimited** | $19 / month | Everything in Free with no monthly cap. |
343
+ | **Pro Yearly** | **Unlimited** | $190 / year | Same as Pro Monthly, save $38. |
344
+
345
+ Your same API key works across tiers — upgrade just lifts the cap server-side. When you hit the free-tier cap, every response includes a one-click upgrade link. Pay → cap lifts in seconds (Dodo Payments).
330
346
 
331
- Your same API key works across tiers — upgrade just changes the server-side limit. When you hit the free-tier cap, every response includes a one-click upgrade link. Pay tier bumps in seconds (Dodo Payments).
347
+ The monthly cap resets on the 1st (UTC). 500 calls is roughly 50–80 user messages a month enough to evaluate, plus comfortable light use.
332
348
 
333
- **You always pay for your AI's tokens. Tenpo runs zero LLMs on our side** — every analytical tool is deterministic SQL or HTTP. That's why the free tier is genuinely free.
349
+ **You always pay for your AI's tokens. Tenpo runs no LLM in the analytical path on our side** — every analytical tool is deterministic SQL or HTTP. That's why the free tier is genuinely free.
334
350
 
335
351
  ---
336
352
 
@@ -338,12 +354,12 @@ Your same API key works across tiers — upgrade just changes the server-side li
338
354
 
339
355
  ```
340
356
  ┌──────────────────────────────────────────────────────────────────┐
341
- │ Claude Desktop · Cursor · Claude Code · ChatGPT · your host AI
357
+ │ Claude Desktop · Cursor · Claude Code · Codex · Hermes · etc.
342
358
  └──────────────────────┬───────────────────────────────────────────┘
343
359
  │ MCP protocol (stdio JSON-RPC)
344
360
 
345
361
  ┌──────────────────────────────────────────────────────────────────┐
346
- │ @tenpo/mcp (this package, 15 KB pure stdio↔HTTPS proxy)
362
+ │ @tenpo/mcp (this package — small stdio↔HTTPS proxy)
347
363
  └──────────────────────┬───────────────────────────────────────────┘
348
364
  │ HTTPS, Bearer tnp_live_*
349
365
 
@@ -351,9 +367,9 @@ Your same API key works across tiers — upgrade just changes the server-side li
351
367
  │ Tenpo backend │
352
368
  │ ├─ 229 deterministic tools (SQL helpers + HTTP integrations) │
353
369
  │ ├─ Per-merchant database (your data, isolated, encrypted) │
354
- │ ├─ Background syncs every 15 min (Klaviyo, Meta, GA4, Stripe…)
355
- │ ├─ Heartbeat monitors (revenue, stock, supplier, churn, ads…)
356
- │ └─ K-anonymous network telemetry (peer benchmarks, k≥3)
370
+ │ ├─ Background syncs every 15 min (only for connected merchants)
371
+ │ ├─ Background watchers (revenue, stock, supplier, churn, ads…)
372
+ │ └─ Anonymous network telemetry (peer benchmarks, k≥3 merchants)
357
373
  └──────────────────────────────────────────────────────────────────┘
358
374
  ```
359
375
 
@@ -366,7 +382,7 @@ Your AI does the synthesis. Tenpo provides the synapses.
366
382
  - **Your data is yours.** Per-merchant database, isolated from every other merchant. No cross-tenant queries are possible.
367
383
  - **Network telemetry is anonymous.** When Tenpo learns from cross-merchant patterns (e.g. "what most stores in your category approve"), merchant IDs are salt-hashed irreversibly. Free-text fields (email, phone, $ amounts, IDs, API tokens) are stripped to placeholders before any aggregation.
368
384
  - **K-anonymity (k≥3).** No stat surfaces until at least 3 distinct merchants contributed to it. You're never the only data point.
369
- - **No LLM on the analytical path.** Your data doesn't get sent to any model — Tenpo runs SQL and returns rows. Your AI (Claude, Cursor, etc.) sees the rows and writes a sentence.
385
+ - **No LLM on the analytical path.** Your data isn't sent to a model — Tenpo runs SQL and returns rows. Your AI host (Claude, Cursor, etc.) sees the rows and writes a sentence.
370
386
  - **Retention.** Raw events expire after 90 days. Aggregates kept indefinitely (already anonymised).
371
387
 
372
388
  ---
@@ -403,18 +419,17 @@ You don't need to know which tool runs. You don't need to learn a syntax. **Just
403
419
 
404
420
  ## Status
405
421
 
406
- - Production. Live at **[tenpo.ai](https://tenpo.ai)**.
407
- - Sub-10ms p50 latency on analytical tools (verified on multi-gigabyte stores).
408
- - 45+ platform integrations.
409
- - K-anonymous network intelligence with peer benchmarks.
410
- - Standard Webhooks signature verification + idempotent billing flow.
422
+ - 🟢 Backend live at `api.tenpo.ai`
423
+ - 🟢 Sub-10ms p50 latency on analytical tools (verified live)
424
+ - 🟢 47 platform integrations
425
+ - 🟢 Anonymous network intelligence with peer benchmarks
426
+ - 🟡 Public-facing site at tenpo.ai is in active development
411
427
 
412
428
  ---
413
429
 
414
430
  ## Support
415
431
 
416
432
  Questions, issues, feedback → **contact@tenpo.ai**
417
- Website → **[tenpo.ai](https://tenpo.ai)**
418
433
 
419
434
  ---
420
435
 
package/dist/index.js CHANGED
@@ -70,7 +70,7 @@ async function tenpoFetch(path, options = {}) {
70
70
  async function ensureApiKey() {
71
71
  if (TENPO_API_KEY)
72
72
  return;
73
- log("No TENPO_API_KEY set. Issuing free-tier key (500 calls/day, no expiry).");
73
+ log("No TENPO_API_KEY set auto-issuing a free key (500 calls/month, no card, no expiry).");
74
74
  try {
75
75
  // /api/v1/connect/issue-key is the current name; backend also accepts the
76
76
  // legacy /trial-key for back-compat with older MCP package versions.
@@ -80,17 +80,19 @@ async function ensureApiKey() {
80
80
  }));
81
81
  if (res.api_key) {
82
82
  TENPO_API_KEY = res.api_key;
83
+ const limit = res.monthly_call_limit ?? res.daily_call_limit ?? 500;
83
84
  log(`\n` +
84
85
  `╔══════════════════════════════════════════════════════════════════════╗\n` +
85
- `║ Tenpo MCP — Free Tier API Key Issued ║\n` +
86
+ `║ Tenpo — Free Key Issued ║\n` +
86
87
  `╠══════════════════════════════════════════════════════════════════════╣\n` +
87
- `║ Save this in your MCP config to keep using the same key: ║\n` +
88
+ `║ Add this to your MCP config so the same key is reused next time: ║\n` +
88
89
  `║ ║\n` +
89
90
  `║ TENPO_API_KEY=${(res.api_key ?? "").padEnd(54)}║\n` +
90
91
  `║ ║\n` +
91
- `║ Free tier: ${(res.daily_call_limit ?? 500).toString().padEnd(4)} calls/day, no expiry.${" ".repeat(28)}║\n` +
92
- `║ Upgrade for higher limits: ${(res.upgrade_url ?? "https://tenpo.ai/billing/upgrade").padEnd(42)}║\n` +
93
- `║ Connect your store: ${(res.connect_url ?? "https://tenpo.ai/connect").padEnd(42)}║\n` +
92
+ `║ Free tier: ${limit.toString().padEnd(4)} calls/month · resets the 1st (UTC) · no expiry.${" ".repeat(2)}║\n` +
93
+ `║ Upgrade ($19/mo unlimited): ${(res.upgrade_url ?? "https://tenpo.ai").padEnd(41)}║\n` +
94
+ `║ Connect your store: ${(res.connect_url ?? "https://tenpo.ai").padEnd(41)}║\n` +
95
+ `║ Questions? contact@tenpo.ai ║\n` +
94
96
  `╚══════════════════════════════════════════════════════════════════════╝\n`);
95
97
  }
96
98
  }
@@ -368,6 +370,43 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
368
370
  }));
369
371
  return { tools: [...TOOLS, ...dynamicEntries] };
370
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
+ // Type guard: try to pull data.chat_message safely
386
+ const r = result;
387
+ // Error path: backend returned ok:false. Show it cleanly.
388
+ if (r && r.ok === false) {
389
+ return {
390
+ content: [
391
+ { type: "text", text: `Error: ${r.error ?? "Tool execution failed"}` },
392
+ { type: "text", text: JSON.stringify(result, null, 2) },
393
+ ],
394
+ isError: true,
395
+ };
396
+ }
397
+ const chatMessage = r?.data?.chat_message;
398
+ if (typeof chatMessage === "string" && chatMessage.length > 0) {
399
+ // Primary: the chat-ready message. Secondary: structured JSON for introspection.
400
+ return {
401
+ content: [
402
+ { type: "text", text: chatMessage },
403
+ { type: "text", text: JSON.stringify(result, null, 2) },
404
+ ],
405
+ };
406
+ }
407
+ // No chat_message — fall back to pretty-printed JSON.
408
+ return formatToolResult(result);
409
+ }
371
410
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
372
411
  await ensureApiKey();
373
412
  const { name, arguments: args = {} } = request.params;
@@ -378,7 +417,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
378
417
  method: "POST",
379
418
  body: args,
380
419
  });
381
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
420
+ return formatToolResult(result);
382
421
  }
383
422
  case "tenpo_run_tool": {
384
423
  const a = args;
@@ -388,7 +427,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
388
427
  method: "POST",
389
428
  body: a.args ?? {},
390
429
  });
391
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
430
+ return formatToolResult(result);
392
431
  }
393
432
  case "tenpo_classify_intent": {
394
433
  const a = args;
@@ -447,7 +486,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
447
486
  if (!a.resource)
448
487
  throw new Error("resource name required");
449
488
  const result = await tenpoFetch(`/api/v1/resources/${encodeURIComponent(a.resource)}`);
450
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
489
+ return formatToolResult(result);
451
490
  }
452
491
  case "tenpo_get_prompt": {
453
492
  const a = args;
@@ -462,7 +501,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
462
501
  path += `?${params.toString()}`;
463
502
  }
464
503
  const result = await tenpoFetch(path);
465
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
504
+ return formatToolResult(result);
466
505
  }
467
506
  case "tenpo_list_prompts": {
468
507
  const a = args;
@@ -470,7 +509,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
470
509
  ? `/api/v1/prompts?q=${encodeURIComponent(a.q)}`
471
510
  : `/api/v1/prompts`;
472
511
  const result = await tenpoFetch(path);
473
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
512
+ return formatToolResult(result);
474
513
  }
475
514
  case "tenpo_connect_integration": {
476
515
  const a = args;
@@ -481,13 +520,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
481
520
  method: "POST",
482
521
  body: { integration_id: a.integration_id, credentials: a.credentials },
483
522
  });
484
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
523
+ return formatToolResult(result);
485
524
  }
486
525
  const result = await tenpoFetch("/api/v1/connect/start", {
487
526
  method: "POST",
488
527
  body: { integration_id: a.integration_id },
489
528
  });
490
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
529
+ return formatToolResult(result);
491
530
  }
492
531
  case "tenpo_remember": {
493
532
  const a = args;
@@ -498,7 +537,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
498
537
  method: "POST",
499
538
  body: { content, scope: a.scope ?? a.memory_type ?? "fact", mode: a.mode ?? "append" },
500
539
  });
501
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
540
+ return formatToolResult(result);
502
541
  }
503
542
  // tenpo_pattern_detect, tenpo_fetch_url, tenpo_write_md, tenpo_route_skills,
504
543
  // tenpo_overview cases DROPPED — host AI's native capabilities cover them.
@@ -513,7 +552,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
513
552
  throw new Error(`Unknown tool: ${name}. Use tenpo_route to discover available tools.`);
514
553
  }
515
554
  const result = await tenpoFetch(`/api/v1/tools/${encodeURIComponent(name)}`, { method: "POST", body: args });
516
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
555
+ return formatToolResult(result);
517
556
  }
518
557
  }
519
558
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenpo/mcp",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
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",