dropclaw 1.0.0 → 1.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.
package/README.md CHANGED
@@ -1,69 +1,116 @@
1
- # dropclaw
1
+ # DropClaw
2
2
 
3
- Permanent encrypted on-chain storage for AI agents. Store files on Monad blockchain with AES-256-GCM encryption.
3
+ **Permanent encrypted on-chain storage for AI agents on Monad blockchain with x402 payments.**
4
4
 
5
- ## Install
5
+ DropClaw gives AI agents a way to store files permanently on-chain. Files are compressed and encrypted client-side (AES-256-GCM) before upload — the server never sees plaintext. It's a blind encrypted relay. Files go directly on-chain as Monad calldata — DropClaw never stores user files. Encryption keys stay with the user.
6
6
 
7
+ ## Quick Start
8
+
9
+ ### 1. Install
7
10
  ```bash
8
11
  npm install dropclaw
9
12
  ```
10
13
 
11
- ## Usage
14
+ ### 2. Connect to Claude Code
15
+ ```bash
16
+ claude mcp add dropclaw -- npx dropclaw-mcp
17
+ ```
12
18
 
13
- ```js
14
- const { VaultClient } = require('dropclaw');
19
+ ### 3. Use Storage
15
20
 
16
- const client = new VaultClient({ gatewayUrl: 'https://dropclaw.cloud' });
21
+ Your agent now has 5 MCP tools:
17
22
 
18
- // Store a file
19
- const result = await client.store(fileBuffer, {
20
- paymentHeader: base64PaymentHeader
21
- });
22
- // result.skillFile JSON with tx hashes for reconstruction
23
- // result.key hex-encoded AES-256 encryption key (keep safe!)
24
- // result.fileId unique file identifier
23
+ | Tool | Description |
24
+ |------|-------------|
25
+ | `dropclaw_payment_options` | Get x402 payment requirements (MON, SOL, USDC) |
26
+ | `dropclaw_store` | Store encrypted file on Monad (requires payment) |
27
+ | `dropclaw_retrieve` | Retrieve and decrypt a file (free) |
28
+ | `dropclaw_pricing` | Get cost estimates for a file size |
29
+ | `dropclaw_list` | List locally stored files and keys |
25
30
 
26
- // Retrieve a file
27
- const original = await client.retrieve(result.skillFile, result.key);
28
- // original === your file, byte-for-byte identical
31
+ ## How It Works
29
32
 
30
- // Estimate cost
31
- const pricing = await client.estimateCost(fileBuffer.length);
32
- ```
33
+ 1. Agent compresses (zlib) and encrypts (AES-256-GCM) files client-side
34
+ 2. Calls `dropclaw_payment_options` to get payment addresses and amounts
35
+ 3. Sends payment on-chain (MON on Monad, SOL on Solana, or USDC on Base)
36
+ 4. Calls `dropclaw_store` with the payment tx hash and encrypted blob
37
+ 5. DropClaw chunks the blob into segments and stores each as calldata on Monad
38
+ 6. Agent receives a file ID — encryption key is saved locally in `~/.dropclaw/keys.json`
39
+ 7. Call `dropclaw_retrieve` with the file ID to fetch and decrypt (free)
40
+
41
+ ## Pricing
42
+
43
+ - **Storage:** $30 USD service fee + Monad gas costs
44
+ - **Retrieval:** Always free
45
+ - **Syntek subscribers:** [Syntek](https://github.com/timowhite88/farnsworth-syntek) subscribers ($100/90 days) get DropClaw access for Syntek memory uploads (gas only, no service fee)
46
+ - **50% of fees** go to FARNS token buybacks
47
+
48
+ ## Payment Options
49
+
50
+ | Network | Asset | Pay-To |
51
+ |---------|-------|--------|
52
+ | Monad (eip155:143) | MON (native) | `0xC86E4a0b90874d8081276AE13e830e23C726229e` |
53
+ | Solana | SOL (native) | `9cQMUBgEPzunpzkjQxV2TMKUUHPFqAHWzNGw9dBzZeSc` |
54
+ | Base (eip155:8453) | USDC | `0xC86E4a0b90874d8081276AE13e830e23C726229e` |
55
+
56
+ ## API Endpoints
33
57
 
34
- ## Async Upload Polling
58
+ | Method | Endpoint | Description |
59
+ |--------|----------|-------------|
60
+ | POST | `/vault/store` | Store encrypted file (x402 payment required) |
61
+ | POST | `/vault/retrieve/{id}` | Retrieve encrypted file (free) |
62
+ | GET | `/vault/pricing?size=N` | Cost estimates with live chain prices |
63
+ | GET | `/.well-known/x402` | x402 discovery manifest |
64
+ | GET | `/skill` | DropClaw skill file |
65
+ | GET | `/openai-tools` | OpenAI function calling definitions |
66
+ | GET | `/claude-tools` | Claude tool definitions |
35
67
 
36
- Large files are processed asynchronously. The SDK handles polling automatically:
68
+ ## Programmatic Usage
37
69
 
38
- ```js
39
- // store() automatically polls for completion
40
- const result = await client.store(largeFileBuffer, { paymentHeader });
70
+ ```javascript
71
+ const { DropClawClient } = require('dropclaw');
41
72
 
42
- // Or poll manually
43
- const { jobId } = await someAsyncOperation();
44
- const completed = await client.waitForCompletion(jobId, {
45
- pollInterval: 2000, // ms between polls (default: 2000)
46
- timeout: 300000 // max wait time in ms (default: 300000)
73
+ const client = new DropClawClient({
74
+ apiKey: 'your-api-key' // or set DROPCLAW_API_KEY env var
47
75
  });
48
- ```
49
76
 
50
- ## API
77
+ // Get pricing
78
+ const pricing = await client.pricing(1000000); // 1MB file
79
+ console.log(pricing.totalEstimateUSD); // ~$30.01
51
80
 
52
- ### `new VaultClient({ gatewayUrl })`
53
- Create a client connected to a DropClaw gateway.
81
+ // Store a file (after sending payment on-chain)
82
+ const result = await client.store({
83
+ content: Buffer.from('hello world'),
84
+ fileName: 'test.txt',
85
+ paymentTxHash: '0x...',
86
+ paymentNetwork: 'eip155:143'
87
+ });
88
+ console.log(result.fileId); // Save this!
54
89
 
55
- ### `client.store(fileBuffer, options)`
56
- Compress, encrypt, and upload a file. Returns `{ skillFile, key, fileId }`.
90
+ // Retrieve (free)
91
+ const file = await client.retrieve(result.fileId);
92
+ ```
57
93
 
58
- ### `client.retrieve(skillFile, key)`
59
- Download, decrypt, and decompress a file. Returns the original `Buffer`.
94
+ ## Credentials
60
95
 
61
- ### `client.waitForCompletion(jobId, options)`
62
- Poll for async job completion. Returns the completed job data.
96
+ Credentials are stored in `~/.dropclaw/vault.json`. Encryption keys are saved in `~/.dropclaw/keys.json`.
97
+
98
+ ```bash
99
+ npx dropclaw setup # Interactive setup
100
+ npx dropclaw status # Check connection
101
+ npx dropclaw revoke # Securely erase credentials
102
+ ```
63
103
 
64
- ### `client.estimateCost(fileSize)`
65
- Get pricing estimate for a file size in bytes.
104
+ Or use environment variables:
105
+ ```bash
106
+ export DROPCLAW_API_KEY=dc_...
107
+ export DROPCLAW_GATEWAY=https://dropclaw.cloud
108
+ ```
66
109
 
67
110
  ## License
68
111
 
69
- Proprietary — see LICENSE for details.
112
+ Proprietary — Farnsworth Labs. All rights reserved.
113
+
114
+ ---
115
+
116
+ [dropclaw.cloud](https://dropclaw.cloud)
package/SKILL.md ADDED
@@ -0,0 +1,119 @@
1
+ # DropClaw Storage Service
2
+
3
+ > Permanent encrypted on-chain storage for AI agents on Monad blockchain with x402 payments.
4
+
5
+ ## How It Works
6
+
7
+ DropClaw is a blind encrypted relay — **files go directly on-chain as Monad calldata**. We never store user files. The flow is:
8
+
9
+ 1. Client compresses (zlib) and encrypts (AES-256-GCM) the file locally
10
+ 2. Encrypted blob is chunked and written as calldata transactions on Monad
11
+ 3. The encryption key stays with YOU — DropClaw never sees it
12
+ 4. To retrieve: fetch the encrypted blob from chain, decrypt locally with your key
13
+
14
+ ## Endpoint
15
+
16
+ `https://dropclaw.cloud`
17
+
18
+ ## Authentication
19
+
20
+ Storage operations require an API key:
21
+ ```
22
+ Authorization: Bearer <api-key>
23
+ ```
24
+
25
+ Retrieval is always free and does not require authentication.
26
+
27
+ ## MCP Integration
28
+
29
+ ```bash
30
+ claude mcp add dropclaw -- npx dropclaw-mcp
31
+ ```
32
+
33
+ ### MCP Tools
34
+
35
+ | Tool | Description |
36
+ |------|-------------|
37
+ | `dropclaw_payment_options` | Get x402 payment requirements before storing a file |
38
+ | `dropclaw_store` | Encrypt and store file on Monad blockchain (requires payment tx hash) |
39
+ | `dropclaw_retrieve` | Retrieve and decrypt a stored file using your encryption key (free) |
40
+ | `dropclaw_pricing` | Get cost estimates for a given file size |
41
+ | `dropclaw_list` | List locally stored file IDs and encryption keys |
42
+
43
+ ### Key Management
44
+
45
+ When you store a file, `dropclaw_store` returns a `file_id` and saves the encryption key locally to `~/.dropclaw/keys.json`. **Both the file_id and key stay with you** — DropClaw does not store your keys. If you lose them, your data cannot be recovered.
46
+
47
+ When you retrieve a file, `dropclaw_retrieve` will:
48
+ 1. Fetch the encrypted blob from Monad blockchain
49
+ 2. Look up the encryption key in your local `keys.json` (or use the `encryption_key` parameter you provide)
50
+ 3. Decrypt (AES-256-GCM) and decompress (zlib inflate) the data
51
+ 4. Return the original plaintext content
52
+
53
+ ## REST API
54
+
55
+ ### Public (No Auth)
56
+
57
+ | Method | Path | Description |
58
+ |--------|------|-------------|
59
+ | `GET` | `/vault/pricing?size=N` | Cost estimate for N bytes |
60
+ | `GET` | `/.well-known/x402` | x402 discovery manifest |
61
+ | `GET` | `/skill` | This file |
62
+ | `GET` | `/openai-tools` | OpenAI function calling definitions |
63
+ | `GET` | `/claude-tools` | Claude tool definitions |
64
+
65
+ ### Authenticated
66
+
67
+ | Method | Path | Description |
68
+ |--------|------|-------------|
69
+ | `POST` | `/vault/store` | Store encrypted file — `{ content_base64, file_name, payment_tx_hash, payment_network }` |
70
+ | `POST` | `/vault/retrieve/{id}` | Retrieve encrypted blob from chain (free) |
71
+
72
+ ## x402 Payment Flow
73
+
74
+ 1. **Get pricing** — `GET /vault/pricing?size=<bytes>`
75
+ 2. **Send payment** — Transfer exact amount to the `payTo` address on your preferred chain
76
+ 3. **Store file** — `POST /vault/store` with `payment_tx_hash` and `payment_network`
77
+ 4. **Save your keys** — Store the returned `file_id` and your local encryption key securely
78
+ 5. **Retrieve anytime** — `POST /vault/retrieve/{id}` (free, no payment needed)
79
+
80
+ ## Payment Options
81
+
82
+ | Network | Chain ID | Asset | Pay-To Address |
83
+ |---------|----------|-------|---------------|
84
+ | Monad | eip155:143 | MON (native) | `0xC86E4a0b90874d8081276AE13e830e23C726229e` |
85
+ | Solana | solana:5eykt4... | SOL (native) | `9cQMUBgEPzunpzkjQxV2TMKUUHPFqAHWzNGw9dBzZeSc` |
86
+ | Base | eip155:8453 | USDC | `0xC86E4a0b90874d8081276AE13e830e23C726229e` |
87
+
88
+ ## Pricing
89
+
90
+ - **Service fee:** $30 USD + gas costs
91
+ - **Gas costs:** Variable (depends on file size and Monad gas prices)
92
+ - **Retrieval:** Always free
93
+ - **Syntek subscribers:** Gas only (no service fee) — Syntek subscription ($100/90 days) includes DropClaw access for Syntek memory uploads. Users still pay Monad gas fees.
94
+ - **50% of service fees** go to FARNS token buybacks
95
+
96
+ ## Encryption
97
+
98
+ - **Algorithm:** AES-256-GCM
99
+ - **Key generation:** Client-side, 32-byte random key — never transmitted to DropClaw
100
+ - **IV:** 12-byte random — prepended to ciphertext
101
+ - **Auth tag:** 16-byte GCM tag — prepended after IV
102
+ - **Compression:** zlib deflate before encryption
103
+ - **Wire format:** `[IV (12 bytes) | AuthTag (16 bytes) | Ciphertext]` → base64
104
+ - **On-chain storage:** Encrypted blob chunked into segments, stored as Monad calldata
105
+ - **Zero-knowledge:** Server never sees plaintext data or encryption keys
106
+
107
+ ## Example Usage
108
+
109
+ ```bash
110
+ # Get pricing for 1MB file
111
+ curl https://dropclaw.cloud/vault/pricing?size=1000000
112
+
113
+ # Check x402 discovery
114
+ curl https://dropclaw.cloud/.well-known/x402
115
+
116
+ # Get tool definitions
117
+ curl https://dropclaw.cloud/openai-tools
118
+ curl https://dropclaw.cloud/claude-tools
119
+ ```
package/dist/client.js ADDED
@@ -0,0 +1,190 @@
1
+ /**
2
+ * DropClaw v1.2.0
3
+ * (c) 2026 Farnsworth Labs — All rights reserved.
4
+ * PROPRIETARY AND CONFIDENTIAL. Unauthorized copying prohibited.
5
+ * This software is protected by international copyright law.
6
+ */
7
+
8
+ const crypto = require("crypto");
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+ const zlib = require("zlib");
12
+
13
+ const DEFAULT_GATEWAY = "https://dropclaw.cloud";
14
+ const VERSION = "1.2.0";
15
+
16
+ class DropClawClient {
17
+ constructor(opts = {}) {
18
+ this.gateway = (opts.gateway || process.env.DROPCLAW_GATEWAY || DEFAULT_GATEWAY).replace(/\/+$/, "");
19
+ this.apiKey = opts.apiKey || process.env.DROPCLAW_API_KEY || null;
20
+ this._vaultDir = path.join(
21
+ process.env.HOME || process.env.USERPROFILE || "/tmp",
22
+ ".dropclaw"
23
+ );
24
+
25
+ if (!this.apiKey) {
26
+ this._loadVaultKey();
27
+ }
28
+ if (!this.apiKey) {
29
+ throw new Error(
30
+ "API key required. Set DROPCLAW_API_KEY env var, pass apiKey in constructor, " +
31
+ "or run: npx dropclaw setup"
32
+ );
33
+ }
34
+ }
35
+
36
+ _loadVaultKey() {
37
+ try {
38
+ // Try new name first, fall back to legacy
39
+ let vaultPath = path.join(this._vaultDir, "vault.json");
40
+ if (!fs.existsSync(vaultPath)) {
41
+ vaultPath = path.join(this._vaultDir, "vault.enc");
42
+ }
43
+ if (fs.existsSync(vaultPath)) {
44
+ const data = JSON.parse(fs.readFileSync(vaultPath, "utf8"));
45
+ if (data.apiKey) this.apiKey = data.apiKey;
46
+ if (data.gateway) this.gateway = data.gateway;
47
+ }
48
+ } catch {}
49
+ }
50
+
51
+ _headers() {
52
+ return {
53
+ "Content-Type": "application/json",
54
+ "X-Client-Version": VERSION,
55
+ "Authorization": `Bearer ${this.apiKey}`,
56
+ };
57
+ }
58
+
59
+ async _handle(resp) {
60
+ if (!resp.ok) {
61
+ const body = await resp.text();
62
+ let msg;
63
+ try { msg = JSON.parse(body).error || body; } catch { msg = body; }
64
+ throw new Error(msg);
65
+ }
66
+ return resp.json();
67
+ }
68
+
69
+ async _get(endpoint) {
70
+ const headers = this._headers();
71
+ delete headers["Content-Type"];
72
+ const resp = await fetch(`${this.gateway}${endpoint}`, { method: "GET", headers });
73
+ return this._handle(resp);
74
+ }
75
+
76
+ async _post(endpoint, body = {}) {
77
+ const resp = await fetch(`${this.gateway}${endpoint}`, {
78
+ method: "POST",
79
+ headers: this._headers(),
80
+ body: JSON.stringify(body),
81
+ });
82
+ return this._handle(resp);
83
+ }
84
+
85
+ // --- Public API ---
86
+
87
+ async pricing(fileSize) {
88
+ const resp = await fetch(`${this.gateway}/vault/pricing?size=${fileSize}`);
89
+ return this._handle(resp);
90
+ }
91
+
92
+ async getPaymentOptions(fileSize) {
93
+ return this.pricing(fileSize);
94
+ }
95
+
96
+ async store(opts = {}) {
97
+ if (!opts.paymentTxHash) {
98
+ throw new Error("paymentTxHash required. Call pricing() first, send payment, then store().");
99
+ }
100
+ if (!opts.filePath && !opts.content && !opts.contentBase64) {
101
+ throw new Error("Provide filePath, content, or contentBase64");
102
+ }
103
+
104
+ let contentBase64;
105
+ let keyHex = null;
106
+ const fileName = opts.fileName || (opts.filePath ? path.basename(opts.filePath) : "untitled");
107
+
108
+ if (opts.filePath) {
109
+ const raw = fs.readFileSync(opts.filePath);
110
+ const compressed = zlib.deflateSync(raw);
111
+ const key = crypto.randomBytes(32);
112
+ const iv = crypto.randomBytes(12);
113
+ const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
114
+ const encrypted = Buffer.concat([cipher.update(compressed), cipher.final()]);
115
+ const tag = cipher.getAuthTag();
116
+ contentBase64 = Buffer.concat([iv, tag, encrypted]).toString("base64");
117
+ keyHex = key.toString("hex");
118
+ } else if (opts.content) {
119
+ const raw = Buffer.isBuffer(opts.content) ? opts.content : Buffer.from(opts.content);
120
+ const compressed = zlib.deflateSync(raw);
121
+ const key = crypto.randomBytes(32);
122
+ const iv = crypto.randomBytes(12);
123
+ const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
124
+ const encrypted = Buffer.concat([cipher.update(compressed), cipher.final()]);
125
+ const tag = cipher.getAuthTag();
126
+ contentBase64 = Buffer.concat([iv, tag, encrypted]).toString("base64");
127
+ keyHex = key.toString("hex");
128
+ } else if (opts.contentBase64) {
129
+ contentBase64 = opts.contentBase64;
130
+ }
131
+
132
+ const result = await this._post("/vault/store", {
133
+ content_base64: contentBase64,
134
+ file_name: fileName,
135
+ payment_tx_hash: opts.paymentTxHash,
136
+ payment_network: opts.paymentNetwork || "eip155:143",
137
+ });
138
+
139
+ // Save key with file_id AFTER successful API response
140
+ if (keyHex) {
141
+ const fileId = result.fileId || result.file_id || null;
142
+ this._saveKey(fileName, keyHex, fileId);
143
+ }
144
+
145
+ return result;
146
+ }
147
+
148
+ async retrieve(fileId) {
149
+ return this._post(`/vault/retrieve/${fileId}`, {});
150
+ }
151
+
152
+ async list() {
153
+ try {
154
+ const keysPath = path.join(this._vaultDir, "keys.json");
155
+ if (fs.existsSync(keysPath)) {
156
+ return JSON.parse(fs.readFileSync(keysPath, "utf8"));
157
+ }
158
+ } catch {}
159
+ return [];
160
+ }
161
+
162
+ _saveKey(fileName, keyHex, fileId) {
163
+ try {
164
+ if (!fs.existsSync(this._vaultDir)) {
165
+ fs.mkdirSync(this._vaultDir, { recursive: true });
166
+ }
167
+ const keysPath = path.join(this._vaultDir, "keys.json");
168
+ let keys = [];
169
+ try { keys = JSON.parse(fs.readFileSync(keysPath, "utf8")); } catch {}
170
+ keys.push({
171
+ fileId: fileId || null,
172
+ fileName,
173
+ key: keyHex,
174
+ storedAt: new Date().toISOString(),
175
+ });
176
+ fs.writeFileSync(keysPath, JSON.stringify(keys, null, 2));
177
+ } catch (e) {
178
+ console.error("WARNING: Failed to save encryption key locally:", e.message);
179
+ console.error("Your encryption key is:", keyHex);
180
+ console.error("SAVE THIS KEY — without it, your data cannot be recovered.");
181
+ }
182
+ }
183
+
184
+ async x402Discovery() {
185
+ const resp = await fetch(`${this.gateway}/.well-known/x402`);
186
+ return this._handle(resp);
187
+ }
188
+ }
189
+
190
+ module.exports = { DropClawClient };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * DropClaw Credential Manager v1.2.0
3
+ * (c) 2026 Farnsworth Labs — All rights reserved.
4
+ * PROPRIETARY AND CONFIDENTIAL. Unauthorized copying prohibited.
5
+ */
6
+ const fs=require("fs"),path=require("path");
7
+ const VD=path.join(process.env.HOME||process.env.USERPROFILE||"/tmp",".dropclaw");
8
+ const VP=path.join(VD,"vault.json");
9
+ const VP_LEGACY=path.join(VD,"vault.enc");
10
+ function load(){try{if(fs.existsSync(VP))return JSON.parse(fs.readFileSync(VP,"utf8"));if(fs.existsSync(VP_LEGACY))return JSON.parse(fs.readFileSync(VP_LEGACY,"utf8"));return null}catch{return null}}
11
+ function save(data){if(!fs.existsSync(VD))fs.mkdirSync(VD,{recursive:true});fs.writeFileSync(VP,JSON.stringify(data,null,2))}
12
+ function getApiKey(){const v=load();return v?.apiKey||process.env.DROPCLAW_API_KEY||null}
13
+ function getGateway(){const v=load();return v?.gateway||process.env.DROPCLAW_GATEWAY||"https://dropclaw.cloud"}
14
+ function saveKey(fileName,keyHex,fileId){if(!fs.existsSync(VD))fs.mkdirSync(VD,{recursive:true});const kp=path.join(VD,"keys.json");let ks=[];try{ks=JSON.parse(fs.readFileSync(kp,"utf8"))}catch{}ks.push({fileId:fileId||null,fileName,key:keyHex,storedAt:new Date().toISOString()});fs.writeFileSync(kp,JSON.stringify(ks,null,2))}
15
+ function getKeys(){const kp=path.join(VD,"keys.json");try{return JSON.parse(fs.readFileSync(kp,"utf8"))}catch{return[]}}
16
+ function revoke(){const files=[VP,VP_LEGACY,path.join(VD,"keys.json")];for(const f of files){if(fs.existsSync(f))fs.unlinkSync(f)}}
17
+ module.exports={load,save,getApiKey,getGateway,saveKey,getKeys,revoke};
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * DropClaw MCP Server v1.2.0
4
+ * (c) 2026 Farnsworth Labs — All rights reserved.
5
+ * PROPRIETARY AND CONFIDENTIAL. Unauthorized copying prohibited.
6
+ */
7
+ import{Server}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema,ListToolsRequestSchema}from"@modelcontextprotocol/sdk/types.js";import fs from"fs";import path from"path";import crypto from"crypto";import zlib from"zlib";
8
+ const G=process.env.DROPCLAW_GATEWAY||"https://dropclaw.cloud";const V="1.2.0";
9
+ const VD=path.join(process.env.HOME||process.env.USERPROFILE||"/tmp",".dropclaw");
10
+ function lk(){try{const p=path.join(VD,"vault.json");if(fs.existsSync(p)){return JSON.parse(fs.readFileSync(p,"utf8"))}}catch{}try{const p=path.join(VD,"vault.enc");if(fs.existsSync(p)){return JSON.parse(fs.readFileSync(p,"utf8"))}}catch{}return{}}
11
+ function hd(){const v=lk();const h={"Content-Type":"application/json","X-Client-Version":V};if(v.apiKey)h["Authorization"]=`Bearer ${v.apiKey}`;if(process.env.DROPCLAW_API_KEY)h["Authorization"]=`Bearer ${process.env.DROPCLAW_API_KEY}`;return h}
12
+ async function api(m,p,b){const u=`${G}${p}`;const o={method:m,headers:hd()};if(m==="GET")delete o.headers["Content-Type"];if(b)o.body=JSON.stringify(b);const r=await fetch(u,o);if(!r.ok){const t=await r.text();let msg;try{msg=JSON.parse(t).error||t}catch{msg=t}throw new Error(`${r.status}: ${msg}`)}return r.json()}
13
+ function saveKey(fileName,keyHex,fileId){if(!fs.existsSync(VD))fs.mkdirSync(VD,{recursive:true});const kp=path.join(VD,"keys.json");let ks=[];try{ks=JSON.parse(fs.readFileSync(kp,"utf8"))}catch{}ks.push({fileId:fileId||null,fileName,key:keyHex,storedAt:new Date().toISOString()});fs.writeFileSync(kp,JSON.stringify(ks,null,2))}
14
+ function getKeys(){const kp=path.join(VD,"keys.json");try{return JSON.parse(fs.readFileSync(kp,"utf8"))}catch{return[]}}
15
+ const server=new Server({name:"dropclaw-mcp",version:V},{capabilities:{tools:{}}});
16
+ server.setRequestHandler(ListToolsRequestSchema,async()=>({tools:[
17
+ {name:"dropclaw_payment_options",description:"STEP 1: Get x402 payment requirements before storing a file. Returns exact amounts in MON, SOL, and USDC with pay-to addresses. Regular usage: $30 + gas. Syntek subscribers: gas only.",inputSchema:{type:"object",properties:{file_size:{type:"number",description:"File size in bytes"}},required:["file_size"]}},
18
+ {name:"dropclaw_store",description:"STEP 2: Store a file permanently on Monad blockchain. Files go DIRECTLY on-chain as calldata — DropClaw never stores user files. The file is compressed (zlib) and encrypted (AES-256-GCM) client-side before upload. You MUST save the returned file_id and encryption key — these stay with YOU and are the only way to retrieve and decrypt later.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Absolute path to file to store"},content_base64:{type:"string",description:"Base64-encoded content (alternative to file_path — must be pre-encrypted)"},file_name:{type:"string",description:"Original filename"},payment_tx_hash:{type:"string",description:"Transaction hash of on-chain payment"},payment_network:{type:"string",enum:["eip155:143","solana","eip155:8453"],description:"Payment network",default:"eip155:143"}},required:["payment_tx_hash"]}},
19
+ {name:"dropclaw_retrieve",description:"Retrieve an encrypted file from Monad blockchain. FREE — no payment required. Returns the encrypted blob (base64). Decrypt with your encryption key using the wire format in SKILL.md.",inputSchema:{type:"object",properties:{file_id:{type:"string",description:"File ID returned from dropclaw_store"},save_to:{type:"string",description:"Path to save encrypted blob (optional)"}},required:["file_id"]}},
20
+ {name:"dropclaw_pricing",description:"Get cost estimates for storing a file. Returns $30 USD service fee plus estimated gas costs. Syntek subscribers pay gas only.",inputSchema:{type:"object",properties:{file_size:{type:"number",description:"File size in bytes"}},required:["file_size"]}},
21
+ {name:"dropclaw_list",description:"List all files stored via DropClaw with their encryption keys and file IDs saved locally.",inputSchema:{type:"object",properties:{}}}
22
+ ]}));
23
+ server.setRequestHandler(CallToolRequestSchema,async(req)=>{const{name,arguments:args}=req.params;try{
24
+ if(name==="dropclaw_payment_options"||name==="dropclaw_pricing"){const sz=args.file_size!==undefined?args.file_size:1000000;const r=await api("GET",`/vault/pricing?size=${sz}`);return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}
25
+ if(name==="dropclaw_store"){if(!args.file_path&&!args.content_base64){return{content:[{type:"text",text:"Error: Provide either file_path or content_base64"}],isError:true}}let cb64=args.content_base64;let keyHex=null;const fn=args.file_name||(args.file_path?path.basename(args.file_path):"untitled");if(args.file_path&&!cb64){const raw=fs.readFileSync(args.file_path);const comp=zlib.deflateSync(raw);const key=crypto.randomBytes(32);const iv=crypto.randomBytes(12);const c=crypto.createCipheriv("aes-256-gcm",key,iv);const enc=Buffer.concat([c.update(comp),c.final()]);const tag=c.getAuthTag();cb64=Buffer.concat([iv,tag,enc]).toString("base64");keyHex=key.toString("hex")}
26
+ const r=await api("POST","/vault/store",{content_base64:cb64,file_name:fn,payment_tx_hash:args.payment_tx_hash,payment_network:args.payment_network||"eip155:143"});if(keyHex&&r.fileId){saveKey(fn,keyHex,r.fileId)}else if(keyHex){saveKey(fn,keyHex,r.file_id||null)}
27
+ return{content:[{type:"text",text:JSON.stringify(r,null,2)+"\n\n⚠️ IMPORTANT: Save the file_id and encryption key. These stay with YOU — DropClaw does not store your keys. Without them, your data cannot be recovered."}]}}
28
+ if(name==="dropclaw_retrieve"){const r=await api("POST",`/vault/retrieve/${args.file_id}`,{});if(r.content_base64&&args.save_to){fs.writeFileSync(args.save_to,Buffer.from(r.content_base64,"base64"))}return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}
29
+ if(name==="dropclaw_list"){return{content:[{type:"text",text:JSON.stringify(getKeys(),null,2)}]}}
30
+ return{content:[{type:"text",text:`Unknown tool: ${name}`}],isError:true}}catch(e){return{content:[{type:"text",text:`Error: ${e.message}`}],isError:true}}});
31
+ async function main(){const t=new StdioServerTransport();await server.connect(t)}
32
+ main().catch(e=>{process.stderr.write(`DropClaw MCP fatal: ${e.message}\n`);process.exit(1)});
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * DropClaw Setup CLI v1.2.0
4
+ * (c) 2026 Farnsworth Labs — All rights reserved.
5
+ * PROPRIETARY AND CONFIDENTIAL. Unauthorized copying prohibited.
6
+ */
7
+ const fs=require("fs"),path=require("path"),readline=require("readline");
8
+ const V="1.2.0",G="https://dropclaw.cloud";
9
+ const VD=path.join(process.env.HOME||process.env.USERPROFILE||"/tmp",".dropclaw");
10
+ const VP=path.join(VD,"vault.json");
11
+ function rl(){return readline.createInterface({input:process.stdin,output:process.stdout})}
12
+ function ask(r,q){return new Promise(res=>{r.question(q,ans=>{res(ans.trim())})})}
13
+ async function setup(){
14
+ console.log(`\n DropClaw Setup v${V}\n ${"─".repeat(30)}\n`);
15
+ const r=rl();
16
+ const key=await ask(r," API Key (dc_...): ");
17
+ if(!key){console.log(" Cancelled.");r.close();return}
18
+ const gw=await ask(r,` Gateway [${G}]: `)||G;
19
+ r.close();
20
+ if(!fs.existsSync(VD))fs.mkdirSync(VD,{recursive:true});
21
+ const vault={apiKey:key,gateway:gw,createdAt:new Date().toISOString()};
22
+ fs.writeFileSync(VP,JSON.stringify(vault,null,2));
23
+ console.log(`\n Credentials saved to ${VP}`);
24
+ console.log(" Run 'npx dropclaw status' to verify.\n");
25
+ try{const resp=await fetch(`${gw}/vault/pricing?size=1000`);const d=await resp.json();console.log(` Connection OK — service fee: $${d.serviceFeeUSD}`)}catch(e){console.log(` Warning: Could not reach ${gw} — ${e.message}`)}
26
+ }
27
+ async function status(){
28
+ console.log(`\n DropClaw Status v${V}\n ${"─".repeat(30)}\n`);
29
+ if(!fs.existsSync(VP)){const legacy=path.join(VD,"vault.enc");if(!fs.existsSync(legacy)){console.log(" No credentials found. Run: npx dropclaw setup\n");return}}
30
+ let vault;
31
+ try{vault=JSON.parse(fs.readFileSync(fs.existsSync(VP)?VP:path.join(VD,"vault.enc"),"utf8"))}catch(e){console.log(` Error reading credentials: ${e.message}\n`);return}
32
+ const gw=vault.gateway||G;
33
+ console.log(` Gateway: ${gw}`);
34
+ console.log(` API Key: ${vault.apiKey?.slice(0,6)}...`);
35
+ console.log(` Created: ${vault.createdAt||"unknown"}`);
36
+ try{const resp=await fetch(`${gw}/vault/pricing?size=1000000`);const d=await resp.json();console.log(` Service: Online`);console.log(` Fee: $${d.serviceFeeUSD} + gas`);console.log(` Chains: MON, SOL, USDC`)}catch(e){console.log(` Service: Offline (${e.message})`)}
37
+ const kp=path.join(VD,"keys.json");
38
+ try{const ks=JSON.parse(fs.readFileSync(kp,"utf8"));console.log(` Local keys: ${ks.length} files stored`)}catch{console.log(" Local keys: 0 files")}
39
+ console.log();
40
+ }
41
+ async function revoke(){
42
+ const files=[VP,path.join(VD,"vault.enc"),path.join(VD,"keys.json")];
43
+ let erased=false;
44
+ for(const f of files){if(fs.existsSync(f)){fs.unlinkSync(f);erased=true}}
45
+ if(erased){console.log("\n Local credentials removed.");console.log(" Note: On-chain data is immutable and cannot be deleted.");console.log(" If you removed keys.json, encrypted on-chain files are unrecoverable.\n")}
46
+ else console.log("\n No credentials found.\n");
47
+ }
48
+ const cmd=process.argv[2]||"setup";
49
+ if(cmd==="setup")setup().catch(e=>console.error(e.message));
50
+ else if(cmd==="status")status().catch(e=>console.error(e.message));
51
+ else if(cmd==="revoke")revoke().catch(e=>console.error(e.message));
52
+ else{console.log(`\n DropClaw CLI v${V}\n\n Usage:\n npx dropclaw setup Setup credentials\n npx dropclaw status Check connection\n npx dropclaw revoke Erase credentials\n`)}
package/package.json CHANGED
@@ -1,17 +1,47 @@
1
1
  {
2
2
  "name": "dropclaw",
3
- "version": "1.0.0",
4
- "description": "DropClaw — Permanent Encrypted On-Chain Storage for AI Agents on Monad",
5
- "main": "stub.js",
3
+ "version": "1.2.0",
4
+ "description": "DropClaw — Permanent encrypted on-chain storage for AI agents on Monad blockchain with x402 payments.",
5
+ "main": "dist/client.js",
6
+ "bin": {
7
+ "dropclaw": "./dist/mcp/setup.js",
8
+ "dropclaw-mcp": "./dist/mcp/index.mjs"
9
+ },
10
+ "scripts": {
11
+ "setup": "node dist/mcp/setup.js setup",
12
+ "status": "node dist/mcp/setup.js status"
13
+ },
14
+ "dependencies": {
15
+ "@modelcontextprotocol/sdk": "^1.0.0",
16
+ "zod": "^3.22.0"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/timowhite88/dropclaw.git"
21
+ },
22
+ "homepage": "https://dropclaw.cloud",
23
+ "keywords": [
24
+ "dropclaw",
25
+ "blockchain",
26
+ "storage",
27
+ "encryption",
28
+ "monad",
29
+ "ai-agents",
30
+ "x402",
31
+ "on-chain",
32
+ "mcp",
33
+ "claude"
34
+ ],
6
35
  "files": [
7
- "stub.js",
8
- "README.md"
36
+ "dist/",
37
+ "SKILL.md"
9
38
  ],
10
- "keywords": ["dropclaw", "blockchain", "storage", "encryption", "monad", "ai-agents", "x402", "on-chain"],
11
- "author": "Farnsworth",
12
- "license": "Proprietary",
13
- "homepage": "https://dropclaw.cloud",
39
+ "license": "PROPRIETARY",
40
+ "author": "Farnsworth Labs <timowhite88@icloud.com>",
14
41
  "engines": {
15
42
  "node": ">=18.0.0"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
16
46
  }
17
47
  }
package/stub.js DELETED
@@ -1,15 +0,0 @@
1
- /**
2
- * DropClaw — Permanent Encrypted On-Chain Storage for AI Agents
3
- *
4
- * This is the official npm listing for DropClaw.
5
- * Full SDK access is available via the DropClaw gateway.
6
- *
7
- * Website: https://dropclaw.cloud
8
- * Docs: https://dropclaw.cloud/docs
9
- */
10
-
11
- module.exports = {
12
- name: "dropclaw",
13
- gateway: "https://dropclaw.cloud",
14
- description: "Permanent encrypted on-chain storage for AI agents on Monad.",
15
- };