@coffrify/mcp 0.1.2

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 (3) hide show
  1. package/README.md +95 -0
  2. package/dist/server.js +273 -0
  3. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # @coffrify/mcp
2
+
3
+ **MCP server for Coffrify** — gives AI agents (Claude Desktop, Cursor, Windsurf, OpenAI Agents SDK) direct access to encrypted file transfer infrastructure.
4
+
5
+ ## What is MCP ?
6
+
7
+ [Model Context Protocol](https://modelcontextprotocol.io) is a standard for connecting AI agents to tools. With this server, agents can :
8
+
9
+ - Send encrypted file transfers
10
+ - Manage webhook subscriptions
11
+ - Query audit logs
12
+ - Create/revoke API keys
13
+ - All without leaving the chat.
14
+
15
+ ## Setup
16
+
17
+ ### Claude Desktop
18
+
19
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%/Claude/claude_desktop_config.json` (Windows) :
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "coffrify": {
25
+ "command": "npx",
26
+ "args": ["-y", "@coffrify/mcp"],
27
+ "env": {
28
+ "COFFRIFY_API_KEY": "cfy_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
29
+ }
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ Restart Claude. You should see "coffrify" tools in the 🔌 menu.
36
+
37
+ ### Cursor
38
+
39
+ Edit `~/.cursor/mcp.json` :
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "coffrify": {
45
+ "command": "npx",
46
+ "args": ["-y", "@coffrify/mcp"],
47
+ "env": { "COFFRIFY_API_KEY": "cfy_live_..." }
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ ### Cline / other MCP clients
54
+
55
+ Same pattern — `command: npx`, `args: ["-y", "@coffrify/mcp"]`, env contains `COFFRIFY_API_KEY`.
56
+
57
+ ## Available tools
58
+
59
+ | Tool | What it does |
60
+ |---|---|
61
+ | `coffrify_list_transfers` | List recent transfers |
62
+ | `coffrify_get_transfer` | Full details of one transfer |
63
+ | `coffrify_create_transfer` | Create transfer with files, expiry, password, etc. |
64
+ | `coffrify_delete_transfer` | Delete a transfer |
65
+ | `coffrify_list_webhooks` | List webhook subscriptions |
66
+ | `coffrify_create_webhook` | Create webhook + return secret |
67
+ | `coffrify_test_webhook` | Send test ping |
68
+ | `coffrify_list_webhook_deliveries` | Debug failures / see latency |
69
+ | `coffrify_replay_webhook_delivery` | Replay a past event |
70
+ | `coffrify_list_api_keys` | List API keys (hashes only) |
71
+ | `coffrify_create_api_key` | Create new key with scopes |
72
+ | `coffrify_revoke_api_key` | Revoke a key |
73
+ | `coffrify_query_audit_log` | Filter audit log by action, actor, time |
74
+ | `coffrify_get_workspace_info` | Current workspace + plan + scopes |
75
+
76
+ ## Example usage in Claude
77
+
78
+ ```
79
+ You: "Send my latest report to ada@lovelace.io, expire after 24h, password protect it."
80
+
81
+ Claude (uses coffrify_create_transfer):
82
+ → Creates the transfer
83
+ → Returns the share URL + token
84
+ → Optionally sets up a webhook to notify on download
85
+ ```
86
+
87
+ ## Auth
88
+
89
+ Generate an API key in your Coffrify dashboard with the scopes you want the agent to have. **Use a `cfy_test_` key for sandbox testing**, only use `cfy_live_` once you trust the agent.
90
+
91
+ We recommend a dedicated API key per agent installation, with `expires_in_days` set, so you can revoke it cleanly.
92
+
93
+ ## License
94
+
95
+ MIT
package/dist/server.js ADDED
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/server.ts
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
7
+ import { Coffrify } from "@coffrify/sdk";
8
+ var apiKey = process.env.COFFRIFY_API_KEY;
9
+ var apiUrl = process.env.COFFRIFY_API_URL ?? "https://api.coffrify.com";
10
+ if (!apiKey) {
11
+ console.error("[coffrify-mcp] COFFRIFY_API_KEY env var required");
12
+ process.exit(1);
13
+ }
14
+ var coffrify = new Coffrify({ apiKey, apiUrl });
15
+ var server = new Server(
16
+ { name: "coffrify", version: "0.1.0" },
17
+ { capabilities: { tools: {} } }
18
+ );
19
+ var TOOLS = [
20
+ {
21
+ name: "coffrify_list_transfers",
22
+ description: "List recent encrypted file transfers in the workspace. Returns id, short_code, title, status, downloads count, expiration.",
23
+ inputSchema: {
24
+ type: "object",
25
+ properties: {
26
+ limit: { type: "number", description: "Max results (default 20)", default: 20 },
27
+ status: { type: "string", description: "Filter by status: active|expired|deleted" }
28
+ }
29
+ }
30
+ },
31
+ {
32
+ name: "coffrify_get_transfer",
33
+ description: "Get full details of a transfer including files, settings, scan status.",
34
+ inputSchema: {
35
+ type: "object",
36
+ properties: { id: { type: "string", description: "Transfer ID (tr_...)" } },
37
+ required: ["id"]
38
+ }
39
+ },
40
+ {
41
+ 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.",
43
+ inputSchema: {
44
+ type: "object",
45
+ properties: {
46
+ files: {
47
+ type: "array",
48
+ items: {
49
+ type: "object",
50
+ properties: {
51
+ name: { type: "string" },
52
+ size: { type: "number" },
53
+ mime_type: { type: "string" }
54
+ },
55
+ required: ["name", "size"]
56
+ }
57
+ },
58
+ expires_in_hours: { type: "number", default: 168 },
59
+ max_downloads: { type: "number" },
60
+ password: { type: "string" },
61
+ transfer_title: { type: "string" },
62
+ burn_after_read: { type: "boolean" }
63
+ },
64
+ required: ["files"]
65
+ }
66
+ },
67
+ {
68
+ name: "coffrify_delete_transfer",
69
+ description: "Delete a transfer (immediate, irreversible).",
70
+ inputSchema: {
71
+ type: "object",
72
+ properties: { id: { type: "string" } },
73
+ required: ["id"]
74
+ }
75
+ },
76
+ {
77
+ name: "coffrify_list_webhooks",
78
+ description: "List configured webhook endpoints in the workspace.",
79
+ inputSchema: { type: "object", properties: {} }
80
+ },
81
+ {
82
+ name: "coffrify_create_webhook",
83
+ description: "Create a webhook subscription. Returns the webhook + a secret (shown once).",
84
+ inputSchema: {
85
+ type: "object",
86
+ properties: {
87
+ 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
+ }
96
+ },
97
+ required: ["name", "url", "events"]
98
+ }
99
+ },
100
+ {
101
+ 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
+ }
108
+ },
109
+ {
110
+ name: "coffrify_list_webhook_deliveries",
111
+ description: "List recent delivery attempts for a webhook (debug failures, see latency, replay).",
112
+ inputSchema: {
113
+ type: "object",
114
+ properties: {
115
+ webhook_id: { type: "string" },
116
+ limit: { type: "number", default: 20 }
117
+ },
118
+ required: ["webhook_id"]
119
+ }
120
+ },
121
+ {
122
+ name: "coffrify_replay_webhook_delivery",
123
+ description: "Replay a past webhook delivery (creates a new event_id).",
124
+ inputSchema: {
125
+ type: "object",
126
+ properties: { delivery_id: { type: "string" } },
127
+ required: ["delivery_id"]
128
+ }
129
+ },
130
+ {
131
+ name: "coffrify_list_api_keys",
132
+ description: "List API keys in the workspace (key values are hashed and never returned).",
133
+ inputSchema: { type: "object", properties: {} }
134
+ },
135
+ {
136
+ 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.",
138
+ inputSchema: {
139
+ type: "object",
140
+ properties: {
141
+ name: { type: "string" },
142
+ description: { type: "string" },
143
+ 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
+ },
149
+ expires_in_days: { type: "number" },
150
+ allowed_ips: { type: "array", items: { type: "string" }, description: "CIDR allowlist" }
151
+ },
152
+ required: ["name"]
153
+ }
154
+ },
155
+ {
156
+ name: "coffrify_revoke_api_key",
157
+ description: "Revoke an API key (immediate, irreversible).",
158
+ inputSchema: {
159
+ type: "object",
160
+ properties: { id: { type: "string" } },
161
+ required: ["id"]
162
+ }
163
+ },
164
+ {
165
+ 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.",
167
+ inputSchema: {
168
+ type: "object",
169
+ properties: {
170
+ action: { type: "string", description: "e.g. 'transfer.downloaded'" },
171
+ actor_id: { type: "string" },
172
+ resource_type: { type: "string" },
173
+ since: { type: "string", description: "ISO date or relative (e.g. 24h ago)" },
174
+ until: { type: "string", description: "ISO date" },
175
+ limit: { type: "number", default: 100 }
176
+ }
177
+ }
178
+ },
179
+ {
180
+ name: "coffrify_get_workspace_info",
181
+ description: "Get current workspace info: plan, scopes of the current API key, environment.",
182
+ inputSchema: { type: "object", properties: {} }
183
+ }
184
+ ];
185
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
186
+ tools: TOOLS
187
+ }));
188
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
189
+ const { name, arguments: args = {} } = request.params;
190
+ try {
191
+ let result;
192
+ switch (name) {
193
+ case "coffrify_list_transfers":
194
+ result = await coffrify.transfers.list(args);
195
+ break;
196
+ case "coffrify_get_transfer":
197
+ result = await coffrify.transfers.get(args.id);
198
+ break;
199
+ case "coffrify_create_transfer": {
200
+ const a = args;
201
+ result = await coffrify.transfers.create(a.files, {
202
+ expires_in_hours: a.expires_in_hours,
203
+ max_downloads: a.max_downloads,
204
+ password: a.password,
205
+ transfer_title: a.transfer_title,
206
+ burn_after_read: a.burn_after_read
207
+ });
208
+ break;
209
+ }
210
+ case "coffrify_delete_transfer":
211
+ result = await coffrify.transfers.delete(args.id);
212
+ break;
213
+ case "coffrify_list_webhooks":
214
+ result = await coffrify.webhooks.list();
215
+ 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 });
219
+ break;
220
+ }
221
+ case "coffrify_test_webhook":
222
+ result = await coffrify.webhooks.test(args.id);
223
+ break;
224
+ case "coffrify_list_webhook_deliveries": {
225
+ const a = args;
226
+ result = await coffrify.webhooks.deliveries(a.webhook_id, { limit: a.limit });
227
+ break;
228
+ }
229
+ case "coffrify_replay_webhook_delivery":
230
+ result = await coffrify.webhooks.replay(args.delivery_id);
231
+ break;
232
+ case "coffrify_list_api_keys":
233
+ result = await coffrify.apiKeys.list();
234
+ break;
235
+ case "coffrify_create_api_key":
236
+ result = await coffrify.apiKeys.create(args);
237
+ break;
238
+ case "coffrify_revoke_api_key":
239
+ result = await coffrify.apiKeys.revoke(args.id);
240
+ break;
241
+ case "coffrify_query_audit_log": {
242
+ const a = args;
243
+ let since = a.since;
244
+ if (since && /^\d+[hdw]$/.test(since)) {
245
+ const m = since.match(/^(\d+)([hdw])$/);
246
+ const n = parseInt(m[1]);
247
+ const ms = m[2] === "h" ? n * 36e5 : m[2] === "d" ? n * 864e5 : n * 7 * 864e5;
248
+ since = new Date(Date.now() - ms).toISOString();
249
+ }
250
+ result = await coffrify.audit.list({ ...a, since });
251
+ break;
252
+ }
253
+ case "coffrify_get_workspace_info": {
254
+ result = await coffrify.http.request("GET", "/me");
255
+ break;
256
+ }
257
+ default:
258
+ throw new Error(`Unknown tool: ${name}`);
259
+ }
260
+ return {
261
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
262
+ };
263
+ } catch (e) {
264
+ return {
265
+ content: [{ type: "text", text: `Error: ${e?.message ?? "unknown"}
266
+ ${JSON.stringify(e?.details ?? {}, null, 2)}` }],
267
+ isError: true
268
+ };
269
+ }
270
+ });
271
+ var transport = new StdioServerTransport();
272
+ await server.connect(transport);
273
+ console.error("[coffrify-mcp] Server connected via stdio");
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@coffrify/mcp",
3
+ "version": "0.1.2",
4
+ "description": "Coffrify MCP server — gives Claude/Cursor/Windsurf agents direct access to Coffrify (transfers, webhooks, audit, API keys).",
5
+ "type": "module",
6
+ "bin": {
7
+ "coffrify-mcp": "./dist/server.js"
8
+ },
9
+ "main": "./dist/server.js",
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "keywords": [
15
+ "coffrify",
16
+ "mcp",
17
+ "model-context-protocol",
18
+ "claude",
19
+ "ai-agents"
20
+ ],
21
+ "license": "MIT",
22
+ "homepage": "https://coffrify.com/integrations/mcp",
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "dependencies": {
30
+ "@modelcontextprotocol/sdk": "^1.0.0",
31
+ "zod": "^3.23.8",
32
+ "@coffrify/sdk": "0.3.6"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.0.0",
36
+ "tsup": "^8.0.0",
37
+ "tsx": "^4.20.0",
38
+ "typescript": "^5.0.0"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup src/server.ts --format esm --clean --shims",
42
+ "dev": "tsx src/server.ts",
43
+ "lint": "tsc --noEmit"
44
+ }
45
+ }