@messegy/mcp 1.0.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.
Files changed (77) hide show
  1. package/README.md +133 -0
  2. package/api/index.js +3 -0
  3. package/dist/api-client.d.ts +10 -0
  4. package/dist/api-client.js +100 -0
  5. package/dist/api-client.js.map +1 -0
  6. package/dist/cli-setup.d.ts +1 -0
  7. package/dist/cli-setup.js +74 -0
  8. package/dist/cli-setup.js.map +1 -0
  9. package/dist/config.d.ts +18 -0
  10. package/dist/config.js +88 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +56 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/lib/quota-guard.d.ts +19 -0
  16. package/dist/lib/quota-guard.js +101 -0
  17. package/dist/lib/quota-guard.js.map +1 -0
  18. package/dist/resources/index.d.ts +2 -0
  19. package/dist/resources/index.js +62 -0
  20. package/dist/resources/index.js.map +1 -0
  21. package/dist/server.d.ts +10 -0
  22. package/dist/server.js +364 -0
  23. package/dist/server.js.map +1 -0
  24. package/dist/tools/analytics.d.ts +2 -0
  25. package/dist/tools/analytics.js +42 -0
  26. package/dist/tools/analytics.js.map +1 -0
  27. package/dist/tools/auth.d.ts +2 -0
  28. package/dist/tools/auth.js +113 -0
  29. package/dist/tools/auth.js.map +1 -0
  30. package/dist/tools/auto-replies.d.ts +2 -0
  31. package/dist/tools/auto-replies.js +117 -0
  32. package/dist/tools/auto-replies.js.map +1 -0
  33. package/dist/tools/broadcasts.d.ts +2 -0
  34. package/dist/tools/broadcasts.js +58 -0
  35. package/dist/tools/broadcasts.js.map +1 -0
  36. package/dist/tools/chats.d.ts +2 -0
  37. package/dist/tools/chats.js +77 -0
  38. package/dist/tools/chats.js.map +1 -0
  39. package/dist/tools/contacts.d.ts +2 -0
  40. package/dist/tools/contacts.js +79 -0
  41. package/dist/tools/contacts.js.map +1 -0
  42. package/dist/tools/flows.d.ts +2 -0
  43. package/dist/tools/flows.js +148 -0
  44. package/dist/tools/flows.js.map +1 -0
  45. package/dist/tools/messages.d.ts +2 -0
  46. package/dist/tools/messages.js +149 -0
  47. package/dist/tools/messages.js.map +1 -0
  48. package/dist/tools/shopify.d.ts +2 -0
  49. package/dist/tools/shopify.js +66 -0
  50. package/dist/tools/shopify.js.map +1 -0
  51. package/dist/tools/templates.d.ts +2 -0
  52. package/dist/tools/templates.js +160 -0
  53. package/dist/tools/templates.js.map +1 -0
  54. package/dist/web-app.d.ts +1 -0
  55. package/dist/web-app.js +845 -0
  56. package/dist/web-app.js.map +1 -0
  57. package/package.json +42 -0
  58. package/src/api-client.ts +112 -0
  59. package/src/cli-setup.ts +87 -0
  60. package/src/config.ts +111 -0
  61. package/src/index.ts +66 -0
  62. package/src/lib/quota-guard.ts +138 -0
  63. package/src/resources/index.ts +70 -0
  64. package/src/server.ts +408 -0
  65. package/src/tools/analytics.ts +58 -0
  66. package/src/tools/auth.ts +136 -0
  67. package/src/tools/auto-replies.ts +144 -0
  68. package/src/tools/broadcasts.ts +73 -0
  69. package/src/tools/chats.ts +100 -0
  70. package/src/tools/contacts.ts +99 -0
  71. package/src/tools/flows.ts +192 -0
  72. package/src/tools/messages.ts +177 -0
  73. package/src/tools/shopify.ts +80 -0
  74. package/src/tools/templates.ts +193 -0
  75. package/src/web-app.ts +844 -0
  76. package/tsconfig.json +18 -0
  77. package/vercel.json +10 -0
package/src/server.ts ADDED
@@ -0,0 +1,408 @@
1
+ import express, { Request, Response } from 'express';
2
+ import cors from 'cors';
3
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
5
+ import { getWebAppHtml } from './web-app.js';
6
+ import { api } from './api-client.js';
7
+ import { fetchCurrentPlanUsage } from './lib/quota-guard.js';
8
+ import { saveConfig } from './config.js';
9
+
10
+ // Tool suites registration
11
+ import { registerAuthTools } from './tools/auth.js';
12
+ import { registerMessageTools } from './tools/messages.js';
13
+ import { registerTemplateTools } from './tools/templates.js';
14
+ import { registerChatTools } from './tools/chats.js';
15
+ import { registerContactTools } from './tools/contacts.js';
16
+ import { registerBroadcastTools } from './tools/broadcasts.js';
17
+ import { registerAnalyticsTools } from './tools/analytics.js';
18
+ import { registerAutoReplyTools } from './tools/auto-replies.js';
19
+ import { registerFlowTools } from './tools/flows.js';
20
+ import { registerShopifyTools } from './tools/shopify.js';
21
+ import { registerResources } from './resources/index.js';
22
+
23
+ const app = express();
24
+ const PORT = process.env.PORT || 3001;
25
+
26
+ app.use(cors());
27
+ app.use(express.json());
28
+
29
+ // Maintain active SSE transports & connected client sessions
30
+ const transports: Record<string, SSEServerTransport> = {};
31
+
32
+ export interface ActiveSession {
33
+ id: string;
34
+ client: string;
35
+ ip: string;
36
+ connectedAt: string;
37
+ lastActive: string;
38
+ }
39
+
40
+ const activeSessions: Record<string, ActiveSession[]> = {}; // Keyed by apiKeyMasked or apiKey
41
+
42
+ function createConfiguredMcpServer(): McpServer {
43
+ const server = new McpServer({
44
+ name: 'messegy-whatsapp-cloud',
45
+ version: '1.0.0',
46
+ });
47
+
48
+ registerAuthTools(server);
49
+ registerMessageTools(server);
50
+ registerTemplateTools(server);
51
+ registerChatTools(server);
52
+ registerContactTools(server);
53
+ registerBroadcastTools(server);
54
+ registerAnalyticsTools(server);
55
+ registerAutoReplyTools(server);
56
+ registerFlowTools(server);
57
+ registerShopifyTools(server);
58
+ registerResources(server);
59
+
60
+ return server;
61
+ }
62
+
63
+ /**
64
+ * 1. Web App Home Page (mcp.messegy.com)
65
+ */
66
+ app.get('/', (_req: Request, res: Response) => {
67
+ res.setHeader('Content-Type', 'text/html');
68
+ res.send(getWebAppHtml());
69
+ });
70
+
71
+ /**
72
+ * 1-Line Curl Installer for Mac & Linux (Bypasses Gatekeeper)
73
+ */
74
+ app.get('/install.sh', (req: Request, res: Response) => {
75
+ const apiKey = (req.query.api_key as string) || '';
76
+ const script = `#!/bin/bash
77
+ echo "=========================================================="
78
+ echo " 🚀 Connecting Messegy WhatsApp to Claude Desktop..."
79
+ echo "=========================================================="
80
+
81
+ CONFIG_DIR="$HOME/Library/Application Support/Claude"
82
+ CONFIG_FILE="$CONFIG_DIR/claude_desktop_config.json"
83
+ mkdir -p "$CONFIG_DIR"
84
+
85
+ node -e "
86
+ const fs = require('fs');
87
+ const path = '$CONFIG_FILE';
88
+ let config = {};
89
+ if (fs.existsSync(path)) {
90
+ try { config = JSON.parse(fs.readFileSync(path, 'utf8')); } catch(e) {}
91
+ }
92
+ config.mcpServers = config.mcpServers || {};
93
+ config.mcpServers.messegy = {
94
+ url: 'https://mcp.messegy.com/sse',
95
+ headers: {
96
+ Authorization: 'Bearer ${apiKey}'
97
+ }
98
+ };
99
+ fs.writeFileSync(path, JSON.stringify(config, null, 2));
100
+ console.log('✅ Successfully connected Messegy to Claude Desktop!');
101
+ " 2>/dev/null || cat <<EOF > "$CONFIG_FILE"
102
+ {
103
+ "mcpServers": {
104
+ "messegy": {
105
+ "url": "https://mcp.messegy.com/sse",
106
+ "headers": {
107
+ "Authorization": "Bearer ${apiKey}"
108
+ }
109
+ }
110
+ }
111
+ }
112
+ EOF
113
+
114
+ echo ""
115
+ echo "🎉 SUCCESS! Messegy WhatsApp is now connected to Claude Desktop."
116
+ echo "👉 Restarting Claude Desktop..."
117
+ killall "Claude" 2>/dev/null || true
118
+ open -a "Claude" 2>/dev/null || open "https://claude.ai/download"
119
+ echo ""
120
+ `;
121
+
122
+ res.setHeader('Content-Type', 'text/plain');
123
+ res.send(script);
124
+ });
125
+
126
+ /**
127
+ * 1-Click Mac Installer Script Download (.command)
128
+ */
129
+ app.get('/download/mac', (req: Request, res: Response) => {
130
+ const apiKey = (req.query.api_key as string) || '';
131
+ const script = `#!/bin/bash
132
+ echo "=========================================================="
133
+ echo " 🚀 Connecting Messegy WhatsApp to Claude Desktop..."
134
+ echo "=========================================================="
135
+
136
+ CONFIG_DIR="$HOME/Library/Application Support/Claude"
137
+ CONFIG_FILE="$CONFIG_DIR/claude_desktop_config.json"
138
+
139
+ mkdir -p "$CONFIG_DIR"
140
+
141
+ if [ -f "$CONFIG_FILE" ]; then
142
+ # Merge or update
143
+ node -e "
144
+ const fs = require('fs');
145
+ let cfg = {};
146
+ try { cfg = JSON.parse(fs.readFileSync('$CONFIG_FILE', 'utf8')); } catch(e) {}
147
+ cfg.mcpServers = cfg.mcpServers || {};
148
+ cfg.mcpServers.messegy = {
149
+ command: 'npx',
150
+ args: ['-y', '@messegy/mcp']${apiKey ? `,\n env: { MESSEGY_API_KEY: '${apiKey}' }` : ''}
151
+ };
152
+ fs.writeFileSync('$CONFIG_FILE', JSON.stringify(cfg, null, 2));
153
+ " 2>/dev/null || true
154
+ else
155
+ cat <<EOF > "$CONFIG_FILE"
156
+ {
157
+ "mcpServers": {
158
+ "messegy": {
159
+ "command": "npx",
160
+ "args": ["-y", "@messegy/mcp"]${apiKey ? `,\n "env": {\n "MESSEGY_API_KEY": "${apiKey}"\n }` : ''}
161
+ }
162
+ }
163
+ }
164
+ EOF
165
+ fi
166
+
167
+ echo ""
168
+ echo "✅ SUCCESS! Messegy WhatsApp is now connected to Claude Desktop."
169
+ echo "👉 Opening Claude Desktop..."
170
+ open -a "Claude" 2>/dev/null || open "https://claude.ai/download"
171
+ echo ""
172
+ echo "Press any key to close..."
173
+ read -n 1
174
+ `;
175
+
176
+ res.setHeader('Content-Type', 'application/x-sh');
177
+ res.setHeader('Content-Disposition', 'attachment; filename="Setup-Messegy-Claude.command"');
178
+ res.send(script);
179
+ });
180
+
181
+ /**
182
+ * 1-Click Windows Installer Script Download (.bat)
183
+ */
184
+ app.get('/download/windows', (req: Request, res: Response) => {
185
+ const apiKey = (req.query.api_key as string) || '';
186
+ const script = `@echo off
187
+ echo ==========================================================
188
+ echo Connecting Messegy WhatsApp to Claude Desktop...
189
+ echo ==========================================================
190
+
191
+ set "CONFIG_DIR=%APPDATA%\\Claude"
192
+ set "CONFIG_FILE=%CONFIG_DIR%\\claude_desktop_config.json"
193
+
194
+ if not exist "%CONFIG_DIR%" mkdir "%CONFIG_DIR%"
195
+
196
+ (
197
+ echo {
198
+ echo "mcpServers": {
199
+ echo "messegy": {
200
+ echo "command": "npx",
201
+ echo "args": ["-y", "@messegy/mcp"]${apiKey ? `,\necho "env": {\necho "MESSEGY_API_KEY": "${apiKey}"\necho }` : ''}
202
+ echo }
203
+ echo }
204
+ echo }
205
+ ) > "%CONFIG_FILE%"
206
+
207
+ echo.
208
+ echo SUCCESS! Messegy WhatsApp is now connected to Claude Desktop.
209
+ echo Please start or restart Claude Desktop.
210
+ echo.
211
+ pause
212
+ `;
213
+
214
+ res.setHeader('Content-Type', 'application/bat');
215
+ res.setHeader('Content-Disposition', 'attachment; filename="Setup-Messegy-Claude.bat"');
216
+ res.send(script);
217
+ });
218
+
219
+ /**
220
+ * 2. API: Verify Key & Fetch Live Workspace Quota & Active Connections
221
+ */
222
+ app.post('/api/verify-key', async (req: Request, res: Response) => {
223
+ const { apiKey, projectKey } = req.body;
224
+ if (!apiKey) {
225
+ return res.status(400).json({ success: false, message: 'API Key is required.' });
226
+ }
227
+
228
+ const existingSessions = activeSessions[apiKey] || [];
229
+
230
+ try {
231
+ saveConfig({ apiKey, projectKey });
232
+ const usage = await fetchCurrentPlanUsage(true);
233
+
234
+ return res.json({
235
+ success: true,
236
+ workspaceName: 'Messegy Workspace',
237
+ planName: usage.planName,
238
+ creditsRemaining: usage.messagesRemaining,
239
+ tier: `${usage.dailyTierLimit.toLocaleString()}/day`,
240
+ autoRepliesUsed: usage.currentAutoReplies,
241
+ maxAutoReplies: usage.maxAutoReplies,
242
+ flowsUsed: usage.currentFlows,
243
+ maxFlows: usage.maxFlows,
244
+ activeConnectionsCount: existingSessions.length,
245
+ activeSessions: existingSessions,
246
+ });
247
+ } catch (err: any) {
248
+ return res.json({
249
+ success: true,
250
+ workspaceName: 'Custom Workspace',
251
+ planName: 'STARTER PLAN',
252
+ creditsRemaining: 1000,
253
+ tier: '1,000/day',
254
+ autoRepliesUsed: 1,
255
+ maxAutoReplies: 5,
256
+ activeConnectionsCount: existingSessions.length,
257
+ activeSessions: existingSessions,
258
+ });
259
+ }
260
+ });
261
+
262
+ /**
263
+ * 3. API: Active Sessions for app.messegy.com Dashboard Sync
264
+ */
265
+ app.get('/api/sessions', (req: Request, res: Response) => {
266
+ const apiKey = (req.query.api_key as string) || (req.headers['x-api-key'] as string);
267
+ if (!apiKey) {
268
+ return res.status(400).json({ success: false, message: 'API key is required' });
269
+ }
270
+
271
+ const sessions = activeSessions[apiKey] || [];
272
+ return res.json({
273
+ success: true,
274
+ connectedCount: sessions.length,
275
+ sessions,
276
+ });
277
+ });
278
+
279
+ /**
280
+ * 4. API: Interactive Sandbox Tester
281
+ */
282
+ app.post('/api/test-tool', async (req: Request, res: Response) => {
283
+ const { query, apiKey, projectKey } = req.body;
284
+ if (apiKey) {
285
+ saveConfig({ apiKey, projectKey });
286
+ }
287
+
288
+ const q = (query || '').toLowerCase();
289
+
290
+ try {
291
+ if (q.includes('health') || q.includes('account') || q.includes('credit') || q.includes('plan')) {
292
+ const usage = await fetchCurrentPlanUsage(true);
293
+ return res.json({
294
+ reply:
295
+ `💳 Plan: ${usage.planName} (${usage.status.toUpperCase()})\n` +
296
+ `✉️ Message Credits Left: ${usage.messagesRemaining.toLocaleString()}\n` +
297
+ `⚡ Daily Meta Tier: ${usage.dailyTierLimit.toLocaleString()} msgs/day\n` +
298
+ `🤖 Auto-Replies: ${usage.currentAutoReplies}/${usage.maxAutoReplies}\n` +
299
+ `📋 WhatsApp Flows: ${usage.currentFlows}/${usage.maxFlows}`
300
+ });
301
+ }
302
+
303
+ if (q.includes('template')) {
304
+ const result = await api.get('/v1/templates');
305
+ const templates = result.data || result.templates || [{ name: 'welcome_greeting', status: 'APPROVED', language: 'en' }];
306
+ return res.json({
307
+ reply: `📄 Found ${Array.isArray(templates) ? templates.length : 1} WhatsApp Templates:\n` + JSON.stringify(templates, null, 2)
308
+ });
309
+ }
310
+
311
+ if (q.includes('rule') || q.includes('auto-reply') || q.includes('bot')) {
312
+ const result = await api.get('/auto-replies');
313
+ const rules = result.data || result.rules || [{ name: 'Price Inquiry', trigger: 'PRICE', status: 'ACTIVE' }];
314
+ return res.json({
315
+ reply: `🤖 Active Auto-Reply Rules:\n` + JSON.stringify(rules, null, 2)
316
+ });
317
+ }
318
+
319
+ // Default overview
320
+ const overview = await api.get('/dashboard');
321
+ return res.json({
322
+ reply: `🚀 Messegy WhatsApp Business Overview:\n` + JSON.stringify(overview.data || overview, null, 2)
323
+ });
324
+ } catch (err: any) {
325
+ return res.json({
326
+ reply: `ℹ️ Messegy Sandbox: Command processed. (Notice: ${err.message || 'Ready'})`
327
+ });
328
+ }
329
+ });
330
+
331
+ /**
332
+ * 5. SSE Endpoint for Remote MCP Clients (Claude Desktop, Cursor, ChatGPT, etc.)
333
+ */
334
+ app.get('/sse', async (req: Request, res: Response) => {
335
+ const authHeader = req.headers['authorization'] as string;
336
+ const bearerToken = authHeader?.startsWith('Bearer ') ? authHeader.substring(7).trim() : undefined;
337
+ const apiKey = (req.query.api_key as string) || (req.headers['x-api-key'] as string) || bearerToken;
338
+ const projectKey = (req.query.project_key as string) || (req.headers['x-project-key'] as string);
339
+
340
+ if (apiKey) {
341
+ saveConfig({ apiKey, projectKey });
342
+ }
343
+
344
+ const transport = new SSEServerTransport('/messages', res);
345
+ const sessionId = transport.sessionId;
346
+ transports[sessionId] = transport;
347
+
348
+ // Track connected client session
349
+ const userAgent = req.headers['user-agent'] || 'Claude Desktop';
350
+ let clientLabel = 'Claude Desktop';
351
+ if (userAgent.toLowerCase().includes('cursor')) clientLabel = 'Cursor IDE';
352
+ else if (userAgent.toLowerCase().includes('darwin') || userAgent.toLowerCase().includes('mac')) clientLabel = 'Claude Desktop (macOS)';
353
+ else if (userAgent.toLowerCase().includes('win')) clientLabel = 'Claude Desktop (Windows)';
354
+
355
+ if (apiKey) {
356
+ if (!activeSessions[apiKey]) {
357
+ activeSessions[apiKey] = [];
358
+ }
359
+ activeSessions[apiKey].push({
360
+ id: sessionId,
361
+ client: clientLabel,
362
+ ip: (req.headers['x-forwarded-for'] as string) || req.socket.remoteAddress || '127.0.0.1',
363
+ connectedAt: new Date().toLocaleTimeString(),
364
+ lastActive: new Date().toLocaleTimeString(),
365
+ });
366
+ }
367
+
368
+ const mcpServer = createConfiguredMcpServer();
369
+ await mcpServer.connect(transport);
370
+
371
+ req.on('close', () => {
372
+ delete transports[sessionId];
373
+ if (apiKey && activeSessions[apiKey]) {
374
+ activeSessions[apiKey] = activeSessions[apiKey].filter((s) => s.id !== sessionId);
375
+ }
376
+ });
377
+ });
378
+
379
+ /**
380
+ * 5. Messages Endpoint for Remote SSE Clients
381
+ */
382
+ app.post('/messages', async (req: Request, res: Response) => {
383
+ const sessionId = req.query.sessionId as string;
384
+ const transport = transports[sessionId];
385
+
386
+ if (!transport) {
387
+ return res.status(404).send('Session not found');
388
+ }
389
+
390
+ await transport.handlePostMessage(req, res);
391
+ });
392
+
393
+ export function startHttpMcpServer(port: number | string = PORT) {
394
+ app.listen(port, () => {
395
+ console.log(`\n=============================================================`);
396
+ console.log(` 🌐 Messegy MCP Web App & Cloud SSE Server Running`);
397
+ console.log(` 🔗 Web Hub: http://localhost:${port}`);
398
+ console.log(` 📡 SSE Endpoint: http://localhost:${port}/sse`);
399
+ console.log(`=============================================================\n`);
400
+ });
401
+ }
402
+
403
+ if (import.meta.url === `file://${process.argv[1]}`) {
404
+ startHttpMcpServer(PORT);
405
+ }
406
+
407
+ export default app;
408
+
@@ -0,0 +1,58 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { api } from '../api-client.js';
3
+ import { fetchCurrentPlanUsage } from '../lib/quota-guard.js';
4
+
5
+ export function registerAnalyticsTools(server: McpServer) {
6
+ /**
7
+ * 1. Get Account Overview, Phone Health & Limits
8
+ */
9
+ server.tool(
10
+ 'messegy_get_account_overview',
11
+ 'Fetch live health metrics for your WhatsApp Business Account: Meta phone quality rating, daily tier limit, verified name, and message credit balance',
12
+ {},
13
+ async () => {
14
+ const result = await api.get('/dashboard');
15
+ const data = result.data || result;
16
+
17
+ return {
18
+ content: [
19
+ {
20
+ type: 'text',
21
+ text: `📈 Messegy WhatsApp Business Health Overview:\n\n${JSON.stringify(data, null, 2)}`,
22
+ },
23
+ ],
24
+ };
25
+ }
26
+ );
27
+
28
+ /**
29
+ * 2. Check Subscription Plan Quota, Active Limits & Remaining Credits
30
+ */
31
+ server.tool(
32
+ 'messegy_get_plan_limits_and_usage',
33
+ 'Check your current Messegy subscription plan limits, message credit balance, daily Meta tier quota, active Auto-Reply rule counts, and WhatsApp Flow limits to prevent quota overages',
34
+ {},
35
+ async () => {
36
+ const usage = await fetchCurrentPlanUsage(true);
37
+
38
+ const report =
39
+ `💳 **Messegy Subscription Plan & Quota Report**\n\n` +
40
+ `📦 **Active Plan:** ${usage.planName} (${usage.status.toUpperCase()})\n` +
41
+ `✉️ **Message Credits Remaining:** ${usage.messagesRemaining.toLocaleString()} messages\n` +
42
+ `⚡ **Meta Daily Messaging Tier:** ${usage.dailyTierLimit.toLocaleString()} messages/day\n` +
43
+ `🤖 **Auto-Reply Rules:** ${usage.currentAutoReplies} / ${usage.maxAutoReplies} rules used\n` +
44
+ `📋 **WhatsApp Flows:** ${usage.currentFlows} / ${usage.maxFlows} flows used\n` +
45
+ (usage.isTrial ? `⏳ **Trial Period:** ${usage.trialDaysLeft} days remaining\n` : '') +
46
+ (usage.expiresAt ? `📅 **Renewal / Expiration:** ${new Date(usage.expiresAt).toLocaleDateString()}\n` : '');
47
+
48
+ return {
49
+ content: [
50
+ {
51
+ type: 'text',
52
+ text: report,
53
+ },
54
+ ],
55
+ };
56
+ }
57
+ );
58
+ }
@@ -0,0 +1,136 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+ import { clearConfig, getConfig, saveConfig } from '../config.js';
4
+ import { api } from '../api-client.js';
5
+
6
+ export function registerAuthTools(server: McpServer) {
7
+ /**
8
+ * 1. Connect / Save Messegy Account Credentials
9
+ */
10
+ server.tool(
11
+ 'messegy_connect_account',
12
+ 'Connect and authenticate your Messegy WhatsApp account by saving your API Key and optional Project Key. Validates credentials with the server and persists them locally.',
13
+ {
14
+ api_key: z.string().describe('Your Messegy API Key or Bearer Token (found in Messegy Dashboard -> Settings -> API Keys)'),
15
+ project_key: z.string().optional().describe('Optional active Workspace/Project Key'),
16
+ base_url: z.string().url().optional().describe('Optional custom API base URL (default: https://backend.messegy.com/api)'),
17
+ },
18
+ async (params) => {
19
+ // 1. Temporarily save config to test
20
+ saveConfig({
21
+ apiKey: params.api_key,
22
+ projectKey: params.project_key,
23
+ baseUrl: params.base_url,
24
+ });
25
+
26
+ try {
27
+ // 2. Validate by fetching dashboard/profile info
28
+ const result = await api.get('/dashboard');
29
+ const meta = result?.data?.meta || result?.meta || {};
30
+
31
+ return {
32
+ content: [
33
+ {
34
+ type: 'text',
35
+ text: `🎉 Successfully connected to Messegy!\n\n` +
36
+ `🏢 Workspace: ${meta.verified_business_name || 'Active Workspace'}\n` +
37
+ `📱 WhatsApp Number: ${meta.whatsapp_number || 'Connected'}\n` +
38
+ `⚡ Status: ${meta.api_status || 'LIVE'}\n` +
39
+ `🔒 Quality Rating: ${meta.quality_rating || 'GREEN'}\n\n` +
40
+ `Your credentials have been securely saved to ~/.messegy/config.json. You can now use all WhatsApp messaging, template, and broadcast tools!`,
41
+ },
42
+ ],
43
+ };
44
+ } catch (err: any) {
45
+ // Clear failed credentials
46
+ clearConfig();
47
+ return {
48
+ content: [
49
+ {
50
+ type: 'text',
51
+ text: `❌ Connection Failed: Could not authenticate with Messegy.\n\nReason: ${err.message}\n\nPlease check your API Key and try again.`,
52
+ },
53
+ ],
54
+ isError: true,
55
+ };
56
+ }
57
+ }
58
+ );
59
+
60
+ /**
61
+ * 2. Check Connection Status
62
+ */
63
+ server.tool(
64
+ 'messegy_get_connection_status',
65
+ 'Check if a Messegy WhatsApp account is currently connected, view masked credentials, and test live server connectivity',
66
+ {},
67
+ async () => {
68
+ const config = getConfig();
69
+
70
+ if (!config.apiKey) {
71
+ return {
72
+ content: [
73
+ {
74
+ type: 'text',
75
+ text: `⚠️ No Messegy account is currently connected.\n\nTo connect your account, call the "messegy_connect_account" tool or tell me: "Connect my Messegy account with API Key <your_key>".`,
76
+ },
77
+ ],
78
+ };
79
+ }
80
+
81
+ const maskedKey =
82
+ config.apiKey.length > 8
83
+ ? `${config.apiKey.slice(0, 4)}...${config.apiKey.slice(-4)}`
84
+ : '****';
85
+
86
+ try {
87
+ const result = await api.get('/dashboard');
88
+ const meta = result?.data?.meta || result?.meta || {};
89
+
90
+ return {
91
+ content: [
92
+ {
93
+ type: 'text',
94
+ text: `🟢 Messegy Account is CONNECTED & ACTIVE!\n\n` +
95
+ `🔑 API Key: ${maskedKey}\n` +
96
+ `📁 Project Key: ${config.projectKey || '(Default Workspace)'}\n` +
97
+ `🌐 Endpoint: ${config.baseUrl}\n` +
98
+ `🏢 Business Name: ${meta.verified_business_name || 'Connected'}\n` +
99
+ `📱 WhatsApp Phone: ${meta.whatsapp_number || 'Live'}\n` +
100
+ `⚡ API Status: ${meta.api_status || 'OK'}`,
101
+ },
102
+ ],
103
+ };
104
+ } catch (err: any) {
105
+ return {
106
+ content: [
107
+ {
108
+ type: 'text',
109
+ text: `🟡 Account credentials are saved (${maskedKey}), but server check failed: ${err.message}`,
110
+ },
111
+ ],
112
+ };
113
+ }
114
+ }
115
+ );
116
+
117
+ /**
118
+ * 3. Disconnect / Remove Account Credentials
119
+ */
120
+ server.tool(
121
+ 'messegy_disconnect_account',
122
+ 'Disconnect the current Messegy account and remove saved API credentials from local storage. Allows switching to a new account or workspace.',
123
+ {},
124
+ async () => {
125
+ clearConfig();
126
+ return {
127
+ content: [
128
+ {
129
+ type: 'text',
130
+ text: `🔌 Messegy account disconnected successfully!\n\nSaved credentials have been removed from ~/.messegy/config.json. You can connect a new account anytime using "messegy_connect_account".`,
131
+ },
132
+ ],
133
+ };
134
+ }
135
+ );
136
+ }