verbo-mcp-server 0.1.4 → 0.2.0
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/client.js +11 -33
- package/dist/client.js.map +1 -1
- package/dist/index.js +0 -20
- package/dist/index.js.map +1 -1
- package/dist/setup-tools.js +5 -26
- package/dist/setup-tools.js.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +9 -12
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +12 -41
- package/src/index.ts +4 -27
- package/src/setup-tools.ts +5 -25
- package/src/tools.ts +9 -12
package/dist/client.js
CHANGED
|
@@ -7,43 +7,21 @@ class VerboClient {
|
|
|
7
7
|
apiKey;
|
|
8
8
|
constructor(apiKey, baseUrl) {
|
|
9
9
|
this.apiKey = apiKey;
|
|
10
|
-
this.baseUrl = (baseUrl || "https://
|
|
10
|
+
this.baseUrl = (baseUrl || "https://verbolab.co").replace(/\/$/, "");
|
|
11
11
|
}
|
|
12
12
|
async request(path, options = {}) {
|
|
13
13
|
const url = `${this.baseUrl}/api/v1${path}`;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
catch (err) {
|
|
26
|
-
throw new Error(`Could not connect to Verbo API at ${this.baseUrl}. Check your internet connection or VERBO_API_URL setting.`);
|
|
27
|
-
}
|
|
28
|
-
let data;
|
|
29
|
-
try {
|
|
30
|
-
data = await res.json();
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
throw new Error(`Verbo API returned invalid response (HTTP ${res.status}). The server may be temporarily unavailable — try again in a moment.`);
|
|
34
|
-
}
|
|
14
|
+
const res = await fetch(url, {
|
|
15
|
+
...options,
|
|
16
|
+
headers: {
|
|
17
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
...options.headers,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
const data = await res.json();
|
|
35
23
|
if (!res.ok) {
|
|
36
|
-
|
|
37
|
-
if (res.status === 401) {
|
|
38
|
-
throw new Error(`API key is invalid or revoked. Create a new key at ${this.baseUrl}/developers`);
|
|
39
|
-
}
|
|
40
|
-
if (res.status === 403) {
|
|
41
|
-
throw new Error(`Subscription expired or inactive. Upgrade at ${this.baseUrl}/settings/billing — ${errorMsg}`);
|
|
42
|
-
}
|
|
43
|
-
if (res.status === 429) {
|
|
44
|
-
throw new Error(`Rate limit exceeded. ${errorMsg}`);
|
|
45
|
-
}
|
|
46
|
-
throw new Error(`Verbo API error (${res.status}): ${errorMsg}`);
|
|
24
|
+
throw new Error(`Verbo API error (${res.status}): ${data.error || "Unknown error"}`);
|
|
47
25
|
}
|
|
48
26
|
return data;
|
|
49
27
|
}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;AAEpC,MAAa,WAAW;IACd,OAAO,CAAS;IAChB,MAAM,CAAS;IAEvB,YAAY,MAAc,EAAE,OAAgB;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;AAEpC,MAAa,WAAW;IACd,OAAO,CAAS;IAChB,MAAM,CAAS;IAEvB,YAAY,MAAc,EAAE,OAAgB;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,IAAI,qBAAqB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,UAAuB,EAAE;QAC3D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,UAAU,IAAI,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,GAAG,OAAO;YACV,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACxC,cAAc,EAAE,kBAAkB;gBAClC,GAAG,OAAO,CAAC,OAAO;aACnB;SACF,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,oBAAoB,GAAG,CAAC,MAAM,MAAO,IAA2B,CAAC,KAAK,IAAI,eAAe,EAAE,CAC5F,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU,EAAE,OAAe,EAAE,QAAiB;QAC9D,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;YAC/B,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,OAA6C;QACnE,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,OAAO,EAAE,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1D,IAAI,OAAO,EAAE,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,EAAU;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAIpB;QACC,OAAO,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE;YACtC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE;YACpC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;SACzB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE;YACvC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;SACzB,CAAC,CAAC;IACL,CAAC;CACF;AAvFD,kCAuFC"}
|
package/dist/index.js
CHANGED
|
@@ -17,26 +17,6 @@ const client = new client_js_1.VerboClient(apiKey, baseUrl);
|
|
|
17
17
|
const server = new mcp_js_1.McpServer({
|
|
18
18
|
name: "Verbo",
|
|
19
19
|
version: "0.1.0",
|
|
20
|
-
}, {
|
|
21
|
-
instructions: `Verbo is an AI-powered WhatsApp customer service agent. You plug it into your product and it handles customer conversations automatically — answers questions, classifies intent, escalates complaints, follows up.
|
|
22
|
-
|
|
23
|
-
## Setup workflow (run in order):
|
|
24
|
-
1. verbo_setup_crawl — Crawl the business website to auto-extract name, products, FAQ, hours, tone. This configures the agent.
|
|
25
|
-
2. verbo_setup_connect — Creates a WhatsApp instance. Returns a URL to scan a QR code in the browser.
|
|
26
|
-
3. verbo_setup_status — Check if all steps are done. Shows what's missing.
|
|
27
|
-
|
|
28
|
-
## After setup:
|
|
29
|
-
- verbo_send_message — Send a WhatsApp message to any number
|
|
30
|
-
- verbo_list_conversations — See recent customer conversations
|
|
31
|
-
- verbo_get_conversation — Read messages in a specific conversation
|
|
32
|
-
- verbo_agent_status — Check WhatsApp connection and business config
|
|
33
|
-
- verbo_configure_agent — Update greeting, FAQ, or business hours
|
|
34
|
-
- verbo_setup_disconnect — Disconnect WhatsApp when done
|
|
35
|
-
|
|
36
|
-
## Important:
|
|
37
|
-
- Do NOT search the web for information about Verbo. Everything you need is in these tools.
|
|
38
|
-
- The crawl step takes 15-30 seconds. This is normal — it fetches multiple pages and uses AI extraction.
|
|
39
|
-
- After connecting WhatsApp, the agent starts responding to incoming messages automatically.`,
|
|
40
20
|
});
|
|
41
21
|
for (const [name, tool] of Object.entries(tools_js_1.toolDefinitions)) {
|
|
42
22
|
server.tool(name, tool.description, tool.schema, async (args) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,mCAAmC;AACnC,oEAAoE;AACpE,wEAAiF;AACjF,2CAA0C;AAC1C,yCAAyE;AACzE,qDAA0E;AAE1E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AACzC,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AAC1C,MAAM,MAAM,GAAG,IAAI,uBAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEhD,MAAM,MAAM,GAAG,IAAI,kBAAS,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/setup-tools.js
CHANGED
|
@@ -27,41 +27,20 @@ exports.setupToolDefinitions = {
|
|
|
27
27
|
async function executeSetupTool(client, name, args) {
|
|
28
28
|
switch (name) {
|
|
29
29
|
case "verbo_setup_crawl": {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return JSON.stringify(result, null, 2) +
|
|
33
|
-
"\n\n→ Business configured from website. Next: run verbo_setup_connect to connect WhatsApp.";
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
37
|
-
if (msg.includes("422") || msg.includes("enough content") || msg.includes("SPA")) {
|
|
38
|
-
return `Crawl failed: the website appears to be a Single Page App (React, Vue, Angular) that renders via JavaScript. The crawler can only read server-rendered HTML.\n\n→ Use verbo_configure_agent instead to set up the agent manually. Ask the user about their business and set greeting_message, faq (array of {question, answer}), and business_hours.`;
|
|
39
|
-
}
|
|
40
|
-
throw err;
|
|
41
|
-
}
|
|
30
|
+
const result = await client.setupCrawl(args.url);
|
|
31
|
+
return JSON.stringify(result, null, 2);
|
|
42
32
|
}
|
|
43
33
|
case "verbo_setup_connect": {
|
|
44
34
|
const result = await client.setupConnect();
|
|
45
|
-
|
|
46
|
-
const connectUrl = data.connectUrl || "";
|
|
47
|
-
return JSON.stringify(result, null, 2) +
|
|
48
|
-
`\n\n→ WhatsApp instance created. IMPORTANT: Tell the user to open ${connectUrl} in their browser and scan the QR code with their phone. After scanning, run verbo_setup_status to confirm the connection.`;
|
|
35
|
+
return JSON.stringify(result, null, 2);
|
|
49
36
|
}
|
|
50
37
|
case "verbo_setup_status": {
|
|
51
38
|
const result = await client.setupStatus();
|
|
52
|
-
|
|
53
|
-
const ready = data.ready;
|
|
54
|
-
if (ready) {
|
|
55
|
-
return JSON.stringify(result, null, 2) +
|
|
56
|
-
"\n\n→ All set! The AI agent is live and will respond to incoming WhatsApp messages automatically. Use verbo_send_message to send a test message.";
|
|
57
|
-
}
|
|
58
|
-
return JSON.stringify(result, null, 2) +
|
|
59
|
-
"\n\n→ Setup incomplete. Check the steps above and run the missing ones.";
|
|
39
|
+
return JSON.stringify(result, null, 2);
|
|
60
40
|
}
|
|
61
41
|
case "verbo_setup_disconnect": {
|
|
62
42
|
const result = await client.setupDisconnect();
|
|
63
|
-
return JSON.stringify(result, null, 2)
|
|
64
|
-
"\n\n→ WhatsApp disconnected. The phone number is free to use elsewhere.";
|
|
43
|
+
return JSON.stringify(result, null, 2);
|
|
65
44
|
}
|
|
66
45
|
default:
|
|
67
46
|
return JSON.stringify({ error: `Unknown setup tool: ${name}` });
|
package/dist/setup-tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-tools.js","sourceRoot":"","sources":["../src/setup-tools.ts"],"names":[],"mappings":";;;AA+BA,
|
|
1
|
+
{"version":3,"file":"setup-tools.js","sourceRoot":"","sources":["../src/setup-tools.ts"],"names":[],"mappings":";;;AA+BA,4CAyBC;AAxDD,yCAAyC;AACzC,6BAAwB;AAGX,QAAA,oBAAoB,GAAG;IAClC,iBAAiB,EAAE;QACjB,WAAW,EACT,mNAAmN;QACrN,MAAM,EAAE;YACN,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;SACjE;KACF;IACD,mBAAmB,EAAE;QACnB,WAAW,EACT,+QAA+Q;QACjR,MAAM,EAAE,EAAE;KACX;IACD,kBAAkB,EAAE;QAClB,WAAW,EACT,uHAAuH;QACzH,MAAM,EAAE,EAAE;KACX;IACD,sBAAsB,EAAE;QACtB,WAAW,EACT,kKAAkK;QACpK,MAAM,EAAE,EAAE;KACX;CACO,CAAC;AAIJ,KAAK,UAAU,gBAAgB,CACpC,MAAmB,EACnB,IAAY,EACZ,IAA6B;IAE7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,mBAAmB,CAAC,CAAC,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAa,CAAC,CAAC;YAC3D,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,qBAAqB,CAAC,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC1B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,wBAAwB,CAAC,CAAC,CAAC;YAC9B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;QACD;YACE,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,uBAAuB,IAAI,EAAE,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export declare const toolDefinitions: {
|
|
|
30
30
|
readonly schema: {};
|
|
31
31
|
};
|
|
32
32
|
readonly verbo_configure_agent: {
|
|
33
|
-
readonly description: "Configure the AI agent behavior.
|
|
33
|
+
readonly description: "Configure the AI agent behavior. Set greeting message, FAQ, and business hours.";
|
|
34
34
|
readonly schema: {
|
|
35
35
|
readonly greeting_message: z.ZodOptional<z.ZodString>;
|
|
36
36
|
readonly faq: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
package/dist/tools.js
CHANGED
|
@@ -42,23 +42,23 @@ exports.toolDefinitions = {
|
|
|
42
42
|
schema: {},
|
|
43
43
|
},
|
|
44
44
|
verbo_configure_agent: {
|
|
45
|
-
description: "Configure the AI agent behavior.
|
|
45
|
+
description: "Configure the AI agent behavior. Set greeting message, FAQ, and business hours.",
|
|
46
46
|
schema: {
|
|
47
47
|
greeting_message: zod_1.z
|
|
48
48
|
.string()
|
|
49
49
|
.optional()
|
|
50
|
-
.describe("Greeting message
|
|
50
|
+
.describe("Greeting message for new customers"),
|
|
51
51
|
faq: zod_1.z
|
|
52
52
|
.array(zod_1.z.object({
|
|
53
|
-
question: zod_1.z.string()
|
|
54
|
-
answer: zod_1.z.string()
|
|
53
|
+
question: zod_1.z.string(),
|
|
54
|
+
answer: zod_1.z.string(),
|
|
55
55
|
}))
|
|
56
56
|
.optional()
|
|
57
|
-
.describe("
|
|
57
|
+
.describe("Frequently asked questions"),
|
|
58
58
|
business_hours: zod_1.z
|
|
59
59
|
.record(zod_1.z.string(), zod_1.z.string())
|
|
60
60
|
.optional()
|
|
61
|
-
.describe("Business hours
|
|
61
|
+
.describe("Business hours (e.g. { monday: '9:00-18:00' })"),
|
|
62
62
|
},
|
|
63
63
|
},
|
|
64
64
|
};
|
|
@@ -66,16 +66,14 @@ async function executeTool(client, name, args) {
|
|
|
66
66
|
switch (name) {
|
|
67
67
|
case "verbo_send_message": {
|
|
68
68
|
const result = await client.sendMessage(args.to, args.message, args.image_url);
|
|
69
|
-
return JSON.stringify(result, null, 2)
|
|
70
|
-
"\n\n→ Message sent. Use verbo_list_conversations to see the conversation.";
|
|
69
|
+
return JSON.stringify(result, null, 2);
|
|
71
70
|
}
|
|
72
71
|
case "verbo_list_conversations": {
|
|
73
72
|
const result = await client.listConversations({
|
|
74
73
|
status: args.status,
|
|
75
74
|
limit: args.limit,
|
|
76
75
|
});
|
|
77
|
-
return JSON.stringify(result, null, 2)
|
|
78
|
-
"\n\n→ Use verbo_get_conversation with a conversation ID to see full messages.";
|
|
76
|
+
return JSON.stringify(result, null, 2);
|
|
79
77
|
}
|
|
80
78
|
case "verbo_get_conversation": {
|
|
81
79
|
const result = await client.getConversation(args.conversation_id);
|
|
@@ -91,8 +89,7 @@ async function executeTool(client, name, args) {
|
|
|
91
89
|
faqData: args.faq,
|
|
92
90
|
businessHours: args.business_hours,
|
|
93
91
|
});
|
|
94
|
-
return JSON.stringify(result, null, 2)
|
|
95
|
-
"\n\n→ Agent updated. Use verbo_setup_status to verify the full setup.";
|
|
92
|
+
return JSON.stringify(result, null, 2);
|
|
96
93
|
}
|
|
97
94
|
default:
|
|
98
95
|
return JSON.stringify({ error: `Unknown tool: ${name}` });
|
package/dist/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":";;;AA0EA,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -6,55 +6,26 @@ export class VerboClient {
|
|
|
6
6
|
|
|
7
7
|
constructor(apiKey: string, baseUrl?: string) {
|
|
8
8
|
this.apiKey = apiKey;
|
|
9
|
-
this.baseUrl = (baseUrl || "https://
|
|
9
|
+
this.baseUrl = (baseUrl || "https://verbolab.co").replace(/\/$/, "");
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
private async request(path: string, options: RequestInit = {}): Promise<unknown> {
|
|
13
13
|
const url = `${this.baseUrl}/api/v1${path}`;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
} catch (err) {
|
|
25
|
-
throw new Error(
|
|
26
|
-
`Could not connect to Verbo API at ${this.baseUrl}. Check your internet connection or VERBO_API_URL setting.`
|
|
27
|
-
);
|
|
28
|
-
}
|
|
14
|
+
const res = await fetch(url, {
|
|
15
|
+
...options,
|
|
16
|
+
headers: {
|
|
17
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
...options.headers,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
data = await res.json();
|
|
33
|
-
} catch {
|
|
23
|
+
const data = await res.json();
|
|
24
|
+
if (!res.ok) {
|
|
34
25
|
throw new Error(
|
|
35
|
-
`Verbo API
|
|
26
|
+
`Verbo API error (${res.status}): ${(data as { error?: string }).error || "Unknown error"}`
|
|
36
27
|
);
|
|
37
28
|
}
|
|
38
|
-
|
|
39
|
-
if (!res.ok) {
|
|
40
|
-
const errorMsg = (data as { error?: string }).error || "Unknown error";
|
|
41
|
-
if (res.status === 401) {
|
|
42
|
-
throw new Error(
|
|
43
|
-
`API key is invalid or revoked. Create a new key at ${this.baseUrl}/developers`
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
if (res.status === 403) {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`Subscription expired or inactive. Upgrade at ${this.baseUrl}/settings/billing — ${errorMsg}`
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
if (res.status === 429) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
`Rate limit exceeded. ${errorMsg}`
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
throw new Error(`Verbo API error (${res.status}): ${errorMsg}`);
|
|
57
|
-
}
|
|
58
29
|
return data;
|
|
59
30
|
}
|
|
60
31
|
|
package/src/index.ts
CHANGED
|
@@ -15,33 +15,10 @@ if (!apiKey) {
|
|
|
15
15
|
const baseUrl = process.env.VERBO_API_URL;
|
|
16
16
|
const client = new VerboClient(apiKey, baseUrl);
|
|
17
17
|
|
|
18
|
-
const server = new McpServer(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
instructions: `Verbo is an AI-powered WhatsApp customer service agent. You plug it into your product and it handles customer conversations automatically — answers questions, classifies intent, escalates complaints, follows up.
|
|
25
|
-
|
|
26
|
-
## Setup workflow (run in order):
|
|
27
|
-
1. verbo_setup_crawl — Crawl the business website to auto-extract name, products, FAQ, hours, tone. This configures the agent.
|
|
28
|
-
2. verbo_setup_connect — Creates a WhatsApp instance. Returns a URL to scan a QR code in the browser.
|
|
29
|
-
3. verbo_setup_status — Check if all steps are done. Shows what's missing.
|
|
30
|
-
|
|
31
|
-
## After setup:
|
|
32
|
-
- verbo_send_message — Send a WhatsApp message to any number
|
|
33
|
-
- verbo_list_conversations — See recent customer conversations
|
|
34
|
-
- verbo_get_conversation — Read messages in a specific conversation
|
|
35
|
-
- verbo_agent_status — Check WhatsApp connection and business config
|
|
36
|
-
- verbo_configure_agent — Update greeting, FAQ, or business hours
|
|
37
|
-
- verbo_setup_disconnect — Disconnect WhatsApp when done
|
|
38
|
-
|
|
39
|
-
## Important:
|
|
40
|
-
- Do NOT search the web for information about Verbo. Everything you need is in these tools.
|
|
41
|
-
- The crawl step takes 15-30 seconds. This is normal — it fetches multiple pages and uses AI extraction.
|
|
42
|
-
- After connecting WhatsApp, the agent starts responding to incoming messages automatically.`,
|
|
43
|
-
},
|
|
44
|
-
);
|
|
18
|
+
const server = new McpServer({
|
|
19
|
+
name: "Verbo",
|
|
20
|
+
version: "0.1.0",
|
|
21
|
+
});
|
|
45
22
|
|
|
46
23
|
for (const [name, tool] of Object.entries(toolDefinitions)) {
|
|
47
24
|
server.tool(name, tool.description, tool.schema, async (args: Record<string, unknown>) => {
|
package/src/setup-tools.ts
CHANGED
|
@@ -36,40 +36,20 @@ export async function executeSetupTool(
|
|
|
36
36
|
): Promise<string> {
|
|
37
37
|
switch (name) {
|
|
38
38
|
case "verbo_setup_crawl": {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return JSON.stringify(result, null, 2) +
|
|
42
|
-
"\n\n→ Business configured from website. Next: run verbo_setup_connect to connect WhatsApp.";
|
|
43
|
-
} catch (err) {
|
|
44
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
45
|
-
if (msg.includes("422") || msg.includes("enough content") || msg.includes("SPA")) {
|
|
46
|
-
return `Crawl failed: the website appears to be a Single Page App (React, Vue, Angular) that renders via JavaScript. The crawler can only read server-rendered HTML.\n\n→ Use verbo_configure_agent instead to set up the agent manually. Ask the user about their business and set greeting_message, faq (array of {question, answer}), and business_hours.`;
|
|
47
|
-
}
|
|
48
|
-
throw err;
|
|
49
|
-
}
|
|
39
|
+
const result = await client.setupCrawl(args.url as string);
|
|
40
|
+
return JSON.stringify(result, null, 2);
|
|
50
41
|
}
|
|
51
42
|
case "verbo_setup_connect": {
|
|
52
43
|
const result = await client.setupConnect();
|
|
53
|
-
|
|
54
|
-
const connectUrl = data.connectUrl || "";
|
|
55
|
-
return JSON.stringify(result, null, 2) +
|
|
56
|
-
`\n\n→ WhatsApp instance created. IMPORTANT: Tell the user to open ${connectUrl} in their browser and scan the QR code with their phone. After scanning, run verbo_setup_status to confirm the connection.`;
|
|
44
|
+
return JSON.stringify(result, null, 2);
|
|
57
45
|
}
|
|
58
46
|
case "verbo_setup_status": {
|
|
59
47
|
const result = await client.setupStatus();
|
|
60
|
-
|
|
61
|
-
const ready = data.ready;
|
|
62
|
-
if (ready) {
|
|
63
|
-
return JSON.stringify(result, null, 2) +
|
|
64
|
-
"\n\n→ All set! The AI agent is live and will respond to incoming WhatsApp messages automatically. Use verbo_send_message to send a test message.";
|
|
65
|
-
}
|
|
66
|
-
return JSON.stringify(result, null, 2) +
|
|
67
|
-
"\n\n→ Setup incomplete. Check the steps above and run the missing ones.";
|
|
48
|
+
return JSON.stringify(result, null, 2);
|
|
68
49
|
}
|
|
69
50
|
case "verbo_setup_disconnect": {
|
|
70
51
|
const result = await client.setupDisconnect();
|
|
71
|
-
return JSON.stringify(result, null, 2)
|
|
72
|
-
"\n\n→ WhatsApp disconnected. The phone number is free to use elsewhere.";
|
|
52
|
+
return JSON.stringify(result, null, 2);
|
|
73
53
|
}
|
|
74
54
|
default:
|
|
75
55
|
return JSON.stringify({ error: `Unknown setup tool: ${name}` });
|
package/src/tools.ts
CHANGED
|
@@ -45,26 +45,26 @@ export const toolDefinitions = {
|
|
|
45
45
|
},
|
|
46
46
|
verbo_configure_agent: {
|
|
47
47
|
description:
|
|
48
|
-
"Configure the AI agent behavior.
|
|
48
|
+
"Configure the AI agent behavior. Set greeting message, FAQ, and business hours.",
|
|
49
49
|
schema: {
|
|
50
50
|
greeting_message: z
|
|
51
51
|
.string()
|
|
52
52
|
.optional()
|
|
53
|
-
.describe("Greeting message
|
|
53
|
+
.describe("Greeting message for new customers"),
|
|
54
54
|
faq: z
|
|
55
55
|
.array(
|
|
56
56
|
z.object({
|
|
57
|
-
question: z.string()
|
|
58
|
-
answer: z.string()
|
|
57
|
+
question: z.string(),
|
|
58
|
+
answer: z.string(),
|
|
59
59
|
}),
|
|
60
60
|
)
|
|
61
61
|
.optional()
|
|
62
|
-
.describe("
|
|
62
|
+
.describe("Frequently asked questions"),
|
|
63
63
|
business_hours: z
|
|
64
64
|
.record(z.string(), z.string())
|
|
65
65
|
.optional()
|
|
66
66
|
.describe(
|
|
67
|
-
"Business hours
|
|
67
|
+
"Business hours (e.g. { monday: '9:00-18:00' })",
|
|
68
68
|
),
|
|
69
69
|
},
|
|
70
70
|
},
|
|
@@ -84,16 +84,14 @@ export async function executeTool(
|
|
|
84
84
|
args.message as string,
|
|
85
85
|
args.image_url as string | undefined,
|
|
86
86
|
);
|
|
87
|
-
return JSON.stringify(result, null, 2)
|
|
88
|
-
"\n\n→ Message sent. Use verbo_list_conversations to see the conversation.";
|
|
87
|
+
return JSON.stringify(result, null, 2);
|
|
89
88
|
}
|
|
90
89
|
case "verbo_list_conversations": {
|
|
91
90
|
const result = await client.listConversations({
|
|
92
91
|
status: args.status as string | undefined,
|
|
93
92
|
limit: args.limit as number | undefined,
|
|
94
93
|
});
|
|
95
|
-
return JSON.stringify(result, null, 2)
|
|
96
|
-
"\n\n→ Use verbo_get_conversation with a conversation ID to see full messages.";
|
|
94
|
+
return JSON.stringify(result, null, 2);
|
|
97
95
|
}
|
|
98
96
|
case "verbo_get_conversation": {
|
|
99
97
|
const result = await client.getConversation(
|
|
@@ -113,8 +111,7 @@ export async function executeTool(
|
|
|
113
111
|
| Record<string, unknown>
|
|
114
112
|
| undefined,
|
|
115
113
|
});
|
|
116
|
-
return JSON.stringify(result, null, 2)
|
|
117
|
-
"\n\n→ Agent updated. Use verbo_setup_status to verify the full setup.";
|
|
114
|
+
return JSON.stringify(result, null, 2);
|
|
118
115
|
}
|
|
119
116
|
default:
|
|
120
117
|
return JSON.stringify({ error: `Unknown tool: ${name}` });
|