@sellhapi/mcp 0.1.3 → 0.1.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/dist/server.js +2 -0
- package/dist/tools/analytics.d.ts +5 -0
- package/dist/tools/analytics.js +22 -0
- package/dist/tools/commerce.js +39 -3
- package/dist/tools/studio.js +1 -1
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -12,6 +12,7 @@ const studio_js_1 = require("./tools/studio.js");
|
|
|
12
12
|
const commerce_js_1 = require("./tools/commerce.js");
|
|
13
13
|
const content_js_1 = require("./tools/content.js");
|
|
14
14
|
const intelligence_js_1 = require("./tools/intelligence.js");
|
|
15
|
+
const analytics_js_1 = require("./tools/analytics.js");
|
|
15
16
|
const index_js_1 = require("./resources/index.js");
|
|
16
17
|
function createMcpServer() {
|
|
17
18
|
const server = new mcp_js_1.McpServer({
|
|
@@ -22,6 +23,7 @@ function createMcpServer() {
|
|
|
22
23
|
(0, commerce_js_1.registerCommerceTools)(server);
|
|
23
24
|
(0, content_js_1.registerContentTools)(server);
|
|
24
25
|
(0, intelligence_js_1.registerIntelligenceTools)(server);
|
|
26
|
+
(0, analytics_js_1.registerAnalyticsTools)(server);
|
|
25
27
|
(0, index_js_1.registerResources)(server);
|
|
26
28
|
return server;
|
|
27
29
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Analytics tools — read-only access to pre-computed capability metrics.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerAnalyticsTools = registerAnalyticsTools;
|
|
7
|
+
const v4_1 = require("zod/v4");
|
|
8
|
+
const client_js_1 = require("../client.js");
|
|
9
|
+
const util_js_1 = require("../util.js");
|
|
10
|
+
function registerAnalyticsTools(server) {
|
|
11
|
+
server.registerTool("get_analytics", {
|
|
12
|
+
title: "Get Analytics",
|
|
13
|
+
description: "Get pre-computed analytics for this vendor. Returns revenue, transaction counts, and other metrics per capability for a given period. Use this to answer questions like 'what's my revenue this month', 'which capability earns the most', or 'how many orders have I had'. Metrics are computed on a schedule — call this before making business recommendations.",
|
|
14
|
+
annotations: { readOnlyHint: true },
|
|
15
|
+
inputSchema: {
|
|
16
|
+
period: v4_1.z.enum(["7d", "30d", "90d"]).optional().default("30d").describe("Time period for metrics (default: 30d)"),
|
|
17
|
+
},
|
|
18
|
+
}, async ({ period }) => (0, util_js_1.safeCall)(async () => {
|
|
19
|
+
const data = await (0, client_js_1.get)(`/api/mcp/analytics?period=${period}`);
|
|
20
|
+
return JSON.stringify(data, null, 2);
|
|
21
|
+
}));
|
|
22
|
+
}
|
package/dist/tools/commerce.js
CHANGED
|
@@ -72,10 +72,30 @@ function registerCommerceTools(server) {
|
|
|
72
72
|
const data = await (0, client_js_1.get)("/api/mcp/appointments/services");
|
|
73
73
|
return JSON.stringify(data.services, null, 2);
|
|
74
74
|
}));
|
|
75
|
+
// ── Categories ────────────────────────────────────────────────────────────
|
|
76
|
+
server.registerTool("list_categories", {
|
|
77
|
+
title: "List Categories",
|
|
78
|
+
description: "List all product categories for this vendor. Call this before create_product or update_product to get valid categoryId values. Returns id, name, description for each category.",
|
|
79
|
+
annotations: { readOnlyHint: true },
|
|
80
|
+
}, async () => (0, util_js_1.safeCall)(async () => {
|
|
81
|
+
const data = await (0, client_js_1.get)("/api/mcp/categories");
|
|
82
|
+
return JSON.stringify(data.categories, null, 2);
|
|
83
|
+
}));
|
|
84
|
+
server.registerTool("create_category", {
|
|
85
|
+
title: "Create Category",
|
|
86
|
+
description: "Create a product category. Returns the new category id — use it immediately in create_product or update_product. Returns a 409 conflict (with the existing id) if a category with the same name already exists — use that id instead of creating a duplicate.",
|
|
87
|
+
inputSchema: {
|
|
88
|
+
name: v4_1.z.string().describe("Category name e.g. 'Clothing', 'Baked Goods'"),
|
|
89
|
+
description: v4_1.z.string().optional().describe("Optional description"),
|
|
90
|
+
},
|
|
91
|
+
}, async (input) => (0, util_js_1.safeCall)(async () => {
|
|
92
|
+
const data = await (0, client_js_1.post)("/api/mcp/categories", input);
|
|
93
|
+
return JSON.stringify(data, null, 2);
|
|
94
|
+
}));
|
|
75
95
|
// ── Write: Create product ─────────────────────────────────────────────────
|
|
76
96
|
server.registerTool("create_product", {
|
|
77
97
|
title: "Create Product",
|
|
78
|
-
description: "Create a physical or digital product. Call list_capabilities first to confirm the relevant capability (physical_products or digital_products) is active. Prices must be in kobo (₦1 = 100 kobo). imageUrl is optional
|
|
98
|
+
description: "Create a physical or digital product. Call list_capabilities first to confirm the relevant capability (physical_products or digital_products) is active. Call list_categories first to get a valid categoryId — supplying an invalid categoryId returns a 400 error. Prices must be in kobo (₦1 = 100 kobo). imageUrl is optional.",
|
|
79
99
|
inputSchema: {
|
|
80
100
|
name: v4_1.z.string().describe("Product name"),
|
|
81
101
|
description: v4_1.z.string().optional().describe("Product description"),
|
|
@@ -83,11 +103,27 @@ function registerCommerceTools(server) {
|
|
|
83
103
|
type: v4_1.z.enum(["physical", "digital"]).optional().default("physical").describe("Product type — physical (default) or digital"),
|
|
84
104
|
stock: v4_1.z.number().int().min(0).optional().describe("Initial stock quantity (0 = out of stock). Omit for untracked stock."),
|
|
85
105
|
imageUrl: v4_1.z.string().optional().describe("External image URL for the product"),
|
|
106
|
+
categoryId: v4_1.z.string().uuid().optional().describe("Category ID from list_categories. Omit if no category applies."),
|
|
86
107
|
},
|
|
87
108
|
}, async (input) => (0, util_js_1.safeCall)(async () => {
|
|
88
109
|
const data = await (0, client_js_1.post)("/api/mcp/products", input);
|
|
89
110
|
return JSON.stringify(data, null, 2);
|
|
90
111
|
}));
|
|
112
|
+
// ── Write: Update product ─────────────────────────────────────────────────
|
|
113
|
+
server.registerTool("update_product", {
|
|
114
|
+
title: "Update Product",
|
|
115
|
+
description: "Update an existing product's name, description, category, or image. Call list_products to get the productId, list_categories to get a valid categoryId. Only fields provided are updated — omitted fields stay unchanged. Pass categoryId: null to remove the category.",
|
|
116
|
+
inputSchema: {
|
|
117
|
+
productId: v4_1.z.string().uuid().describe("Product ID from list_products"),
|
|
118
|
+
name: v4_1.z.string().optional().describe("New product name"),
|
|
119
|
+
description: v4_1.z.string().optional().describe("New product description"),
|
|
120
|
+
categoryId: v4_1.z.string().uuid().nullable().optional().describe("Category ID from list_categories, or null to remove category"),
|
|
121
|
+
imageUrl: v4_1.z.string().nullable().optional().describe("New image URL, or null to clear"),
|
|
122
|
+
},
|
|
123
|
+
}, async ({ productId, ...rest }) => (0, util_js_1.safeCall)(async () => {
|
|
124
|
+
const data = await (0, client_js_1.patch)(`/api/mcp/products/${productId}`, rest);
|
|
125
|
+
return JSON.stringify(data, null, 2);
|
|
126
|
+
}));
|
|
91
127
|
// ── Write: Create event ───────────────────────────────────────────────────
|
|
92
128
|
server.registerTool("create_event", {
|
|
93
129
|
title: "Create Event",
|
|
@@ -181,13 +217,13 @@ function registerCommerceTools(server) {
|
|
|
181
217
|
// ── Write: Create form ───────────────────────────────────────────────────
|
|
182
218
|
server.registerTool("create_form", {
|
|
183
219
|
title: "Create Form",
|
|
184
|
-
description: "Create a published storefront form. Returns the form ID — use it in useContentForm(formId) and useSubmitForm(formId) in storefront code. Call list_capabilities first to confirm content capability is active. Field types: text, email, phone, textarea, select, checkbox, date, number.",
|
|
220
|
+
description: "Create a published storefront form. Returns the form ID — use it in useContentForm(formId) and useSubmitForm(formId) in storefront code. Call list_capabilities first to confirm content capability is active. Field types: text, email, phone, textarea, select, radio, checkbox, date, number, file.",
|
|
185
221
|
inputSchema: {
|
|
186
222
|
title: v4_1.z.string().describe("Form name e.g. 'Contact Us'"),
|
|
187
223
|
description: v4_1.z.string().optional(),
|
|
188
224
|
fields: v4_1.z.array(v4_1.z.object({
|
|
189
225
|
label: v4_1.z.string().describe("Field label shown to the user"),
|
|
190
|
-
type: v4_1.z.enum(["text", "email", "phone", "textarea", "select", "checkbox", "date", "number"]).describe("Field input type"),
|
|
226
|
+
type: v4_1.z.enum(["text", "email", "phone", "textarea", "select", "radio", "checkbox", "date", "number", "file"]).describe("Field input type"),
|
|
191
227
|
required: v4_1.z.boolean().optional().default(false),
|
|
192
228
|
placeholder: v4_1.z.string().optional(),
|
|
193
229
|
options: v4_1.z.array(v4_1.z.string()).optional().describe("Options for select fields"),
|
package/dist/tools/studio.js
CHANGED
|
@@ -124,7 +124,7 @@ function registerStudioTools(server) {
|
|
|
124
124
|
// ── Push code (zero credits) ───────────────────────────────────────────────
|
|
125
125
|
server.registerTool("push_code", {
|
|
126
126
|
title: "Push Code",
|
|
127
|
-
description: "Push client-generated React code to a project. Runs BuildGuard validation + esbuild bundling and returns a preview URL. ZERO AI credit cost — you generate the code, SellHapi only builds it. CRITICAL RULES: (1) import ONLY from @sellhapi/studio-runtime and react — NO external packages; (2) every top-level JSX section must have data-region, data-label, data-scope attributes; (3)
|
|
127
|
+
description: "Push client-generated React code to a project. Runs BuildGuard validation + esbuild bundling and returns a preview URL. ZERO AI credit cost — you generate the code, SellHapi only builds it. CRITICAL RULES: (1) import ONLY from @sellhapi/studio-runtime and react — NO external packages; (2) every top-level JSX section must have data-region, data-label, data-scope attributes; (3) use inline React style objects for ALL styling — Tailwind is NOT available; (4) NO localStorage/sessionStorage for state management — EXCEPTION: window.location.href IS required and allowed for payment redirects (all commerce hooks return { paymentLink } — redirect with window.location.href = result.paymentLink); (5) prices via priceKobo / 100 — never hardcode currency. Call get_build_rules or get_runtime_hooks for full reference.",
|
|
128
128
|
inputSchema: {
|
|
129
129
|
projectId: v4_1.z.string().describe("Studio project ID"),
|
|
130
130
|
files: v4_1.z.record(v4_1.z.string(), v4_1.z.string()).describe("Map of filename → code content. Must include App.tsx as entry point."),
|