@honkio/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.
- package/LICENSE +21 -0
- package/README.md +334 -0
- package/dist/client.d.ts +165 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +192 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +111 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +4 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +96 -0
- package/dist/resources.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +518 -0
- package/dist/tools.js.map +1 -0
- package/package.json +39 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HonkIO API client — thin wrapper around the REST API, used by all MCP tools.
|
|
3
|
+
*/
|
|
4
|
+
const DEFAULT_BASE_URL = 'https://api.honkio.ca';
|
|
5
|
+
// Cap upstream calls so a slow API can't hang the agent indefinitely.
|
|
6
|
+
const REQUEST_TIMEOUT_MS = 15_000;
|
|
7
|
+
export class HonkioError extends Error {
|
|
8
|
+
status;
|
|
9
|
+
code;
|
|
10
|
+
constructor(status, code, message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.name = 'HonkioError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class HonkioClient {
|
|
18
|
+
apiKey;
|
|
19
|
+
baseUrl;
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.apiKey = options.apiKey;
|
|
22
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, '');
|
|
23
|
+
}
|
|
24
|
+
async request(method, path, body, query) {
|
|
25
|
+
let url = `${this.baseUrl}${path}`;
|
|
26
|
+
if (query) {
|
|
27
|
+
const params = new URLSearchParams();
|
|
28
|
+
for (const [k, v] of Object.entries(query)) {
|
|
29
|
+
if (v !== undefined)
|
|
30
|
+
params.set(k, String(v));
|
|
31
|
+
}
|
|
32
|
+
const qs = params.toString();
|
|
33
|
+
if (qs)
|
|
34
|
+
url += `?${qs}`;
|
|
35
|
+
}
|
|
36
|
+
const res = await fetch(url, {
|
|
37
|
+
method,
|
|
38
|
+
headers: {
|
|
39
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
|
+
'Accept': 'application/json',
|
|
42
|
+
},
|
|
43
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
44
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
45
|
+
});
|
|
46
|
+
// 204 / empty bodies should not crash JSON parsing.
|
|
47
|
+
const text = await res.text();
|
|
48
|
+
const data = text ? (() => { try {
|
|
49
|
+
return JSON.parse(text);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
} })() : null;
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
const code = data?.code ?? 'UNKNOWN_ERROR';
|
|
56
|
+
const message = data?.message ?? text ?? `HTTP ${res.status}`;
|
|
57
|
+
throw new HonkioError(res.status, code, message);
|
|
58
|
+
}
|
|
59
|
+
return data;
|
|
60
|
+
}
|
|
61
|
+
// ── Messages ─────────────────────────────────────────────
|
|
62
|
+
sendMessage(params) {
|
|
63
|
+
return this.request('POST', '/v1/messages', params);
|
|
64
|
+
}
|
|
65
|
+
listMessages(query) {
|
|
66
|
+
return this.request('GET', '/v1/messages', undefined, query);
|
|
67
|
+
}
|
|
68
|
+
getMessage(id) {
|
|
69
|
+
return this.request('GET', `/v1/messages/${id}`);
|
|
70
|
+
}
|
|
71
|
+
// ── Phone Numbers ─────────────────────────────────────────
|
|
72
|
+
searchPhoneNumbers(query) {
|
|
73
|
+
return this.request('GET', '/v1/phone-numbers/search', undefined, query);
|
|
74
|
+
}
|
|
75
|
+
provisionPhoneNumber(phoneNumber) {
|
|
76
|
+
return this.request('POST', '/v1/phone-numbers', { phone_number: phoneNumber });
|
|
77
|
+
}
|
|
78
|
+
listPhoneNumbers() {
|
|
79
|
+
return this.request('GET', '/v1/phone-numbers');
|
|
80
|
+
}
|
|
81
|
+
getPhoneNumber(id) {
|
|
82
|
+
return this.request('GET', `/v1/phone-numbers/${id}`);
|
|
83
|
+
}
|
|
84
|
+
releasePhoneNumber(id) {
|
|
85
|
+
return this.request('DELETE', `/v1/phone-numbers/${id}`);
|
|
86
|
+
}
|
|
87
|
+
// ── Compliance: Consents ──────────────────────────────────
|
|
88
|
+
recordConsent(params) {
|
|
89
|
+
return this.request('POST', '/v1/compliance/consents', params);
|
|
90
|
+
}
|
|
91
|
+
listConsents(query) {
|
|
92
|
+
return this.request('GET', '/v1/compliance/consents', undefined, query);
|
|
93
|
+
}
|
|
94
|
+
checkConsent(phoneNumber) {
|
|
95
|
+
return this.request('GET', '/v1/compliance/consents/check', undefined, { phone_number: phoneNumber });
|
|
96
|
+
}
|
|
97
|
+
revokeConsent(phoneNumber) {
|
|
98
|
+
return this.request('DELETE', `/v1/compliance/consents/${encodeURIComponent(phoneNumber)}`);
|
|
99
|
+
}
|
|
100
|
+
// ── Compliance: Opt-Outs ──────────────────────────────────
|
|
101
|
+
recordOptOut(params) {
|
|
102
|
+
return this.request('POST', '/v1/compliance/opt-outs', params);
|
|
103
|
+
}
|
|
104
|
+
listOptOuts(query) {
|
|
105
|
+
return this.request('GET', '/v1/compliance/opt-outs', undefined, query);
|
|
106
|
+
}
|
|
107
|
+
// ── Compliance: DNCL ─────────────────────────────────────
|
|
108
|
+
checkDncl(phoneNumber) {
|
|
109
|
+
return this.request('POST', '/v1/compliance/dncl/check', { phone_number: phoneNumber });
|
|
110
|
+
}
|
|
111
|
+
batchCheckDncl(phoneNumbers) {
|
|
112
|
+
return this.request('POST', '/v1/compliance/dncl/batch-check', { phone_numbers: phoneNumbers });
|
|
113
|
+
}
|
|
114
|
+
// ── Compliance: Erasure ───────────────────────────────────
|
|
115
|
+
requestErasure(params) {
|
|
116
|
+
return this.request('POST', '/v1/compliance/erasure', params);
|
|
117
|
+
}
|
|
118
|
+
// ── Verify (OTP) ──────────────────────────────────────────
|
|
119
|
+
startVerification(params) {
|
|
120
|
+
return this.request('POST', '/v1/verify', params);
|
|
121
|
+
}
|
|
122
|
+
checkVerification(verificationId, code) {
|
|
123
|
+
return this.request('POST', `/v1/verify/${verificationId}/check`, { code });
|
|
124
|
+
}
|
|
125
|
+
getVerification(verificationId) {
|
|
126
|
+
return this.request('GET', `/v1/verify/${verificationId}`);
|
|
127
|
+
}
|
|
128
|
+
listVerifications(query) {
|
|
129
|
+
return this.request('GET', '/v1/verify', undefined, query);
|
|
130
|
+
}
|
|
131
|
+
// ── Webhooks ──────────────────────────────────────────────
|
|
132
|
+
createWebhook(params) {
|
|
133
|
+
return this.request('POST', '/v1/webhooks', params);
|
|
134
|
+
}
|
|
135
|
+
listWebhooks() {
|
|
136
|
+
return this.request('GET', '/v1/webhooks');
|
|
137
|
+
}
|
|
138
|
+
getWebhook(id) {
|
|
139
|
+
return this.request('GET', `/v1/webhooks/${id}`);
|
|
140
|
+
}
|
|
141
|
+
updateWebhook(id, params) {
|
|
142
|
+
return this.request('PATCH', `/v1/webhooks/${id}`, params);
|
|
143
|
+
}
|
|
144
|
+
deleteWebhook(id) {
|
|
145
|
+
return this.request('DELETE', `/v1/webhooks/${id}`);
|
|
146
|
+
}
|
|
147
|
+
listWebhookDeliveries(webhookId, query) {
|
|
148
|
+
return this.request('GET', `/v1/webhooks/${webhookId}/deliveries`, undefined, query);
|
|
149
|
+
}
|
|
150
|
+
reactivateWebhook(webhookId) {
|
|
151
|
+
return this.request('POST', `/v1/webhooks/${webhookId}/reactivate`);
|
|
152
|
+
}
|
|
153
|
+
listWebhookDeadLetters(webhookId, query) {
|
|
154
|
+
return this.request('GET', `/v1/webhooks/${webhookId}/dead-letters`, undefined, query);
|
|
155
|
+
}
|
|
156
|
+
replayWebhookDeadLetter(deadLetterId) {
|
|
157
|
+
return this.request('POST', `/v1/webhooks/dead-letters/${deadLetterId}/replay`);
|
|
158
|
+
}
|
|
159
|
+
discardWebhookDeadLetter(deadLetterId) {
|
|
160
|
+
return this.request('DELETE', `/v1/webhooks/dead-letters/${deadLetterId}`);
|
|
161
|
+
}
|
|
162
|
+
// ── Account ───────────────────────────────────────────────
|
|
163
|
+
/**
|
|
164
|
+
* Resolve the account the API key belongs to.
|
|
165
|
+
*
|
|
166
|
+
* The key does not carry its account id, and every other account route needs
|
|
167
|
+
* one, so without this an agent cannot use them at all — it would have to ask
|
|
168
|
+
* the user to fetch the id from the dashboard.
|
|
169
|
+
*/
|
|
170
|
+
getCurrentAccount() {
|
|
171
|
+
return this.request('GET', '/v1/accounts/me');
|
|
172
|
+
}
|
|
173
|
+
getAccount(id) {
|
|
174
|
+
return this.request('GET', `/v1/accounts/${id}`);
|
|
175
|
+
}
|
|
176
|
+
updateAccount(id, params) {
|
|
177
|
+
return this.request('PATCH', `/v1/accounts/${id}`, params);
|
|
178
|
+
}
|
|
179
|
+
getUsage(id, query) {
|
|
180
|
+
return this.request('GET', `/v1/accounts/${id}/usage`, undefined, query);
|
|
181
|
+
}
|
|
182
|
+
createApiKey(accountId, params) {
|
|
183
|
+
return this.request('POST', `/v1/accounts/${accountId}/api-keys`, params ?? {});
|
|
184
|
+
}
|
|
185
|
+
revokeApiKey(accountId, keyId) {
|
|
186
|
+
return this.request('DELETE', `/v1/accounts/${accountId}/api-keys/${keyId}`);
|
|
187
|
+
}
|
|
188
|
+
rotateApiKey(accountId, keyId) {
|
|
189
|
+
return this.request('POST', `/v1/accounts/${accountId}/api-keys/${keyId}/rotate`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* HonkIO MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes the HonkIO SMS API as an MCP server for AI coding agents.
|
|
6
|
+
* Supports stdio transport (Claude Desktop, Cursor, VS Code, etc.)
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* HONKIO_API_KEY=mk_live_... node dist/index.js
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* HonkIO MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes the HonkIO SMS API as an MCP server for AI coding agents.
|
|
6
|
+
* Supports stdio transport (Claude Desktop, Cursor, VS Code, etc.)
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* HONKIO_API_KEY=mk_live_... node dist/index.js
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { dirname, resolve } from 'node:path';
|
|
14
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
15
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
16
|
+
import { HonkioClient } from './client.js';
|
|
17
|
+
import { registerTools } from './tools.js';
|
|
18
|
+
import { registerResources } from './resources.js';
|
|
19
|
+
import { registerPrompts } from './prompts.js';
|
|
20
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const PACKAGE_VERSION = (() => {
|
|
22
|
+
try {
|
|
23
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, '../package.json'), 'utf8'));
|
|
24
|
+
return pkg.version ?? 'unknown';
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return 'unknown';
|
|
28
|
+
}
|
|
29
|
+
})();
|
|
30
|
+
function getEnv(key) {
|
|
31
|
+
const val = process.env[key];
|
|
32
|
+
if (!val) {
|
|
33
|
+
console.error(`[honkio-mcp] Missing required environment variable: ${key}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
return val;
|
|
37
|
+
}
|
|
38
|
+
async function main() {
|
|
39
|
+
const apiKey = getEnv('HONKIO_API_KEY');
|
|
40
|
+
const baseUrl = process.env['HONKIO_API_URL'] ?? 'https://api.honkio.ca';
|
|
41
|
+
const client = new HonkioClient({ apiKey, baseUrl });
|
|
42
|
+
const server = new McpServer({
|
|
43
|
+
name: 'honkio',
|
|
44
|
+
version: PACKAGE_VERSION,
|
|
45
|
+
});
|
|
46
|
+
registerTools(server, client);
|
|
47
|
+
registerResources(server, client);
|
|
48
|
+
registerPrompts(server);
|
|
49
|
+
const transport = new StdioServerTransport();
|
|
50
|
+
await server.connect(transport);
|
|
51
|
+
}
|
|
52
|
+
main().catch((err) => {
|
|
53
|
+
console.error('[honkio-mcp] Fatal error:', err);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAC;QAC5G,OAAO,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,EAAE,CAAC;AAEL,SAAS,MAAM,CAAC,GAAW;IACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,uDAAuD,GAAG,EAAE,CAAC,CAAC;QAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,uBAAuB,CAAC;IAEzE,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAErD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;IAEH,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,eAAe,CAAC,MAAM,CAAC,CAAC;IAExB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyIvD"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function registerPrompts(server) {
|
|
3
|
+
server.prompt('send_compliant_sms', 'Walk through the full compliant SMS send workflow: check CASL consent and send the message. (CRTC DNCL checking is coming soon and not yet enforced.)', {
|
|
4
|
+
phone_number: z.string().describe('Recipient phone number in E.164 format (e.g. +14165551234).'),
|
|
5
|
+
from_number: z.string().describe('Your sending phone number in E.164 format.'),
|
|
6
|
+
message: z.string().describe('The message body you want to send.'),
|
|
7
|
+
}, ({ phone_number, from_number, message }) => ({
|
|
8
|
+
messages: [{
|
|
9
|
+
role: 'user',
|
|
10
|
+
content: {
|
|
11
|
+
type: 'text',
|
|
12
|
+
text: `I want to send an SMS message via HonkIO. Please help me do this compliantly:
|
|
13
|
+
|
|
14
|
+
**Recipient:** ${phone_number}
|
|
15
|
+
**From:** ${from_number}
|
|
16
|
+
**Message:** ${message}
|
|
17
|
+
|
|
18
|
+
Please follow these steps in order:
|
|
19
|
+
1. Use \`check_consent\` to verify the recipient has valid CASL consent on file.
|
|
20
|
+
2. Based on the result:
|
|
21
|
+
- If consent is ACTIVE → use \`send_sms\` to send the message. (Note: CRTC DNCL checking is coming soon and not yet enforced, so no DNCL check is required right now.)
|
|
22
|
+
- If consent is missing or expired → explain that consent must be recorded before sending. Ask if I want to record express or implied consent.
|
|
23
|
+
- If there is an opt-out → inform me that the number has opted out and the message cannot be sent until they opt back in (they must send START/UNSTOP).
|
|
24
|
+
|
|
25
|
+
Show me the result of each step.`,
|
|
26
|
+
},
|
|
27
|
+
}],
|
|
28
|
+
}));
|
|
29
|
+
server.prompt('provision_canadian_number', 'Search for and provision a Canadian phone number, optionally filtered by area code.', {
|
|
30
|
+
area_code: z.string().optional().describe('Preferred area code (e.g. "416" for Toronto, "604" for Vancouver). Leave blank to search all available Canadian numbers.'),
|
|
31
|
+
}, ({ area_code }) => ({
|
|
32
|
+
messages: [{
|
|
33
|
+
role: 'user',
|
|
34
|
+
content: {
|
|
35
|
+
type: 'text',
|
|
36
|
+
text: `I want to provision a Canadian phone number for my HonkIO account${area_code ? ` in the ${area_code} area code` : ''}.
|
|
37
|
+
|
|
38
|
+
Please:
|
|
39
|
+
1. Use \`search_phone_numbers\` to find available numbers${area_code ? ` with area_code "${area_code}"` : ''}.
|
|
40
|
+
2. Show me the results including the phone number, region (province), capabilities, and monthly cost.
|
|
41
|
+
3. Ask me which number I'd like to provision.
|
|
42
|
+
4. Once I choose, use \`provision_phone_number\` to provision it.
|
|
43
|
+
5. Confirm the result and show me the provisioned number's details.`,
|
|
44
|
+
},
|
|
45
|
+
}],
|
|
46
|
+
}));
|
|
47
|
+
server.prompt('setup_webhooks', 'Set up webhook endpoints to receive HonkIO event notifications.', {
|
|
48
|
+
url: z.string().describe('Your HTTPS endpoint URL that will receive webhook events.'),
|
|
49
|
+
}, ({ url }) => ({
|
|
50
|
+
messages: [{
|
|
51
|
+
role: 'user',
|
|
52
|
+
content: {
|
|
53
|
+
type: 'text',
|
|
54
|
+
text: `I want to set up webhooks for my HonkIO account to receive event notifications at: ${url}
|
|
55
|
+
|
|
56
|
+
Please:
|
|
57
|
+
1. Use \`list_webhooks\` to check if any webhooks already exist for this account.
|
|
58
|
+
2. If none exist, use \`create_webhook\` to register a webhook at the provided URL with a recommended event set:
|
|
59
|
+
- message.delivered (to know when messages arrive)
|
|
60
|
+
- message.failed (to handle delivery failures)
|
|
61
|
+
- message.received (to handle inbound SMS replies)
|
|
62
|
+
- opt_out.recorded (to sync opt-outs to your CRM)
|
|
63
|
+
3. Display the signing_secret from the response — remind me to store it securely as it won't be shown again. Explain that I should use it to verify the X-HonkIO-Signature header on incoming webhook requests.
|
|
64
|
+
4. If webhooks already exist, show me the existing ones and ask if I want to create an additional one or update an existing one.`,
|
|
65
|
+
},
|
|
66
|
+
}],
|
|
67
|
+
}));
|
|
68
|
+
server.prompt('compliance_audit', 'Run a compliance check on a phone number: consent status and opt-out status. (CRTC DNCL status is coming soon.)', {
|
|
69
|
+
phone_number: z.string().describe('Phone number to audit in E.164 format.'),
|
|
70
|
+
}, ({ phone_number }) => ({
|
|
71
|
+
messages: [{
|
|
72
|
+
role: 'user',
|
|
73
|
+
content: {
|
|
74
|
+
type: 'text',
|
|
75
|
+
text: `Please run a CASL compliance audit for the phone number: ${phone_number}
|
|
76
|
+
|
|
77
|
+
Use these tools and summarize the results:
|
|
78
|
+
1. \`check_consent\` — What is the consent status? Is it ACTIVE, EXPIRED, or missing?
|
|
79
|
+
2. \`list_opt_outs\` with phone_number filter — Has this number opted out from any of my sending numbers?
|
|
80
|
+
(CRTC DNCL checking is coming soon and not yet available, so skip the DNCL lookup for now.)
|
|
81
|
+
|
|
82
|
+
Summarize with:
|
|
83
|
+
- ✅ or ❌ for each check
|
|
84
|
+
- Whether it is currently safe to send a commercial message to this number
|
|
85
|
+
- What steps (if any) need to be taken before sending`,
|
|
86
|
+
},
|
|
87
|
+
}],
|
|
88
|
+
}));
|
|
89
|
+
server.prompt('handle_erasure_request', 'Process a PIPEDA right-to-erasure request for a subscriber.', {
|
|
90
|
+
phone_number: z.string().describe('Phone number to erase data for in E.164 format.'),
|
|
91
|
+
reason: z.string().optional().describe('Reason provided by the subscriber for the erasure request.'),
|
|
92
|
+
}, ({ phone_number, reason }) => ({
|
|
93
|
+
messages: [{
|
|
94
|
+
role: 'user',
|
|
95
|
+
content: {
|
|
96
|
+
type: 'text',
|
|
97
|
+
text: `A subscriber has requested erasure of their data under PIPEDA / Quebec Law 25.
|
|
98
|
+
|
|
99
|
+
**Phone number:** ${phone_number}
|
|
100
|
+
${reason ? `**Reason provided:** ${reason}` : ''}
|
|
101
|
+
|
|
102
|
+
Please:
|
|
103
|
+
1. Confirm with me before proceeding — this action is irreversible.
|
|
104
|
+
2. If confirmed, use \`request_erasure\` to erase all personal data for this number.
|
|
105
|
+
3. Show me the result including the erased_at timestamp.
|
|
106
|
+
4. Explain what was erased (message bodies, consent records, opt-out records) and what is retained (message metadata and an immutable audit log entry for compliance).`,
|
|
107
|
+
},
|
|
108
|
+
}],
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,KAAK,YAAY,EAAe,MAAM,aAAa,CAAC;AAE7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAgH/E"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { HonkioError } from './client.js';
|
|
2
|
+
export function registerResources(server, client) {
|
|
3
|
+
// honkio://messages — paginated list of messages
|
|
4
|
+
server.resource('messages', 'honkio://messages', { description: 'Recent SMS messages (up to 20)' }, async (uri) => {
|
|
5
|
+
try {
|
|
6
|
+
const result = await client.listMessages({ limit: 20 });
|
|
7
|
+
return {
|
|
8
|
+
contents: [{
|
|
9
|
+
uri: uri.href,
|
|
10
|
+
mimeType: 'application/json',
|
|
11
|
+
text: JSON.stringify(result, null, 2),
|
|
12
|
+
}],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
const message = err instanceof HonkioError ? `[${err.code}] ${err.message}` : String(err);
|
|
17
|
+
return {
|
|
18
|
+
contents: [{
|
|
19
|
+
uri: uri.href,
|
|
20
|
+
mimeType: 'text/plain',
|
|
21
|
+
text: `Error fetching messages: ${message}`,
|
|
22
|
+
}],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
// honkio://phone-numbers — list of provisioned numbers
|
|
27
|
+
server.resource('phone-numbers', 'honkio://phone-numbers', { description: 'Phone numbers provisioned on your account' }, async (uri) => {
|
|
28
|
+
try {
|
|
29
|
+
const result = await client.listPhoneNumbers();
|
|
30
|
+
return {
|
|
31
|
+
contents: [{
|
|
32
|
+
uri: uri.href,
|
|
33
|
+
mimeType: 'application/json',
|
|
34
|
+
text: JSON.stringify(result, null, 2),
|
|
35
|
+
}],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const message = err instanceof HonkioError ? `[${err.code}] ${err.message}` : String(err);
|
|
40
|
+
return {
|
|
41
|
+
contents: [{
|
|
42
|
+
uri: uri.href,
|
|
43
|
+
mimeType: 'text/plain',
|
|
44
|
+
text: `Error fetching phone numbers: ${message}`,
|
|
45
|
+
}],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
// honkio://consents — active CASL consents
|
|
50
|
+
server.resource('consents', 'honkio://consents', { description: 'Active CASL consent records (up to 20)' }, async (uri) => {
|
|
51
|
+
try {
|
|
52
|
+
const result = await client.listConsents({ status: 'ACTIVE', limit: 20 });
|
|
53
|
+
return {
|
|
54
|
+
contents: [{
|
|
55
|
+
uri: uri.href,
|
|
56
|
+
mimeType: 'application/json',
|
|
57
|
+
text: JSON.stringify(result, null, 2),
|
|
58
|
+
}],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
const message = err instanceof HonkioError ? `[${err.code}] ${err.message}` : String(err);
|
|
63
|
+
return {
|
|
64
|
+
contents: [{
|
|
65
|
+
uri: uri.href,
|
|
66
|
+
mimeType: 'text/plain',
|
|
67
|
+
text: `Error fetching consents: ${message}`,
|
|
68
|
+
}],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
// honkio://webhooks — registered webhooks
|
|
73
|
+
server.resource('webhooks', 'honkio://webhooks', { description: 'Registered webhook endpoints for your account' }, async (uri) => {
|
|
74
|
+
try {
|
|
75
|
+
const result = await client.listWebhooks();
|
|
76
|
+
return {
|
|
77
|
+
contents: [{
|
|
78
|
+
uri: uri.href,
|
|
79
|
+
mimeType: 'application/json',
|
|
80
|
+
text: JSON.stringify(result, null, 2),
|
|
81
|
+
}],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
const message = err instanceof HonkioError ? `[${err.code}] ${err.message}` : String(err);
|
|
86
|
+
return {
|
|
87
|
+
contents: [{
|
|
88
|
+
uri: uri.href,
|
|
89
|
+
mimeType: 'text/plain',
|
|
90
|
+
text: `Error fetching webhooks: ${message}`,
|
|
91
|
+
}],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,KAAK,YAAY,EAAe,MAAM,aAAa,CAAC;AAwC7D,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAiqB3E"}
|