@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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jeff Caldwell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,334 @@
1
+ # HonkIO MCP Server
2
+
3
+ Model Context Protocol (MCP) server for [HonkIO](https://honkio.ca), the Canadian SMS API. It lets an AI agent send SMS, run phone verification, manage Canadian numbers, and handle CASL compliance through natural language.
4
+
5
+ 37 tools, 4 resources, and 5 guided prompts, all backed by the live HonkIO REST API.
6
+
7
+ ---
8
+
9
+ ## Requirements
10
+
11
+ - **Node.js 20 or newer**
12
+ - A HonkIO account and API key
13
+
14
+ ---
15
+
16
+ ## 1. Get an API key
17
+
18
+ Sign in at **<https://honkio.ca/dashboard/keys>** and copy a key:
19
+
20
+ | Prefix | Mode | Behaviour |
21
+ |---|---|---|
22
+ | `mk_test_…` | Test | Messages are simulated as delivered. **No SMS is sent and nothing is charged.** |
23
+ | `mk_live_…` | Live | Real SMS, real Canadian numbers, **real charges against your balance**. |
24
+
25
+ **Start with a test key.** Every tool works in test mode, so an agent can exercise the whole surface for free. Switch to a live key only when you want real delivery.
26
+
27
+ Live sending also requires that the account owner has completed phone verification, and that you have provisioned at least one number to send from.
28
+
29
+ ---
30
+
31
+ ## 2. Install
32
+
33
+ > **The package is not on npm yet**, so `npx @honkio/mcp` will not work. Until it is published, install from source. It takes about thirty seconds.
34
+
35
+ ```sh
36
+ git clone https://github.com/jeffcaldwellca/honkio
37
+ cd honkio/mcp
38
+ npm install
39
+ npm run build
40
+ ```
41
+
42
+ That produces `dist/index.js`, which is the server entry point. Note its absolute path — you will need it in the next step:
43
+
44
+ ```sh
45
+ pwd # e.g. /Users/you/code/honkio/mcp
46
+ ```
47
+
48
+ ---
49
+
50
+ ## 3. Connect your AI tool
51
+
52
+ In every example below, replace `/ABSOLUTE/PATH/TO/honkio/mcp` with the path from `pwd`, and put your own key in `HONKIO_API_KEY`.
53
+
54
+ ### Claude Code
55
+
56
+ From inside your project:
57
+
58
+ ```sh
59
+ claude mcp add honkio \
60
+ --env HONKIO_API_KEY=mk_test_YOUR_KEY_HERE \
61
+ -- node /ABSOLUTE/PATH/TO/honkio/mcp/dist/index.js
62
+ ```
63
+
64
+ Or commit a `.mcp.json` at the project root to share it with your team (keep the real key out of git — see [Keeping your key out of git](#keeping-your-key-out-of-git)):
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "honkio": {
70
+ "command": "node",
71
+ "args": ["/ABSOLUTE/PATH/TO/honkio/mcp/dist/index.js"],
72
+ "env": { "HONKIO_API_KEY": "mk_test_YOUR_KEY_HERE" }
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ ### Claude Desktop
79
+
80
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
81
+
82
+ ```json
83
+ {
84
+ "mcpServers": {
85
+ "honkio": {
86
+ "command": "node",
87
+ "args": ["/ABSOLUTE/PATH/TO/honkio/mcp/dist/index.js"],
88
+ "env": { "HONKIO_API_KEY": "mk_test_YOUR_KEY_HERE" }
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ Restart Claude Desktop afterwards.
95
+
96
+ ### Cursor
97
+
98
+ Edit `.cursor/mcp.json` in your project, or `~/.cursor/mcp.json` globally:
99
+
100
+ ```json
101
+ {
102
+ "mcpServers": {
103
+ "honkio": {
104
+ "command": "node",
105
+ "args": ["/ABSOLUTE/PATH/TO/honkio/mcp/dist/index.js"],
106
+ "env": { "HONKIO_API_KEY": "mk_test_YOUR_KEY_HERE" }
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ ### VS Code (GitHub Copilot)
113
+
114
+ Edit `.vscode/mcp.json` in your workspace:
115
+
116
+ ```json
117
+ {
118
+ "servers": {
119
+ "honkio": {
120
+ "type": "stdio",
121
+ "command": "node",
122
+ "args": ["/ABSOLUTE/PATH/TO/honkio/mcp/dist/index.js"],
123
+ "env": { "HONKIO_API_KEY": "mk_test_YOUR_KEY_HERE" }
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ ---
130
+
131
+ ## 4. Confirm it works
132
+
133
+ Ask your agent:
134
+
135
+ ```
136
+ List my HonkIO phone numbers.
137
+ ```
138
+
139
+ - A list (or an empty list) means you are connected.
140
+ - `Error [UNAUTHORIZED]: Invalid or missing API key.` means the key is wrong, missing, or has been revoked.
141
+
142
+ To check the server outside any AI tool:
143
+
144
+ ```sh
145
+ HONKIO_API_KEY=mk_test_YOUR_KEY node dist/index.js
146
+ ```
147
+
148
+ It should start and wait silently on stdin — an MCP server speaks JSON-RPC over stdio, so no output is the healthy state. Press Ctrl-C to exit. If it exits immediately with an error, the message tells you what is wrong.
149
+
150
+ ---
151
+
152
+ ## Environment variables
153
+
154
+ | Variable | Required | Description |
155
+ |---|---|---|
156
+ | `HONKIO_API_KEY` | Yes | Your API key (`mk_live_…` or `mk_test_…`). The server refuses to start without it. |
157
+ | `HONKIO_API_URL` | No | Override the API base URL. Defaults to `https://api.honkio.ca`. Only needed for self-hosting or local development. |
158
+
159
+ ### Keeping your key out of git
160
+
161
+ `.mcp.json` and `.vscode/mcp.json` are usually committed. An API key pasted into one is a live credential in your repository history. Either keep those files untracked, or reference an environment variable your shell already exports and add the file to `.gitignore`.
162
+
163
+ If a key does leak, revoke it immediately at <https://honkio.ca/dashboard/keys> — a revoked key stops working at once.
164
+
165
+ ---
166
+
167
+ ## Tools
168
+
169
+ ### Messages
170
+ | Tool | Description |
171
+ |---|---|
172
+ | `send_sms` | Send an SMS from one of your numbers. Enforces CASL consent unless overridden. |
173
+ | `list_messages` | List messages, filterable by number, status, direction and date. |
174
+ | `get_message` | Full detail for one message, including delivery status and cost. |
175
+
176
+ ### Phone verification (OTP)
177
+ | Tool | Description |
178
+ |---|---|
179
+ | `start_verification` | Send a one-time code to a phone number. |
180
+ | `check_verification` | Submit a code to verify it. |
181
+ | `get_verification` | Status of a single verification attempt. |
182
+ | `list_verifications` | List verification attempts. |
183
+
184
+ Verification is billed per message plus a per-verification surcharge. In test mode the code is always `000000`, padded to the requested length.
185
+
186
+ ### Phone numbers
187
+ | Tool | Description |
188
+ |---|---|
189
+ | `search_phone_numbers` | Search available Canadian numbers by area code. |
190
+ | `provision_phone_number` | Purchase a number. **Charges an upfront fee plus monthly rent.** |
191
+ | `list_phone_numbers` | List the numbers on your account. |
192
+ | `get_phone_number` | Detail for one number. |
193
+ | `release_phone_number` | Release a number and stop its recurring rent. |
194
+
195
+ ### CASL compliance
196
+ | Tool | Description |
197
+ |---|---|
198
+ | `record_consent` | Record express or implied consent. |
199
+ | `list_consents` | List consent records. |
200
+ | `check_consent` | Check whether a number has valid consent. |
201
+ | `revoke_consent` | Revoke consent for a number. |
202
+ | `record_opt_out` | Record an opt-out manually. |
203
+ | `list_opt_outs` | List opt-out records. |
204
+
205
+ ### DNCL — not available yet
206
+ | Tool | Description |
207
+ |---|---|
208
+ | `check_dncl` | Returns `501 DNCL_COMING_SOON`. |
209
+ | `batch_check_dncl` | Returns `501 DNCL_COMING_SOON`. |
210
+
211
+ CRTC Do Not Call List checking is not live. `dncl_exemptions` on `send_sms` is accepted but not yet acted upon.
212
+
213
+ ### Webhooks
214
+ | Tool | Description |
215
+ |---|---|
216
+ | `create_webhook` | Register an endpoint for delivery receipts and inbound messages. |
217
+ | `list_webhooks` | List registered webhooks. |
218
+ | `update_webhook` | Change a webhook's URL or subscribed events. |
219
+ | `delete_webhook` | Remove a webhook. |
220
+ | `list_webhook_deliveries` | Delivery attempts for a webhook, for debugging. |
221
+ | `list_webhook_dead_letters` | Deliveries that exhausted their retries. |
222
+ | `replay_webhook_dead_letter` | Retry a dead-lettered delivery. |
223
+ | `discard_webhook_dead_letter` | Drop a dead-lettered delivery. |
224
+ | `reactivate_webhook` | Re-enable a webhook disabled by repeated failures. |
225
+
226
+ ### Account and keys
227
+ | Tool | Description |
228
+ |---|---|
229
+ | `whoami` | Identify the account the API key belongs to — id, name, balance, status. |
230
+ | `get_account` | Account detail and credit balance. |
231
+ | `update_account` | Update the account name. |
232
+ | `get_usage` | Usage for a billing period. |
233
+ | `create_api_key` | Issue a new live or test key. |
234
+ | `rotate_api_key` | Replace a key, invalidating the old value. |
235
+ | `revoke_api_key` | Revoke a key immediately. |
236
+
237
+ > **`account_id` is optional on all of these.** Omit it and the server resolves your account from the API key, so *"show my usage for this month"* just works. Pass one explicitly only if you are deliberately targeting a different account. Use `whoami` if you want to see the id itself.
238
+
239
+ ### PIPEDA
240
+ | Tool | Description |
241
+ |---|---|
242
+ | `request_erasure` | Execute a right-to-erasure request for a phone number. |
243
+
244
+ ---
245
+
246
+ ## Resources
247
+
248
+ Readable by MCP clients that support resources:
249
+
250
+ | URI | Contents |
251
+ |---|---|
252
+ | `honkio://messages` | 20 most recent messages |
253
+ | `honkio://phone-numbers` | Your provisioned numbers |
254
+ | `honkio://consents` | Active CASL consent records |
255
+ | `honkio://webhooks` | Registered webhook endpoints |
256
+
257
+ ## Prompts
258
+
259
+ Guided multi-step workflows:
260
+
261
+ | Prompt | What it walks through |
262
+ |---|---|
263
+ | `send_compliant_sms` | Check consent, then send |
264
+ | `provision_canadian_number` | Search, then purchase |
265
+ | `setup_webhooks` | Register event notifications |
266
+ | `compliance_audit` | Full compliance check on a number |
267
+ | `handle_erasure_request` | Process a PIPEDA erasure request |
268
+
269
+ ---
270
+
271
+ ## Things to try
272
+
273
+ ```
274
+ Find me an available Toronto (416) number and tell me what it costs before buying anything.
275
+
276
+ Check whether +15145559876 has valid CASL consent, and if it does, text them that
277
+ their appointment is confirmed for 2pm tomorrow.
278
+
279
+ Start a phone verification for +16045551111, then check the code 123456 against it.
280
+
281
+ Set up a webhook at https://myapp.ca/webhooks/honkio for delivery receipts and
282
+ inbound messages.
283
+
284
+ Show me any webhook deliveries that failed and ended up in the dead-letter queue.
285
+ ```
286
+
287
+ ---
288
+
289
+ ## Spending money by accident
290
+
291
+ Two tools move real money on a live key:
292
+
293
+ - **`provision_phone_number`** charges an upfront fee and starts monthly rent. Rent keeps accruing until you call `release_phone_number`.
294
+ - **`send_sms`** and **`start_verification`** charge per segment against your balance.
295
+
296
+ Agents act on instructions that can be vaguer than you intended. If you are exploring, use a test key — the tools behave the same and charge nothing.
297
+
298
+ ---
299
+
300
+ ## Canadian compliance
301
+
302
+ - **CASL** — commercial messages need consent on record. Use `record_consent` before sending; `send_sms` enforces it unless you pass `skip_consent_check`. Express consent does not expire; implied consent expires two years after the last transaction.
303
+ - **DNCL** — CRTC Do Not Call List checking is not available yet and is not enforced.
304
+ - **PIPEDA** — customer data is **stored** in Canada (`ca-central-1`). Request processing currently runs on infrastructure outside Canada, so data crosses the border in transit; see the [privacy policy](https://honkio.ca/legal/privacy) for the full disclosure. Use `request_erasure` for right-to-erasure requests.
305
+
306
+ ---
307
+
308
+ ## Troubleshooting
309
+
310
+ | Symptom | Cause and fix |
311
+ |---|---|
312
+ | `Error [UNAUTHORIZED]` | Key is wrong, revoked, or `HONKIO_API_KEY` never reached the server. Check the `env` block in your config. |
313
+ | Tools do not appear in the agent | The client did not start the server. Confirm the path in `args` is absolute and that `dist/index.js` exists — run `npm run build` if it does not. Restart the client. |
314
+ | `Cannot find module …/dist/index.js` | You skipped `npm run build`, or the path is wrong. |
315
+ | `Error [PAYMENT_REQUIRED]` | The account needs an initial top-up before live use. |
316
+ | `Error [ACCOUNT_NOT_VERIFIED]` | Live sending needs the account owner's phone verified. Do it in the dashboard. |
317
+ | `501 DNCL_COMING_SOON` | Expected. DNCL checking is not live yet. |
318
+ | Server starts then exits silently | That is normal when nothing is attached to stdin. It only means something is wrong if it prints an error. |
319
+
320
+ ---
321
+
322
+ ## Development
323
+
324
+ ```sh
325
+ npm run dev # run from source with tsx, no build step
326
+ npm run typecheck # types only
327
+ npm run build # compile to dist/
328
+ ```
329
+
330
+ Point the server at a local API with `HONKIO_API_URL=http://localhost:3000`.
331
+
332
+ ## License
333
+
334
+ MIT
@@ -0,0 +1,165 @@
1
+ /**
2
+ * HonkIO API client — thin wrapper around the REST API, used by all MCP tools.
3
+ */
4
+ export interface HonkioClientOptions {
5
+ apiKey: string;
6
+ baseUrl?: string;
7
+ }
8
+ export declare class HonkioError extends Error {
9
+ readonly status: number;
10
+ readonly code: string;
11
+ constructor(status: number, code: string, message: string);
12
+ }
13
+ export declare class HonkioClient {
14
+ private readonly apiKey;
15
+ private readonly baseUrl;
16
+ constructor(options: HonkioClientOptions);
17
+ private request;
18
+ sendMessage(params: {
19
+ from: string;
20
+ to: string;
21
+ body: string;
22
+ skip_consent_check?: boolean;
23
+ dncl_exemptions?: string[];
24
+ }): Promise<Record<string, unknown>>;
25
+ listMessages(query?: {
26
+ from?: string;
27
+ to?: string;
28
+ status?: string;
29
+ direction?: string;
30
+ page?: number;
31
+ limit?: number;
32
+ date_from?: string;
33
+ date_to?: string;
34
+ }): Promise<{
35
+ data: unknown[];
36
+ meta: unknown;
37
+ }>;
38
+ getMessage(id: string): Promise<Record<string, unknown>>;
39
+ searchPhoneNumbers(query?: {
40
+ area_code?: string;
41
+ limit?: number;
42
+ }): Promise<unknown[]>;
43
+ provisionPhoneNumber(phoneNumber: string): Promise<Record<string, unknown>>;
44
+ listPhoneNumbers(): Promise<{
45
+ data: unknown[];
46
+ }>;
47
+ getPhoneNumber(id: string): Promise<Record<string, unknown>>;
48
+ releasePhoneNumber(id: string): Promise<void>;
49
+ recordConsent(params: {
50
+ phone_number: string;
51
+ consent_type: 'express' | 'implied';
52
+ source_description?: string;
53
+ source_ip?: string;
54
+ source_url?: string;
55
+ relationship_type?: string;
56
+ last_transaction_date?: string;
57
+ }): Promise<Record<string, unknown>>;
58
+ listConsents(query?: {
59
+ phone_number?: string;
60
+ status?: string;
61
+ page?: number;
62
+ limit?: number;
63
+ }): Promise<{
64
+ data: unknown[];
65
+ }>;
66
+ checkConsent(phoneNumber: string): Promise<Record<string, unknown>>;
67
+ revokeConsent(phoneNumber: string): Promise<void>;
68
+ recordOptOut(params: {
69
+ phone_number: string;
70
+ from_number: string;
71
+ }): Promise<Record<string, unknown>>;
72
+ listOptOuts(query?: {
73
+ phone_number?: string;
74
+ from_number?: string;
75
+ page?: number;
76
+ limit?: number;
77
+ }): Promise<{
78
+ data: unknown[];
79
+ }>;
80
+ checkDncl(phoneNumber: string): Promise<Record<string, unknown>>;
81
+ batchCheckDncl(phoneNumbers: string[]): Promise<{
82
+ results: unknown[];
83
+ }>;
84
+ requestErasure(params: {
85
+ phone_number: string;
86
+ reason?: string;
87
+ }): Promise<Record<string, unknown>>;
88
+ startVerification(params: {
89
+ from: string;
90
+ to: string;
91
+ code_length?: 4 | 6 | 8;
92
+ ttl_minutes?: number;
93
+ app_name?: string;
94
+ }): Promise<Record<string, unknown>>;
95
+ checkVerification(verificationId: string, code: string): Promise<Record<string, unknown>>;
96
+ getVerification(verificationId: string): Promise<Record<string, unknown>>;
97
+ listVerifications(query?: {
98
+ phone_number?: string;
99
+ status?: string;
100
+ page?: number;
101
+ limit?: number;
102
+ }): Promise<{
103
+ data: unknown[];
104
+ }>;
105
+ createWebhook(params: {
106
+ url: string;
107
+ events: string[];
108
+ }): Promise<Record<string, unknown>>;
109
+ listWebhooks(): Promise<{
110
+ data: unknown[];
111
+ }>;
112
+ getWebhook(id: string): Promise<Record<string, unknown>>;
113
+ updateWebhook(id: string, params: {
114
+ url?: string;
115
+ events?: string[];
116
+ active?: boolean;
117
+ }): Promise<Record<string, unknown>>;
118
+ deleteWebhook(id: string): Promise<void>;
119
+ listWebhookDeliveries(webhookId: string, query?: {
120
+ limit?: number;
121
+ }): Promise<{
122
+ data: unknown[];
123
+ }>;
124
+ reactivateWebhook(webhookId: string): Promise<Record<string, unknown>>;
125
+ listWebhookDeadLetters(webhookId: string, query?: {
126
+ limit?: number;
127
+ include_replayed?: boolean;
128
+ }): Promise<{
129
+ data: unknown[];
130
+ }>;
131
+ replayWebhookDeadLetter(deadLetterId: string): Promise<Record<string, unknown>>;
132
+ discardWebhookDeadLetter(deadLetterId: string): Promise<void>;
133
+ /**
134
+ * Resolve the account the API key belongs to.
135
+ *
136
+ * The key does not carry its account id, and every other account route needs
137
+ * one, so without this an agent cannot use them at all — it would have to ask
138
+ * the user to fetch the id from the dashboard.
139
+ */
140
+ getCurrentAccount(): Promise<{
141
+ account: {
142
+ id: string;
143
+ } & Record<string, unknown>;
144
+ }>;
145
+ getAccount(id: string): Promise<Record<string, unknown>>;
146
+ updateAccount(id: string, params: {
147
+ name: string;
148
+ }): Promise<Record<string, unknown>>;
149
+ getUsage(id: string, query?: {
150
+ from?: string;
151
+ to?: string;
152
+ }): Promise<Record<string, unknown>>;
153
+ createApiKey(accountId: string, params?: {
154
+ mode?: 'live' | 'test';
155
+ label?: string;
156
+ }): Promise<Record<string, unknown>>;
157
+ revokeApiKey(accountId: string, keyId: string): Promise<void>;
158
+ rotateApiKey(accountId: string, keyId: string): Promise<{
159
+ key: string;
160
+ prefix: string;
161
+ mode: "live" | "test";
162
+ revoked_id: string;
163
+ }>;
164
+ }
165
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}