@coffrify/mcp 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/server.js +301 -83
  2. package/package.json +2 -2
package/dist/server.js CHANGED
@@ -3,8 +3,15 @@
3
3
  // src/server.ts
4
4
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
- import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
7
- import { Coffrify } from "@coffrify/sdk";
6
+ import {
7
+ CallToolRequestSchema,
8
+ ListToolsRequestSchema,
9
+ ListResourcesRequestSchema,
10
+ ReadResourceRequestSchema,
11
+ ListPromptsRequestSchema,
12
+ GetPromptRequestSchema
13
+ } from "@modelcontextprotocol/sdk/types.js";
14
+ import { Coffrify, COFFRIFY_EVENT_CATALOG } from "@coffrify/sdk";
8
15
  var apiKey = process.env.COFFRIFY_API_KEY;
9
16
  var apiUrl = process.env.COFFRIFY_API_URL ?? "https://api.coffrify.com";
10
17
  if (!apiKey) {
@@ -13,33 +20,42 @@ if (!apiKey) {
13
20
  }
14
21
  var coffrify = new Coffrify({ apiKey, apiUrl });
15
22
  var server = new Server(
16
- { name: "coffrify", version: "0.1.0" },
17
- { capabilities: { tools: {} } }
23
+ { name: "coffrify", version: "0.2.0" },
24
+ { capabilities: { tools: {}, resources: {}, prompts: {} } }
18
25
  );
26
+ var eventEnum = COFFRIFY_EVENT_CATALOG.map((e) => e.type);
19
27
  var TOOLS = [
20
28
  {
21
29
  name: "coffrify_list_transfers",
22
- description: "List recent encrypted file transfers in the workspace. Returns id, short_code, title, status, downloads count, expiration.",
30
+ description: "List recent encrypted file transfers in the workspace.",
23
31
  inputSchema: {
24
32
  type: "object",
25
33
  properties: {
26
- limit: { type: "number", description: "Max results (default 20)", default: 20 },
27
- status: { type: "string", description: "Filter by status: active|expired|deleted" }
34
+ limit: { type: "number", default: 20 },
35
+ status: { type: "string", description: "active|expired|deleted" }
28
36
  }
29
37
  }
30
38
  },
31
39
  {
32
- name: "coffrify_get_transfer",
33
- description: "Get full details of a transfer including files, settings, scan status.",
40
+ name: "coffrify_search_transfers",
41
+ description: "Search transfers by title substring or short_code prefix.",
34
42
  inputSchema: {
35
43
  type: "object",
36
- properties: { id: { type: "string", description: "Transfer ID (tr_...)" } },
37
- required: ["id"]
44
+ properties: {
45
+ query: { type: "string", description: "Substring (case-insensitive) to match against title or short_code" },
46
+ limit: { type: "number", default: 20 }
47
+ },
48
+ required: ["query"]
38
49
  }
39
50
  },
51
+ {
52
+ name: "coffrify_get_transfer",
53
+ description: "Get full details of a transfer (files, settings, scan status).",
54
+ inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] }
55
+ },
40
56
  {
41
57
  name: "coffrify_create_transfer",
42
- description: "Create a new encrypted file transfer. Returns the transfer + share URL. Files must be uploaded separately to the presigned URLs returned.",
58
+ description: "Create a new encrypted file transfer. Returns the transfer + share URL.",
43
59
  inputSchema: {
44
60
  type: "object",
45
61
  properties: {
@@ -59,119 +75,123 @@ var TOOLS = [
59
75
  max_downloads: { type: "number" },
60
76
  password: { type: "string" },
61
77
  transfer_title: { type: "string" },
62
- burn_after_read: { type: "boolean" }
78
+ burn_after_read: { type: "boolean" },
79
+ encryption_mode: { type: "string", enum: ["server_side", "e2e_v1"], default: "server_side" }
63
80
  },
64
81
  required: ["files"]
65
82
  }
66
83
  },
67
84
  {
68
85
  name: "coffrify_delete_transfer",
69
- description: "Delete a transfer (immediate, irreversible).",
86
+ description: "Delete a transfer (irreversible).",
87
+ inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] }
88
+ },
89
+ {
90
+ name: "coffrify_bulk_delete_transfers",
91
+ description: "Delete multiple transfers at once. Returns per-id success/failure.",
70
92
  inputSchema: {
71
93
  type: "object",
72
- properties: { id: { type: "string" } },
73
- required: ["id"]
94
+ properties: { ids: { type: "array", items: { type: "string" }, minItems: 1, maxItems: 100 } },
95
+ required: ["ids"]
74
96
  }
75
97
  },
76
98
  {
77
99
  name: "coffrify_list_webhooks",
78
- description: "List configured webhook endpoints in the workspace.",
100
+ description: "List configured webhook endpoints.",
79
101
  inputSchema: { type: "object", properties: {} }
80
102
  },
81
103
  {
82
104
  name: "coffrify_create_webhook",
83
- description: "Create a webhook subscription. Returns the webhook + a secret (shown once).",
105
+ description: "Create a webhook subscription. Returns the webhook + signing secret (shown once).",
84
106
  inputSchema: {
85
107
  type: "object",
86
108
  properties: {
87
109
  name: { type: "string" },
88
- url: { type: "string", description: "HTTPS endpoint" },
89
- events: {
90
- type: "array",
91
- items: {
92
- type: "string",
93
- enum: ["transfer.created", "transfer.downloaded", "transfer.expired", "transfer.deleted", "transfer.scanned", "transfer.cloned", "transfer.limit_reached"]
94
- }
95
- }
110
+ url: { type: "string" },
111
+ events: { type: "array", items: { type: "string", enum: eventEnum } },
112
+ description: { type: "string" }
96
113
  },
97
114
  required: ["name", "url", "events"]
98
115
  }
99
116
  },
100
117
  {
101
118
  name: "coffrify_test_webhook",
102
- description: "Send a test ping event to a webhook to verify the endpoint is reachable.",
103
- inputSchema: {
104
- type: "object",
105
- properties: { id: { type: "string" } },
106
- required: ["id"]
107
- }
119
+ description: "Send a test ping event to a webhook.",
120
+ inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] }
108
121
  },
109
122
  {
110
123
  name: "coffrify_list_webhook_deliveries",
111
- description: "List recent delivery attempts for a webhook (debug failures, see latency, replay).",
124
+ description: "List recent delivery attempts for a webhook.",
112
125
  inputSchema: {
113
126
  type: "object",
114
- properties: {
115
- webhook_id: { type: "string" },
116
- limit: { type: "number", default: 20 }
117
- },
127
+ properties: { webhook_id: { type: "string" }, limit: { type: "number", default: 20 } },
118
128
  required: ["webhook_id"]
119
129
  }
120
130
  },
121
131
  {
122
132
  name: "coffrify_replay_webhook_delivery",
123
- description: "Replay a past webhook delivery (creates a new event_id).",
133
+ description: "Replay a past webhook delivery.",
134
+ inputSchema: { type: "object", properties: { delivery_id: { type: "string" } }, required: ["delivery_id"] }
135
+ },
136
+ {
137
+ name: "coffrify_list_webhook_event_types",
138
+ description: "Return the catalog of every supported webhook event type with descriptions, families, stability, and required plan.",
124
139
  inputSchema: {
125
140
  type: "object",
126
- properties: { delivery_id: { type: "string" } },
127
- required: ["delivery_id"]
141
+ properties: {
142
+ family: { type: "string", description: "Filter by family: transfer|workspace|api_key|webhook|scim|saml|audit|gdpr|system|member|api_token" }
143
+ }
128
144
  }
129
145
  },
130
146
  {
131
147
  name: "coffrify_list_api_keys",
132
- description: "List API keys in the workspace (key values are hashed and never returned).",
148
+ description: "List API keys (key values are hashed and never returned).",
133
149
  inputSchema: { type: "object", properties: {} }
134
150
  },
135
151
  {
136
152
  name: "coffrify_create_api_key",
137
- description: "Create a new API key. Returns the key value ONCE \u2014 must be stored securely. Specify scopes for least-privilege access.",
153
+ description: "Create a new API key. Returns the key value ONCE \u2014 store securely. Specify scopes for least-privilege access.",
138
154
  inputSchema: {
139
155
  type: "object",
140
156
  properties: {
141
157
  name: { type: "string" },
142
158
  description: { type: "string" },
143
159
  environment: { type: "string", enum: ["live", "test"], default: "live" },
144
- scopes: {
145
- type: "array",
146
- items: { type: "string" },
147
- description: "e.g. ['transfers:read', 'transfers:write', 'webhooks:manage']"
148
- },
160
+ scopes: { type: "array", items: { type: "string" } },
149
161
  expires_in_days: { type: "number" },
150
- allowed_ips: { type: "array", items: { type: "string" }, description: "CIDR allowlist" }
162
+ allowed_ips: { type: "array", items: { type: "string" } }
151
163
  },
152
164
  required: ["name"]
153
165
  }
154
166
  },
155
167
  {
156
168
  name: "coffrify_revoke_api_key",
157
- description: "Revoke an API key (immediate, irreversible).",
169
+ description: "Revoke an API key (irreversible).",
170
+ inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] }
171
+ },
172
+ {
173
+ name: "coffrify_rotate_api_key",
174
+ description: "Rotate an API key \u2014 mints a new one with same scopes. Old key revokes after grace_days (default 7, max 30).",
158
175
  inputSchema: {
159
176
  type: "object",
160
- properties: { id: { type: "string" } },
177
+ properties: {
178
+ id: { type: "string" },
179
+ grace_days: { type: "number", default: 7 }
180
+ },
161
181
  required: ["id"]
162
182
  }
163
183
  },
164
184
  {
165
185
  name: "coffrify_query_audit_log",
166
- description: "Query the workspace audit log. Pro tier: 30 days. Entreprise: 365 days. Filter by action, actor, time range.",
186
+ description: "Query the workspace audit log. Filter by action, actor, time range. Supports relative since (e.g. '24h').",
167
187
  inputSchema: {
168
188
  type: "object",
169
189
  properties: {
170
- action: { type: "string", description: "e.g. 'transfer.downloaded'" },
190
+ action: { type: "string" },
171
191
  actor_id: { type: "string" },
172
192
  resource_type: { type: "string" },
173
- since: { type: "string", description: "ISO date or relative (e.g. 24h ago)" },
174
- until: { type: "string", description: "ISO date" },
193
+ since: { type: "string" },
194
+ until: { type: "string" },
175
195
  limit: { type: "number", default: 100 }
176
196
  }
177
197
  }
@@ -182,22 +202,196 @@ var TOOLS = [
182
202
  inputSchema: { type: "object", properties: {} }
183
203
  }
184
204
  ];
185
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
186
- tools: TOOLS
205
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
206
+ resources: [
207
+ { uri: "coffrify://transfers", name: "transfers", description: "All recent transfers (JSON list)", mimeType: "application/json" },
208
+ { uri: "coffrify://webhooks", name: "webhooks", description: "All webhook endpoints", mimeType: "application/json" },
209
+ { uri: "coffrify://api-keys", name: "api-keys", description: "All API keys (hashed)", mimeType: "application/json" },
210
+ { uri: "coffrify://events", name: "events", description: "Catalog of every supported webhook event type", mimeType: "application/json" },
211
+ { uri: "coffrify://workspace", name: "workspace", description: "Current workspace + scopes", mimeType: "application/json" },
212
+ { uri: "coffrify://audit", name: "audit", description: "Recent audit log entries (last 100)", mimeType: "application/json" }
213
+ ]
187
214
  }));
215
+ server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
216
+ const uri = req.params.uri;
217
+ let data;
218
+ if (uri === "coffrify://transfers") {
219
+ data = await coffrify.transfers.list({ limit: 50 });
220
+ } else if (uri.startsWith("coffrify://transfers/")) {
221
+ data = await coffrify.transfers.get(uri.split("/").pop());
222
+ } else if (uri === "coffrify://webhooks") {
223
+ data = await coffrify.webhooks.list();
224
+ } else if (uri.startsWith("coffrify://webhooks/")) {
225
+ const id = uri.split("/").pop();
226
+ const [hooks, deliveries] = await Promise.all([
227
+ coffrify.webhooks.list(),
228
+ coffrify.webhooks.deliveries(id, { limit: 10 }).catch(() => null)
229
+ ]);
230
+ const webhook = (hooks.webhooks ?? hooks.data ?? []).find((w) => w.id === id);
231
+ data = { webhook, recent_deliveries: deliveries };
232
+ } else if (uri === "coffrify://api-keys") {
233
+ data = await coffrify.apiKeys.list();
234
+ } else if (uri === "coffrify://events") {
235
+ data = { catalog: COFFRIFY_EVENT_CATALOG };
236
+ } else if (uri === "coffrify://workspace") {
237
+ data = await coffrify.http.request("GET", "/me");
238
+ } else if (uri === "coffrify://audit") {
239
+ data = await coffrify.audit.list({ limit: 100 });
240
+ } else {
241
+ throw new Error(`Unknown resource: ${uri}`);
242
+ }
243
+ return {
244
+ contents: [{ uri, mimeType: "application/json", text: JSON.stringify(data, null, 2) }]
245
+ };
246
+ });
247
+ var PROMPTS = [
248
+ {
249
+ name: "send_invoice",
250
+ description: "Compose and send an invoice file as a Coffrify transfer with sensible defaults.",
251
+ arguments: [
252
+ { name: "recipient_email", description: "Recipient email", required: true },
253
+ { name: "invoice_filename", description: "Filename of the invoice (e.g. INV-2026-001.pdf)", required: true },
254
+ { name: "expires_in_days", description: "Expiration window (default 30)", required: false }
255
+ ]
256
+ },
257
+ {
258
+ name: "audit_weekly",
259
+ description: "Pull the last 7 days of audit log and summarize unusual activity.",
260
+ arguments: []
261
+ },
262
+ {
263
+ name: "rotate_all_api_keys",
264
+ description: "Rotate every API key in the workspace with a 7-day grace window.",
265
+ arguments: []
266
+ },
267
+ {
268
+ name: "subscribe_to_security_events",
269
+ description: "Create a webhook subscribed to all security-relevant events (geo_blocked, password_failed, scan_infected, suspicious_usage, saml.login_failed).",
270
+ arguments: [
271
+ { name: "endpoint_url", description: "HTTPS endpoint to receive events", required: true }
272
+ ]
273
+ },
274
+ {
275
+ name: "investigate_transfer",
276
+ description: "Pull a transfer + its scan results + recent webhook deliveries to investigate an incident.",
277
+ arguments: [
278
+ { name: "short_code", description: "Short code or ID of the transfer", required: true }
279
+ ]
280
+ }
281
+ ];
282
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({ prompts: PROMPTS }));
283
+ server.setRequestHandler(GetPromptRequestSchema, async (req) => {
284
+ const { name, arguments: args = {} } = req.params;
285
+ const a = args;
286
+ switch (name) {
287
+ case "send_invoice":
288
+ return {
289
+ description: "Send an invoice via Coffrify",
290
+ messages: [{
291
+ role: "user",
292
+ content: {
293
+ type: "text",
294
+ text: `Send the file "${a.invoice_filename}" as a Coffrify transfer.
295
+ Recipient: ${a.recipient_email}.
296
+ Expiration: ${a.expires_in_days ?? "30"} days.
297
+ Use the coffrify_create_transfer tool with: title="Invoice ${a.invoice_filename}", expires_in_hours=${parseInt(a.expires_in_days ?? "30", 10) * 24}, max_downloads=3.
298
+ Then share the returned share_url with the recipient.`
299
+ }
300
+ }]
301
+ };
302
+ case "audit_weekly":
303
+ return {
304
+ description: "Weekly audit summary",
305
+ messages: [{
306
+ role: "user",
307
+ content: {
308
+ type: "text",
309
+ text: `Use coffrify_query_audit_log with since="7d" and limit=500 to fetch the last week of activity.
310
+ Summarize:
311
+ 1. Top 5 most frequent actions
312
+ 2. Any failed/denied actions and what they indicate
313
+ 3. Unusual IP addresses or geo distributions
314
+ 4. Any api_key.suspicious_usage or saml.login_failed events
315
+ Output a brief markdown report.`
316
+ }
317
+ }]
318
+ };
319
+ case "rotate_all_api_keys":
320
+ return {
321
+ description: "Rotate every API key with 7-day grace",
322
+ messages: [{
323
+ role: "user",
324
+ content: {
325
+ type: "text",
326
+ text: `1. Call coffrify_list_api_keys to get all active keys.
327
+ 2. For each key with status=active and not already rotated, call coffrify_rotate_api_key with grace_days=7.
328
+ 3. Report: { rotated_count, new_keys: [{ name, new_prefix, grace_until }] }.
329
+ Stress that the new key values are returned ONCE \u2014 they must be saved immediately.`
330
+ }
331
+ }]
332
+ };
333
+ case "subscribe_to_security_events":
334
+ return {
335
+ description: "Wire a webhook to all security events",
336
+ messages: [{
337
+ role: "user",
338
+ content: {
339
+ type: "text",
340
+ text: `Call coffrify_create_webhook with:
341
+ name = "Security events"
342
+ url = "${a.endpoint_url}"
343
+ events = ["transfer.password_failed", "transfer.geo_blocked", "transfer.scan_infected", "transfer.scan_quarantined",
344
+ "api_key.suspicious_usage", "api_key.expired", "api_key.revoked",
345
+ "saml.login_failed", "audit.policy_violated",
346
+ "webhook.endpoint_disabled", "workspace.payment_failed"]
347
+ Print the returned signing secret to the user \u2014 it's shown only once.`
348
+ }
349
+ }]
350
+ };
351
+ case "investigate_transfer":
352
+ return {
353
+ description: "Investigate a transfer incident",
354
+ messages: [{
355
+ role: "user",
356
+ content: {
357
+ type: "text",
358
+ text: `Investigate transfer "${a.short_code}":
359
+ 1. Use coffrify_search_transfers query="${a.short_code}" to locate it.
360
+ 2. Call coffrify_get_transfer with the id to fetch full details (scan_status, downloads, password_protected).
361
+ 3. Call coffrify_query_audit_log with resource_id=<that id> since="30d" to pull related audit entries.
362
+ 4. List any recent webhook deliveries that mention this transfer.
363
+ 5. Output a timeline + a diagnosis of what happened.`
364
+ }
365
+ }]
366
+ };
367
+ default:
368
+ throw new Error(`Unknown prompt: ${name}`);
369
+ }
370
+ });
371
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
188
372
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
189
373
  const { name, arguments: args = {} } = request.params;
190
374
  try {
191
375
  let result;
376
+ const a = args;
192
377
  switch (name) {
193
378
  case "coffrify_list_transfers":
194
- result = await coffrify.transfers.list(args);
379
+ result = await coffrify.transfers.list(a);
380
+ break;
381
+ case "coffrify_search_transfers": {
382
+ const list = await coffrify.transfers.list({ limit: 100 });
383
+ const arr = list.transfers ?? list.data ?? [];
384
+ const q = a.query.toLowerCase();
385
+ const matches = arr.filter(
386
+ (t) => (t.transfer_title ?? "").toLowerCase().includes(q) || (t.short_code ?? "").toLowerCase().startsWith(q)
387
+ ).slice(0, a.limit ?? 20);
388
+ result = { matches, total: matches.length };
195
389
  break;
390
+ }
196
391
  case "coffrify_get_transfer":
197
- result = await coffrify.transfers.get(args.id);
392
+ result = await coffrify.transfers.get(a.id);
198
393
  break;
199
- case "coffrify_create_transfer": {
200
- const a = args;
394
+ case "coffrify_create_transfer":
201
395
  result = await coffrify.transfers.create(a.files, {
202
396
  expires_in_hours: a.expires_in_hours,
203
397
  max_downloads: a.max_downloads,
@@ -206,68 +400,92 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
206
400
  burn_after_read: a.burn_after_read
207
401
  });
208
402
  break;
209
- }
210
403
  case "coffrify_delete_transfer":
211
- result = await coffrify.transfers.delete(args.id);
404
+ result = await coffrify.transfers.delete(a.id);
212
405
  break;
406
+ case "coffrify_bulk_delete_transfers": {
407
+ const out = [];
408
+ for (const id of a.ids) {
409
+ try {
410
+ await coffrify.transfers.delete(id);
411
+ out.push({ id, ok: true });
412
+ } catch (e) {
413
+ out.push({ id, ok: false, error: e?.message ?? String(e) });
414
+ }
415
+ }
416
+ result = { results: out, ok_count: out.filter((r) => r.ok).length };
417
+ break;
418
+ }
213
419
  case "coffrify_list_webhooks":
214
420
  result = await coffrify.webhooks.list();
215
421
  break;
216
- case "coffrify_create_webhook": {
217
- const a = args;
218
- result = await coffrify.webhooks.create({ name: a.name, url: a.url, events: a.events });
422
+ case "coffrify_create_webhook":
423
+ result = await coffrify.webhooks.create({
424
+ name: a.name,
425
+ url: a.url,
426
+ events: a.events,
427
+ description: a.description
428
+ });
219
429
  break;
220
- }
221
430
  case "coffrify_test_webhook":
222
- result = await coffrify.webhooks.test(args.id);
431
+ result = await coffrify.webhooks.test(a.id);
223
432
  break;
224
- case "coffrify_list_webhook_deliveries": {
225
- const a = args;
433
+ case "coffrify_list_webhook_deliveries":
226
434
  result = await coffrify.webhooks.deliveries(a.webhook_id, { limit: a.limit });
227
435
  break;
228
- }
229
436
  case "coffrify_replay_webhook_delivery":
230
- result = await coffrify.webhooks.replay(args.delivery_id);
437
+ result = await coffrify.webhooks.replay(a.delivery_id);
231
438
  break;
439
+ case "coffrify_list_webhook_event_types": {
440
+ const filtered = a.family ? COFFRIFY_EVENT_CATALOG.filter((e) => e.family === a.family) : COFFRIFY_EVENT_CATALOG;
441
+ result = { events: filtered, total: filtered.length };
442
+ break;
443
+ }
232
444
  case "coffrify_list_api_keys":
233
445
  result = await coffrify.apiKeys.list();
234
446
  break;
235
447
  case "coffrify_create_api_key":
236
- result = await coffrify.apiKeys.create(args);
448
+ result = await coffrify.apiKeys.create(a);
237
449
  break;
238
450
  case "coffrify_revoke_api_key":
239
- result = await coffrify.apiKeys.revoke(args.id);
451
+ result = await coffrify.apiKeys.revoke(a.id);
452
+ break;
453
+ case "coffrify_rotate_api_key":
454
+ result = await coffrify.http.request(
455
+ "POST",
456
+ `/api-keys/${encodeURIComponent(a.id)}/rotate`,
457
+ { grace_days: a.grace_days ?? 7 }
458
+ );
240
459
  break;
241
460
  case "coffrify_query_audit_log": {
242
- const a = args;
243
461
  let since = a.since;
244
462
  if (since && /^\d+[hdw]$/.test(since)) {
245
463
  const m = since.match(/^(\d+)([hdw])$/);
246
- const n = parseInt(m[1]);
464
+ const n = parseInt(m[1], 10);
247
465
  const ms = m[2] === "h" ? n * 36e5 : m[2] === "d" ? n * 864e5 : n * 7 * 864e5;
248
466
  since = new Date(Date.now() - ms).toISOString();
249
467
  }
250
468
  result = await coffrify.audit.list({ ...a, since });
251
469
  break;
252
470
  }
253
- case "coffrify_get_workspace_info": {
471
+ case "coffrify_get_workspace_info":
254
472
  result = await coffrify.http.request("GET", "/me");
255
473
  break;
256
- }
257
474
  default:
258
475
  throw new Error(`Unknown tool: ${name}`);
259
476
  }
260
- return {
261
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
262
- };
477
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
263
478
  } catch (e) {
264
479
  return {
265
- content: [{ type: "text", text: `Error: ${e?.message ?? "unknown"}
266
- ${JSON.stringify(e?.details ?? {}, null, 2)}` }],
480
+ content: [{
481
+ type: "text",
482
+ text: `Error: ${e?.message ?? "unknown"}
483
+ ${JSON.stringify(e?.details ?? {}, null, 2)}`
484
+ }],
267
485
  isError: true
268
486
  };
269
487
  }
270
488
  });
271
489
  var transport = new StdioServerTransport();
272
490
  await server.connect(transport);
273
- console.error("[coffrify-mcp] Server connected via stdio");
491
+ console.error("[coffrify-mcp] v0.2.0 connected via stdio (Tools + Resources + Prompts)");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffrify/mcp",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Coffrify MCP server — gives Claude/Cursor/Windsurf agents direct access to Coffrify (transfers, webhooks, audit, API keys).",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,7 +29,7 @@
29
29
  "dependencies": {
30
30
  "@modelcontextprotocol/sdk": "^1.0.0",
31
31
  "zod": "^3.23.8",
32
- "@coffrify/sdk": "0.3.6"
32
+ "@coffrify/sdk": "0.4.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "^22.0.0",