@centry-digital/bukku-mcp 1.1.0 → 2.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 (109) hide show
  1. package/build/config/env.d.ts +1 -0
  2. package/build/config/env.d.ts.map +1 -0
  3. package/build/config/env.js +2 -1
  4. package/build/index.d.ts +1 -0
  5. package/build/index.d.ts.map +1 -0
  6. package/build/index.js +1813 -44
  7. package/build/tools/custom/account-tools.d.ts +2 -1
  8. package/build/tools/custom/account-tools.d.ts.map +1 -0
  9. package/build/tools/custom/account-tools.js +2 -2
  10. package/build/tools/custom/contact-archive.d.ts +2 -1
  11. package/build/tools/custom/contact-archive.d.ts.map +1 -0
  12. package/build/tools/custom/contact-archive.js +2 -2
  13. package/build/tools/custom/control-panel-archive.d.ts +2 -1
  14. package/build/tools/custom/control-panel-archive.d.ts.map +1 -0
  15. package/build/tools/custom/control-panel-archive.js +2 -2
  16. package/build/tools/custom/file-upload.d.ts +2 -1
  17. package/build/tools/custom/file-upload.d.ts.map +1 -0
  18. package/build/tools/custom/file-upload.js +2 -2
  19. package/build/tools/custom/journal-entry-tools.d.ts +2 -1
  20. package/build/tools/custom/journal-entry-tools.d.ts.map +1 -0
  21. package/build/tools/custom/journal-entry-tools.js +2 -3
  22. package/build/tools/custom/location-tools.d.ts +2 -1
  23. package/build/tools/custom/location-tools.d.ts.map +1 -0
  24. package/build/tools/custom/location-tools.js +2 -2
  25. package/build/tools/custom/product-archive.d.ts +2 -1
  26. package/build/tools/custom/product-archive.d.ts.map +1 -0
  27. package/build/tools/custom/product-archive.js +2 -2
  28. package/build/tools/custom/reference-data.d.ts +3 -2
  29. package/build/tools/custom/reference-data.d.ts.map +1 -0
  30. package/build/tools/custom/reference-data.js +2 -2
  31. package/build/tools/factory.d.ts +2 -2
  32. package/build/tools/factory.d.ts.map +1 -0
  33. package/build/tools/factory.js +2 -2
  34. package/build/tools/registry.d.ts +2 -1
  35. package/build/tools/registry.d.ts.map +1 -0
  36. package/build/tools/registry.js +3 -41
  37. package/package.json +9 -22
  38. package/LICENSE +0 -21
  39. package/README.md +0 -269
  40. package/build/client/bukku-client.d.ts +0 -62
  41. package/build/client/bukku-client.js +0 -195
  42. package/build/errors/transform.d.ts +0 -14
  43. package/build/errors/transform.js +0 -141
  44. package/build/errors/transform.test.d.ts +0 -1
  45. package/build/errors/transform.test.js +0 -101
  46. package/build/tools/cache/reference-cache.d.ts +0 -42
  47. package/build/tools/cache/reference-cache.js +0 -63
  48. package/build/tools/configs/account.d.ts +0 -17
  49. package/build/tools/configs/account.js +0 -28
  50. package/build/tools/configs/bank-money-in.d.ts +0 -10
  51. package/build/tools/configs/bank-money-in.js +0 -22
  52. package/build/tools/configs/bank-money-out.d.ts +0 -10
  53. package/build/tools/configs/bank-money-out.js +0 -22
  54. package/build/tools/configs/bank-transfer.d.ts +0 -11
  55. package/build/tools/configs/bank-transfer.js +0 -23
  56. package/build/tools/configs/contact-group.d.ts +0 -11
  57. package/build/tools/configs/contact-group.js +0 -19
  58. package/build/tools/configs/contact.d.ts +0 -14
  59. package/build/tools/configs/contact.js +0 -25
  60. package/build/tools/configs/delivery-order.d.ts +0 -8
  61. package/build/tools/configs/delivery-order.js +0 -20
  62. package/build/tools/configs/file.d.ts +0 -18
  63. package/build/tools/configs/file.js +0 -26
  64. package/build/tools/configs/goods-received-note.d.ts +0 -8
  65. package/build/tools/configs/goods-received-note.js +0 -20
  66. package/build/tools/configs/journal-entry.d.ts +0 -14
  67. package/build/tools/configs/journal-entry.js +0 -26
  68. package/build/tools/configs/location.d.ts +0 -20
  69. package/build/tools/configs/location.js +0 -28
  70. package/build/tools/configs/product-bundle.d.ts +0 -18
  71. package/build/tools/configs/product-bundle.js +0 -29
  72. package/build/tools/configs/product-group.d.ts +0 -14
  73. package/build/tools/configs/product-group.js +0 -22
  74. package/build/tools/configs/product.d.ts +0 -24
  75. package/build/tools/configs/product.js +0 -35
  76. package/build/tools/configs/purchase-bill.d.ts +0 -9
  77. package/build/tools/configs/purchase-bill.js +0 -21
  78. package/build/tools/configs/purchase-credit-note.d.ts +0 -8
  79. package/build/tools/configs/purchase-credit-note.js +0 -20
  80. package/build/tools/configs/purchase-order.d.ts +0 -8
  81. package/build/tools/configs/purchase-order.js +0 -20
  82. package/build/tools/configs/purchase-payment.d.ts +0 -8
  83. package/build/tools/configs/purchase-payment.js +0 -20
  84. package/build/tools/configs/purchase-refund.d.ts +0 -8
  85. package/build/tools/configs/purchase-refund.js +0 -20
  86. package/build/tools/configs/sales-credit-note.d.ts +0 -8
  87. package/build/tools/configs/sales-credit-note.js +0 -20
  88. package/build/tools/configs/sales-invoice.d.ts +0 -8
  89. package/build/tools/configs/sales-invoice.js +0 -20
  90. package/build/tools/configs/sales-order.d.ts +0 -8
  91. package/build/tools/configs/sales-order.js +0 -20
  92. package/build/tools/configs/sales-payment.d.ts +0 -8
  93. package/build/tools/configs/sales-payment.js +0 -20
  94. package/build/tools/configs/sales-quote.d.ts +0 -8
  95. package/build/tools/configs/sales-quote.js +0 -20
  96. package/build/tools/configs/sales-refund.d.ts +0 -8
  97. package/build/tools/configs/sales-refund.js +0 -20
  98. package/build/tools/configs/tag-group.d.ts +0 -11
  99. package/build/tools/configs/tag-group.js +0 -22
  100. package/build/tools/configs/tag.d.ts +0 -11
  101. package/build/tools/configs/tag.js +0 -22
  102. package/build/tools/validation/double-entry.d.ts +0 -46
  103. package/build/tools/validation/double-entry.js +0 -66
  104. package/build/types/api-responses.d.ts +0 -21
  105. package/build/types/api-responses.js +0 -6
  106. package/build/types/bukku.d.ts +0 -93
  107. package/build/types/bukku.js +0 -11
  108. package/build/utils/logger.d.ts +0 -6
  109. package/build/utils/logger.js +0 -8
package/README.md DELETED
@@ -1,269 +0,0 @@
1
- # Bukku MCP Server
2
-
3
- [![npm version](https://img.shields.io/npm/v/@centry-digital/bukku-mcp)](https://www.npmjs.com/package/@centry-digital/bukku-mcp)
4
-
5
- An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that connects AI assistants to [Bukku](https://bukku.my), a Malaysian accounting platform. This gives your AI the ability to read, create, and manage your accounting data — invoices, bills, payments, contacts, products, and more.
6
-
7
- ## What can it do?
8
-
9
- With this MCP server connected, you can ask your AI things like:
10
-
11
- - "List my unpaid sales invoices"
12
- - "Create an invoice for RM 5,000 to Acme Corp for consulting services"
13
- - "Show me all purchase bills from last month"
14
- - "Record a bank transfer of RM 10,000 from Maybank to CIMB"
15
- - "Create a new contact for my supplier"
16
- - "Upload this receipt and attach it to the purchase bill"
17
-
18
- The server exposes **173 tools** covering the full Bukku API:
19
-
20
- | Category | Tools | What you can do |
21
- |----------|-------|-----------------|
22
- | **Sales** | 42 | Quotes, orders, delivery orders, invoices, credit notes, payments, refunds |
23
- | **Purchases** | 36 | Purchase orders, bills, credit notes, goods received notes, payments, refunds |
24
- | **Banking** | 18 | Money in, money out, bank transfers |
25
- | **Contacts** | 12 | Customers, suppliers, contact groups |
26
- | **Products** | 18 | Products, product bundles, product groups |
27
- | **Accounting** | 13 | Journal entries, chart of accounts |
28
- | **Files** | 3 | Upload and manage file attachments |
29
- | **Organisation** | 21 | Locations, tags, tag groups |
30
- | **Reference Data** | 10 | Tax codes, currencies, payment methods, terms, and more |
31
-
32
- ## Quick Start
33
-
34
- Get up and running in under 2 minutes.
35
-
36
- ### Prerequisites
37
-
38
- - [Node.js](https://nodejs.org) v18 or later
39
- - A [Bukku](https://bukku.my) account with API access enabled
40
- - An AI client that supports MCP (e.g. [Claude Desktop](https://claude.ai/download), [Claude Code](https://docs.anthropic.com/en/docs/claude-code))
41
-
42
- ### Step 1: Get your Bukku API token
43
-
44
- 1. Log into your Bukku account
45
- 2. Go to **Control Panel > Integrations > API Access**
46
- 3. Generate a new API token (or copy your existing one)
47
- 4. Note your company subdomain — e.g. `mycompany` from `mycompany.bukku.my`
48
-
49
- ### Step 2: Add to your AI client
50
-
51
- For Claude Desktop, open your config file:
52
- - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
53
- - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
54
-
55
- Add this configuration:
56
-
57
- ```json
58
- {
59
- "mcpServers": {
60
- "bukku": {
61
- "command": "npx",
62
- "args": ["-y", "@centry-digital/bukku-mcp"],
63
- "env": {
64
- "BUKKU_API_TOKEN": "your-token-here",
65
- "BUKKU_COMPANY_SUBDOMAIN": "your-subdomain"
66
- }
67
- }
68
- }
69
- }
70
- ```
71
-
72
- ### Step 3: Restart your AI client
73
-
74
- Quit and reopen Claude Desktop. That's it — you're ready to go!
75
-
76
- ## Installation
77
-
78
- ### npx (recommended)
79
-
80
- The quickest way to use the server is with `npx`. No installation needed — it downloads and runs the latest version automatically:
81
-
82
- ```bash
83
- npx @centry-digital/bukku-mcp
84
- ```
85
-
86
- This is what the Quick Start configuration uses. `npx` ensures you're always running the latest version without manual updates.
87
-
88
- ### npm global install
89
-
90
- If you prefer a persistent installation:
91
-
92
- ```bash
93
- npm install -g @centry-digital/bukku-mcp
94
- ```
95
-
96
- Then update your AI client configuration to use the installed command instead:
97
-
98
- ```json
99
- {
100
- "mcpServers": {
101
- "bukku": {
102
- "command": "bukku-mcp",
103
- "env": {
104
- "BUKKU_API_TOKEN": "your-token-here",
105
- "BUKKU_COMPANY_SUBDOMAIN": "your-subdomain"
106
- }
107
- }
108
- }
109
- }
110
- ```
111
-
112
- ## Configuration
113
-
114
- ### Environment Variables
115
-
116
- | Variable | Required | Description |
117
- |----------|----------|-------------|
118
- | `BUKKU_API_TOKEN` | Yes | Your Bukku API token from Control Panel > Integrations > API Access |
119
- | `BUKKU_COMPANY_SUBDOMAIN` | Yes | Your company subdomain (e.g. `mycompany` from `mycompany.bukku.my`) |
120
-
121
- ### Claude Desktop
122
-
123
- Open your configuration file:
124
- - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
125
- - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
126
-
127
- **Using npx (recommended):**
128
-
129
- ```json
130
- {
131
- "mcpServers": {
132
- "bukku": {
133
- "command": "npx",
134
- "args": ["-y", "@centry-digital/bukku-mcp"],
135
- "env": {
136
- "BUKKU_API_TOKEN": "your-token-here",
137
- "BUKKU_COMPANY_SUBDOMAIN": "your-subdomain"
138
- }
139
- }
140
- }
141
- }
142
- ```
143
-
144
- **If you installed globally:**
145
-
146
- ```json
147
- {
148
- "mcpServers": {
149
- "bukku": {
150
- "command": "bukku-mcp",
151
- "env": {
152
- "BUKKU_API_TOKEN": "your-token-here",
153
- "BUKKU_COMPANY_SUBDOMAIN": "your-subdomain"
154
- }
155
- }
156
- }
157
- }
158
- ```
159
-
160
- After updating the config, restart Claude Desktop.
161
-
162
- ### Claude Code
163
-
164
- Add to `.claude/settings.json` in your home directory or project:
165
-
166
- **Using npx (recommended):**
167
-
168
- ```json
169
- {
170
- "mcpServers": {
171
- "bukku": {
172
- "command": "npx",
173
- "args": ["-y", "@centry-digital/bukku-mcp"],
174
- "env": {
175
- "BUKKU_API_TOKEN": "your-token-here",
176
- "BUKKU_COMPANY_SUBDOMAIN": "your-subdomain"
177
- }
178
- }
179
- }
180
- }
181
- ```
182
-
183
- **If you installed globally:**
184
-
185
- ```json
186
- {
187
- "mcpServers": {
188
- "bukku": {
189
- "command": "bukku-mcp",
190
- "env": {
191
- "BUKKU_API_TOKEN": "your-token-here",
192
- "BUKKU_COMPANY_SUBDOMAIN": "your-subdomain"
193
- }
194
- }
195
- }
196
- }
197
- ```
198
-
199
- ### Other MCP Clients
200
-
201
- Any client that supports the [MCP stdio transport](https://modelcontextprotocol.io/docs/concepts/transports) can use this server. Use the `npx @centry-digital/bukku-mcp` command with the two environment variables shown above.
202
-
203
- ## Troubleshooting
204
-
205
- **"Configuration Error" on startup**
206
- - Check that both `BUKKU_API_TOKEN` and `BUKKU_COMPANY_SUBDOMAIN` are set in your client config
207
- - Verify the environment variables are inside the `"env"` object
208
-
209
- **"Token validation failed"**
210
- - Your API token may be invalid or expired
211
- - Log into Bukku and regenerate your token at Control Panel > Integrations > API Access
212
-
213
- **Server doesn't appear in your AI client**
214
- - Verify your configuration JSON syntax is correct (no trailing commas)
215
- - Make sure you've restarted your AI client after editing the config
216
- - Check that Node.js v18 or later is installed: `node --version`
217
-
218
- **"Could not resolve package" with npx**
219
- - Check that you have Node.js v18 or later installed
220
- - Verify your network connection and proxy settings if applicable
221
- - Try running `npm view @centry-digital/bukku-mcp` to confirm the package is accessible
222
-
223
- **Permission errors with global install**
224
- - Consider using `npx` instead (no installation needed)
225
- - Or fix npm permissions: [https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally)
226
-
227
- ## Development
228
-
229
- Want to contribute or run from source? Here's how to set up your development environment.
230
-
231
- ### Clone and build
232
-
233
- ```bash
234
- git clone https://github.com/centry-digital/bukku-mcp.git
235
- cd bukku-mcp
236
- npm install
237
- npm run build
238
- ```
239
-
240
- ### Commands
241
-
242
- ```bash
243
- npm run build # Compile TypeScript
244
- npm test # Run tests
245
- npm start # Start server (requires env vars)
246
- ```
247
-
248
- ### Project structure
249
-
250
- ```
251
- src/
252
- ├── client/ # Bukku API HTTP client
253
- ├── config/ # Environment validation
254
- ├── errors/ # Error handling and transformation
255
- ├── tools/ # MCP tool definitions (one folder per category)
256
- │ ├── sales/
257
- │ ├── purchases/
258
- │ ├── banking/
259
- │ ├── contacts/
260
- │ ├── products/
261
- │ ├── accounting/
262
- │ ├── files/
263
- │ └── ...
264
- └── index.ts # Server entry point
265
- ```
266
-
267
- ## License
268
-
269
- MIT
@@ -1,62 +0,0 @@
1
- import type { Env } from "../config/env.js";
2
- /**
3
- * HTTP client for Bukku API.
4
- * Handles authentication via Bearer token and Company-Subdomain header.
5
- * Base URL: https://api.bukku.my
6
- */
7
- export declare class BukkuClient {
8
- private readonly baseUrl;
9
- private readonly token;
10
- private readonly subdomain;
11
- constructor(env: Env);
12
- /**
13
- * Build headers for all requests.
14
- * CRITICAL: Never log the actual token value - use "Bearer ***" for debugging.
15
- */
16
- private getHeaders;
17
- /**
18
- * Map file extensions to MIME types for common file types.
19
- * Returns null for unknown extensions.
20
- */
21
- private getMimeType;
22
- /**
23
- * Build URL with query parameters.
24
- */
25
- private buildUrl;
26
- /**
27
- * GET request with optional query parameters.
28
- */
29
- get(path: string, params?: Record<string, string | number | undefined>): Promise<unknown>;
30
- /**
31
- * POST request with JSON body.
32
- */
33
- post(path: string, body: unknown): Promise<unknown>;
34
- /**
35
- * PUT request with JSON body.
36
- */
37
- put(path: string, body: unknown): Promise<unknown>;
38
- /**
39
- * PATCH request with JSON body (for status updates).
40
- */
41
- patch(path: string, body: unknown): Promise<unknown>;
42
- /**
43
- * DELETE request.
44
- */
45
- delete(path: string): Promise<void>;
46
- /**
47
- * POST multipart/form-data request for file uploads.
48
- * Reads file from disk and sends as multipart form data.
49
- * CRITICAL: Does NOT manually set Content-Type - fetch sets it automatically with boundary.
50
- *
51
- * @param path - API endpoint path
52
- * @param filePath - Absolute path to file on disk
53
- * @returns API response
54
- */
55
- postMultipart(path: string, filePath: string): Promise<unknown>;
56
- /**
57
- * Validate token on startup by making a lightweight API call.
58
- * Uses GET /contacts with page_size=1 to verify authentication.
59
- * Exits process if token is invalid (401).
60
- */
61
- validateToken(): Promise<void>;
62
- }
@@ -1,195 +0,0 @@
1
- import { log } from "../utils/logger.js";
2
- import { readFile } from "node:fs/promises";
3
- import { basename, extname } from "node:path";
4
- /**
5
- * HTTP client for Bukku API.
6
- * Handles authentication via Bearer token and Company-Subdomain header.
7
- * Base URL: https://api.bukku.my
8
- */
9
- export class BukkuClient {
10
- baseUrl = "https://api.bukku.my";
11
- token;
12
- subdomain;
13
- constructor(env) {
14
- this.token = env.BUKKU_API_TOKEN;
15
- this.subdomain = env.BUKKU_COMPANY_SUBDOMAIN;
16
- }
17
- /**
18
- * Build headers for all requests.
19
- * CRITICAL: Never log the actual token value - use "Bearer ***" for debugging.
20
- */
21
- getHeaders(includeContentType = false) {
22
- const headers = {
23
- Authorization: `Bearer ${this.token}`,
24
- "Company-Subdomain": this.subdomain,
25
- Accept: "application/json",
26
- };
27
- if (includeContentType) {
28
- headers["Content-Type"] = "application/json";
29
- }
30
- return headers;
31
- }
32
- /**
33
- * Map file extensions to MIME types for common file types.
34
- * Returns null for unknown extensions.
35
- */
36
- getMimeType(extension) {
37
- const mimeMap = {
38
- ".pdf": "application/pdf",
39
- ".png": "image/png",
40
- ".jpg": "image/jpeg",
41
- ".jpeg": "image/jpeg",
42
- ".gif": "image/gif",
43
- ".txt": "text/plain",
44
- ".csv": "text/csv",
45
- ".json": "application/json",
46
- ".xml": "application/xml",
47
- ".zip": "application/zip",
48
- };
49
- return mimeMap[extension.toLowerCase()] || null;
50
- }
51
- /**
52
- * Build URL with query parameters.
53
- */
54
- buildUrl(path, params) {
55
- const url = new URL(path, this.baseUrl);
56
- if (params) {
57
- for (const [key, value] of Object.entries(params)) {
58
- if (value !== undefined) {
59
- url.searchParams.append(key, String(value));
60
- }
61
- }
62
- }
63
- return url.toString();
64
- }
65
- /**
66
- * GET request with optional query parameters.
67
- */
68
- async get(path, params) {
69
- const url = this.buildUrl(path, params);
70
- const response = await fetch(url, {
71
- method: "GET",
72
- headers: this.getHeaders(),
73
- });
74
- if (!response.ok) {
75
- throw response;
76
- }
77
- return response.json();
78
- }
79
- /**
80
- * POST request with JSON body.
81
- */
82
- async post(path, body) {
83
- const url = this.buildUrl(path);
84
- const response = await fetch(url, {
85
- method: "POST",
86
- headers: this.getHeaders(true),
87
- body: JSON.stringify(body),
88
- });
89
- if (!response.ok) {
90
- throw response;
91
- }
92
- return response.json();
93
- }
94
- /**
95
- * PUT request with JSON body.
96
- */
97
- async put(path, body) {
98
- const url = this.buildUrl(path);
99
- const response = await fetch(url, {
100
- method: "PUT",
101
- headers: this.getHeaders(true),
102
- body: JSON.stringify(body),
103
- });
104
- if (!response.ok) {
105
- throw response;
106
- }
107
- return response.json();
108
- }
109
- /**
110
- * PATCH request with JSON body (for status updates).
111
- */
112
- async patch(path, body) {
113
- const url = this.buildUrl(path);
114
- const response = await fetch(url, {
115
- method: "PATCH",
116
- headers: this.getHeaders(true),
117
- body: JSON.stringify(body),
118
- });
119
- if (!response.ok) {
120
- throw response;
121
- }
122
- return response.json();
123
- }
124
- /**
125
- * DELETE request.
126
- */
127
- async delete(path) {
128
- const url = this.buildUrl(path);
129
- const response = await fetch(url, {
130
- method: "DELETE",
131
- headers: this.getHeaders(),
132
- });
133
- if (!response.ok) {
134
- throw response;
135
- }
136
- }
137
- /**
138
- * POST multipart/form-data request for file uploads.
139
- * Reads file from disk and sends as multipart form data.
140
- * CRITICAL: Does NOT manually set Content-Type - fetch sets it automatically with boundary.
141
- *
142
- * @param path - API endpoint path
143
- * @param filePath - Absolute path to file on disk
144
- * @returns API response
145
- */
146
- async postMultipart(path, filePath) {
147
- const url = this.buildUrl(path);
148
- // Read file from disk
149
- const fileBuffer = await readFile(filePath);
150
- const fileName = basename(filePath);
151
- const fileExtension = extname(filePath);
152
- // Determine MIME type, fallback to generic binary
153
- const mimeType = this.getMimeType(fileExtension) || "application/octet-stream";
154
- // Create File object and FormData
155
- const file = new File([fileBuffer], fileName, { type: mimeType });
156
- const form = new FormData();
157
- form.append("file", file);
158
- // Get auth headers WITHOUT Content-Type (fetch sets it with boundary)
159
- const headers = this.getHeaders(false);
160
- const response = await fetch(url, {
161
- method: "POST",
162
- headers,
163
- body: form,
164
- });
165
- if (!response.ok) {
166
- throw response;
167
- }
168
- return response.json();
169
- }
170
- /**
171
- * Validate token on startup by making a lightweight API call.
172
- * Uses GET /contacts with page_size=1 to verify authentication.
173
- * Exits process if token is invalid (401).
174
- */
175
- async validateToken() {
176
- try {
177
- await this.get("/contacts", { page_size: 1 });
178
- log("Token validated successfully");
179
- }
180
- catch (error) {
181
- if (error instanceof Response && error.status === 401) {
182
- log("Authentication Error\n");
183
- log("The provided BUKKU_API_TOKEN is invalid or expired.\n");
184
- log("Please check:");
185
- log(" 1. Token is copied correctly (no extra spaces)");
186
- log(" 2. API Access is enabled in Bukku Control Panel -> Integrations");
187
- log(" 3. Token has not been revoked or regenerated\n");
188
- process.exit(1);
189
- }
190
- // For other errors, log and exit
191
- log("Failed to validate token:", error);
192
- process.exit(1);
193
- }
194
- }
195
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * HTTP to MCP Error Transformation
3
- * Converts HTTP error responses into conversational MCP error messages
4
- */
5
- export interface MCPErrorResponse {
6
- isError: true;
7
- content: Array<{
8
- type: 'text';
9
- text: string;
10
- }>;
11
- [key: string]: unknown;
12
- }
13
- export declare function transformHttpError(status: number | null, body: unknown, operation: string): MCPErrorResponse;
14
- export declare function transformNetworkError(error: unknown, operation: string): MCPErrorResponse;
@@ -1,141 +0,0 @@
1
- /**
2
- * HTTP to MCP Error Transformation
3
- * Converts HTTP error responses into conversational MCP error messages
4
- */
5
- export function transformHttpError(status, body, operation) {
6
- // Handle authentication errors (401)
7
- if (status === 401) {
8
- return {
9
- isError: true,
10
- content: [
11
- {
12
- type: 'text',
13
- text: `Bukku authentication failed for "${operation}". The BUKKU_API_TOKEN environment variable is either missing or invalid. Please check your token and restart the server with the correct credentials.`,
14
- },
15
- ],
16
- };
17
- }
18
- // Handle permission errors (403)
19
- if (status === 403) {
20
- return {
21
- isError: true,
22
- content: [
23
- {
24
- type: 'text',
25
- text: `You don't have permission to "${operation}". Please check your Bukku account permissions and ensure you have access to this resource.`,
26
- },
27
- ],
28
- };
29
- }
30
- // Handle not found errors (404)
31
- if (status === 404) {
32
- return {
33
- isError: true,
34
- content: [
35
- {
36
- type: 'text',
37
- text: `I couldn't find that item when trying to "${operation}". Try listing the available items first to see what's accessible.`,
38
- },
39
- ],
40
- };
41
- }
42
- // Handle validation errors (400, 422)
43
- if (status === 400 || status === 422) {
44
- const parsedBody = body;
45
- const errors = parsedBody?.errors;
46
- if (errors && typeof errors === 'object') {
47
- // Multiple validation errors - show all at once
48
- const errorMessages = Object.entries(errors)
49
- .map(([field, messages]) => ` - ${field}: ${messages.join(', ')}`)
50
- .join('\n');
51
- return {
52
- isError: true,
53
- content: [
54
- {
55
- type: 'text',
56
- text: `Validation failed for "${operation}":\n${errorMessages}\n\nPlease fix these issues and try again.`,
57
- },
58
- ],
59
- };
60
- }
61
- else {
62
- // Single error message
63
- const message = parsedBody?.message || 'Invalid request';
64
- return {
65
- isError: true,
66
- content: [
67
- {
68
- type: 'text',
69
- text: `${message} when trying to "${operation}". Please check your input and try again.`,
70
- },
71
- ],
72
- };
73
- }
74
- }
75
- // Handle service unavailable (503)
76
- if (status === 503) {
77
- return {
78
- isError: true,
79
- content: [
80
- {
81
- type: 'text',
82
- text: `Bukku is temporarily unavailable while trying to "${operation}". Please try again in a few moments.`,
83
- },
84
- ],
85
- };
86
- }
87
- // Handle server errors (500+)
88
- if (status !== null && status >= 500) {
89
- // Include response body for debugging server errors
90
- // Often these contain validation errors that should have been 400s
91
- const parsedBody = body;
92
- const bodyText = body ? `\n\nServer response: ${JSON.stringify(parsedBody, null, 2)}` : '';
93
- return {
94
- isError: true,
95
- content: [
96
- {
97
- type: 'text',
98
- text: `An unexpected error occurred on Bukku's servers while trying to "${operation}". Please try again, and if the issue persists, contact Bukku support.${bodyText}`,
99
- },
100
- ],
101
- };
102
- }
103
- // Fallback for unknown status codes
104
- return {
105
- isError: true,
106
- content: [
107
- {
108
- type: 'text',
109
- text: `An error occurred while trying to "${operation}". Please check your request and try again.`,
110
- },
111
- ],
112
- };
113
- }
114
- export function transformNetworkError(error, operation) {
115
- // Check if it's a network-related error
116
- const errorMessage = error instanceof Error ? error.message : String(error);
117
- if (errorMessage.includes('fetch') ||
118
- errorMessage.includes('connect') ||
119
- errorMessage.includes('network') ||
120
- error instanceof TypeError) {
121
- return {
122
- isError: true,
123
- content: [
124
- {
125
- type: 'text',
126
- text: `Couldn't connect to Bukku while trying to "${operation}". Please check your internet connection and ensure the Bukku API is accessible.`,
127
- },
128
- ],
129
- };
130
- }
131
- // Fallback for unknown errors
132
- return {
133
- isError: true,
134
- content: [
135
- {
136
- type: 'text',
137
- text: `An unexpected error occurred while trying to "${operation}": ${errorMessage}. Please try again.`,
138
- },
139
- ],
140
- };
141
- }
@@ -1 +0,0 @@
1
- export {};