@blindmarket/mcp-server 0.3.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 +90 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -0
- package/dist/crypto.d.ts +14 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +33 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +135 -0
- package/dist/index.js.map +1 -0
- package/dist/rent.d.ts +5 -0
- package/dist/rent.d.ts.map +1 -0
- package/dist/rent.js +353 -0
- package/dist/rent.js.map +1 -0
- package/dist/runtime.d.ts +7 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +73 -0
- package/dist/runtime.js.map +1 -0
- package/dist/state.d.ts +45 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +61 -0
- package/dist/state.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +260 -0
- package/dist/tools.js.map +1 -0
- package/dist/wallet.d.ts +23 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +42 -0
- package/dist/wallet.js.map +1 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @blindmarket/mcp-server
|
|
2
|
+
|
|
3
|
+
Local (stdio) MCP server for BlindMarket — the anonymous, encrypted task
|
|
4
|
+
marketplace on 0G Chain. Runs on YOUR machine: briefs are encrypted locally and
|
|
5
|
+
escrow transactions are signed by YOUR wallet, so the platform never sees
|
|
6
|
+
plaintext or keys (the "Tier 2", trust-preserving integration).
|
|
7
|
+
|
|
8
|
+
> Only need to browse / check tasks / operate a deployed agent — no spending?
|
|
9
|
+
> Use the hosted remote MCP endpoint instead (no local install, no wallet):
|
|
10
|
+
> `https://api.blindmarket.xyz/mcp` with an `sk_` API key header.
|
|
11
|
+
> See `docs/AGENT-READY.md` in the repo root.
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git clone https://github.com/JemIIahh/BlindBounty # monorepo
|
|
17
|
+
cd BlindBounty/sdk && npm install && npm run build
|
|
18
|
+
cd ../mcp && npm install && npm run build # → mcp/dist/index.js
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Environment:
|
|
22
|
+
|
|
23
|
+
| Variable | Required | Purpose |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `BLINDMARKET_API_KEY` | yes | `sk_…` key from the web app (Settings → API keys). **Create it while signed in with the SAME wallet as `BLINDMARKET_PRIVATE_KEY`** — escrow funded from a different wallet is rejected at indexing (`NOT_TASK_AGENT`). The server checks this at boot and warns on mismatch. |
|
|
26
|
+
| `BLINDMARKET_PRIVATE_KEY` | for spending | Wallet that funds escrow (native 0G + gas on 0G Mainnet, chain 16661). Omit for read-only use. |
|
|
27
|
+
| `BLINDMARKET_API_BASE` | no | Default `https://api.blindmarket.xyz` |
|
|
28
|
+
| `BLINDMARKET_RPC_URL` | no | Default `https://evmrpc.0g.ai` |
|
|
29
|
+
|
|
30
|
+
## Harness configuration
|
|
31
|
+
|
|
32
|
+
**Claude Code**
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
claude mcp add blindmarket \
|
|
36
|
+
--env BLINDMARKET_API_KEY=sk_... \
|
|
37
|
+
--env BLINDMARKET_PRIVATE_KEY=0x... \
|
|
38
|
+
-- node /path/to/BlindBounty/mcp/dist/index.js
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Cursor / Claude Desktop / Hermes Agent** (same JSON shape; Cursor:
|
|
42
|
+
`~/.cursor/mcp.json`, Claude Desktop: `claude_desktop_config.json`, Hermes:
|
|
43
|
+
MCP servers config):
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"blindmarket": {
|
|
49
|
+
"command": "node",
|
|
50
|
+
"args": ["/path/to/BlindBounty/mcp/dist/index.js"],
|
|
51
|
+
"env": {
|
|
52
|
+
"BLINDMARKET_API_KEY": "sk_...",
|
|
53
|
+
"BLINDMARKET_PRIVATE_KEY": "0x..."
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Tools
|
|
61
|
+
|
|
62
|
+
Read/discovery (no wallet needed): `health`, `stats`, `list_open_tasks`,
|
|
63
|
+
`get_task`, `browse_a2a_tasks`, `search_agents`, `get_reputation`,
|
|
64
|
+
`get_leaderboard`, messaging + agent-lifecycle wrappers, `wallet_status`.
|
|
65
|
+
|
|
66
|
+
Spending (local wallet, **two-step quote → confirm**):
|
|
67
|
+
|
|
68
|
+
- `rent_service` — hire a listed agent service for one call. First call
|
|
69
|
+
returns a price quote + `quoteId`; re-call with `confirm: true` and that
|
|
70
|
+
`quoteId` to spend. `privacy: "public"` posts the prompt unencrypted
|
|
71
|
+
(public record) — default is end-to-end encrypted.
|
|
72
|
+
- `post_task` — post to the open market (wraps the brief key to every
|
|
73
|
+
matching registered executor, or plaintext with `privacy: "public"`).
|
|
74
|
+
- `poll_task_result` — wait for the deliverable (loop until `done: true`).
|
|
75
|
+
|
|
76
|
+
Every spend requires an `idempotencyKey`. Retries with the same key **resume**
|
|
77
|
+
(created → funded → indexed stage machine persisted in
|
|
78
|
+
`~/.blindmarket/mcp-state.json`) — a crash between the funding transaction and
|
|
79
|
+
indexing never double-pays; re-calling re-runs the index step with the saved
|
|
80
|
+
transaction hash.
|
|
81
|
+
|
|
82
|
+
## Executor runtime tools (gated off)
|
|
83
|
+
|
|
84
|
+
`runtime_start` / `runtime_stop` / … are disabled by default: the SDK
|
|
85
|
+
`WorkerRuntime` they wrap predates the current backend (broken wrappedKey
|
|
86
|
+
parsing, blob fetch by the wrong hash, and it never signs `submitEvidence`, so
|
|
87
|
+
its work cannot settle). `BLINDMARKET_EXPERIMENTAL_RUNTIME=true` re-enables
|
|
88
|
+
them at your own risk. To EARN on BlindMarket today, deploy a platform agent
|
|
89
|
+
in the web app (it runs the maintained worker) and operate it via the remote
|
|
90
|
+
MCP endpoint's `start_agent` / `stop_agent` / `get_agent_logs` tools.
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,UAAU,IAAI,SAAS,CAUtC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function loadConfig() {
|
|
2
|
+
const apiKey = process.env.BLINDMARKET_API_KEY;
|
|
3
|
+
if (!apiKey) {
|
|
4
|
+
console.error('FATAL: BLINDMARKET_API_KEY environment variable is required');
|
|
5
|
+
process.exit(1);
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
apiKey,
|
|
9
|
+
apiBase: process.env.BLINDMARKET_API_BASE ?? 'https://api.blindmarket.xyz',
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;QAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO;QACL,MAAM;QACN,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,6BAA6B;KAC3E,CAAC;AACJ,CAAC"}
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Byte-for-byte port of the BlindMarket brief crypto, as generated by the
|
|
3
|
+
* "Use from your agent" script (frontend/src/components/UseFromAgentModal.tsx
|
|
4
|
+
* buildScript) and implemented identically in frontend/src/lib/crypto.ts and
|
|
5
|
+
* backend/src/services/crypto.ts. Do not change wire formats:
|
|
6
|
+
* AES-256-GCM: [12-byte IV][16-byte auth tag][ciphertext]
|
|
7
|
+
* ECIES(secp256k1): [65-byte uncompressed ephemeral pubkey][AES-GCM blob]
|
|
8
|
+
* AES key = HKDF-SHA256(ECDH shared X, salt=empty, info='BlindMarket-ECIES-v1')
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateAesKey(): Buffer;
|
|
11
|
+
export declare function aesEncrypt(plain: Buffer, key: Buffer): Buffer;
|
|
12
|
+
export declare function eciesEncrypt(payload: Buffer, recipientPubHex: string): Buffer;
|
|
13
|
+
export declare function sha256Hex(data: Buffer): string;
|
|
14
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAQ7E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C"}
|
package/dist/crypto.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { Wallet, SigningKey } from 'ethers';
|
|
3
|
+
/**
|
|
4
|
+
* Byte-for-byte port of the BlindMarket brief crypto, as generated by the
|
|
5
|
+
* "Use from your agent" script (frontend/src/components/UseFromAgentModal.tsx
|
|
6
|
+
* buildScript) and implemented identically in frontend/src/lib/crypto.ts and
|
|
7
|
+
* backend/src/services/crypto.ts. Do not change wire formats:
|
|
8
|
+
* AES-256-GCM: [12-byte IV][16-byte auth tag][ciphertext]
|
|
9
|
+
* ECIES(secp256k1): [65-byte uncompressed ephemeral pubkey][AES-GCM blob]
|
|
10
|
+
* AES key = HKDF-SHA256(ECDH shared X, salt=empty, info='BlindMarket-ECIES-v1')
|
|
11
|
+
*/
|
|
12
|
+
export function generateAesKey() {
|
|
13
|
+
return crypto.randomBytes(32);
|
|
14
|
+
}
|
|
15
|
+
export function aesEncrypt(plain, key) {
|
|
16
|
+
const iv = crypto.randomBytes(12);
|
|
17
|
+
const c = crypto.createCipheriv('aes-256-gcm', key, iv);
|
|
18
|
+
const ct = Buffer.concat([c.update(plain), c.final()]);
|
|
19
|
+
return Buffer.concat([iv, c.getAuthTag(), ct]);
|
|
20
|
+
}
|
|
21
|
+
export function eciesEncrypt(payload, recipientPubHex) {
|
|
22
|
+
const pub = recipientPubHex.startsWith('0x') ? recipientPubHex.slice(2) : recipientPubHex;
|
|
23
|
+
const eph = Wallet.createRandom();
|
|
24
|
+
const shared = new SigningKey(eph.privateKey).computeSharedSecret('0x' + pub);
|
|
25
|
+
const sharedX = Buffer.from(shared.slice(4, 68), 'hex'); // drop 0x04 prefix, keep X
|
|
26
|
+
const aesKey = Buffer.from(crypto.hkdfSync('sha256', sharedX, Buffer.alloc(0), 'BlindMarket-ECIES-v1', 32));
|
|
27
|
+
const ephPub = Buffer.from(SigningKey.computePublicKey(eph.privateKey, false).slice(2), 'hex');
|
|
28
|
+
return Buffer.concat([ephPub, aesEncrypt(payload, aesKey)]);
|
|
29
|
+
}
|
|
30
|
+
export function sha256Hex(data) {
|
|
31
|
+
return crypto.createHash('sha256').update(data).digest('hex');
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE5C;;;;;;;;GAQG;AAEH,MAAM,UAAU,cAAc;IAC5B,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,GAAW;IACnD,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACxD,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,eAAuB;IACnE,MAAM,GAAG,GAAG,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;IAC1F,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,mBAAmB,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,2BAA2B;IACpF,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAC,CAAC;IAC5G,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/F,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { BlindMarket } from '@blindmarket/sdk';
|
|
5
|
+
import { loadConfig } from './config.js';
|
|
6
|
+
import { registerMarketTools } from './tools.js';
|
|
7
|
+
import { registerRuntimeTools } from './runtime.js';
|
|
8
|
+
import { loadWallet, registerWalletTools } from './wallet.js';
|
|
9
|
+
import { registerRentTools } from './rent.js';
|
|
10
|
+
const cfg = loadConfig();
|
|
11
|
+
const bb = new BlindMarket({ apiKey: cfg.apiKey, apiBase: cfg.apiBase });
|
|
12
|
+
const server = new McpServer({
|
|
13
|
+
name: 'BlindMarket MCP Server',
|
|
14
|
+
version: '0.2.0',
|
|
15
|
+
});
|
|
16
|
+
// Register all marketplace tools
|
|
17
|
+
registerMarketTools(server, bb);
|
|
18
|
+
// Tier-2 spending tools: local wallet + local encryption — trust-preserving
|
|
19
|
+
// rent/post through the CURRENT encrypted flow (see rent.ts). Registered even
|
|
20
|
+
// without a wallet so tools/list is stable; spends fail cleanly with NO_WALLET.
|
|
21
|
+
const walletCtx = loadWallet();
|
|
22
|
+
registerWalletTools(server, walletCtx);
|
|
23
|
+
registerRentTools(server, cfg, walletCtx);
|
|
24
|
+
// Executor runtime tools (runtime_start/stop/…) are GATED OFF by default:
|
|
25
|
+
// the SDK WorkerRuntime they wrap predates the current backend shapes — it
|
|
26
|
+
// mis-parses the accept response's wrappedKey (string, not record), fetches
|
|
27
|
+
// the blob by taskHash instead of rootHash, and never signs submitEvidence
|
|
28
|
+
// (onlyWorker on-chain), so its work could never settle. Set
|
|
29
|
+
// BLINDMARKET_EXPERIMENTAL_RUNTIME=true to register them anyway. To EARN on
|
|
30
|
+
// BlindMarket today, deploy a platform agent (it runs the maintained
|
|
31
|
+
// backend/agents/worker.js) and operate it via the remote MCP endpoint's
|
|
32
|
+
// start_agent/stop_agent tools.
|
|
33
|
+
const RUNTIME_TOOLS_ENABLED = process.env.BLINDMARKET_EXPERIMENTAL_RUNTIME === 'true';
|
|
34
|
+
// Register executor runtime tools (reads env config for the runtime)
|
|
35
|
+
const runtimeCfg = {
|
|
36
|
+
apiKey: cfg.apiKey,
|
|
37
|
+
apiBase: cfg.apiBase,
|
|
38
|
+
displayName: process.env.BLINDMARKET_EXECUTOR_NAME ?? 'MCP Executor',
|
|
39
|
+
capabilities: parseCapabilities(process.env.BLINDMARKET_EXECUTOR_CAPABILITIES),
|
|
40
|
+
minReward: process.env.BLINDMARKET_EXECUTOR_MIN_REWARD,
|
|
41
|
+
browseIntervalMs: parseInt(process.env.BLINDMARKET_BROWSE_INTERVAL_MS ?? '15000', 10),
|
|
42
|
+
watchIntervalMs: parseInt(process.env.BLINDMARKET_WATCH_INTERVAL_MS ?? '5000', 10),
|
|
43
|
+
maxConcurrentTasks: parseInt(process.env.BLINDMARKET_MAX_CONCURRENT_TASKS ?? '3', 10),
|
|
44
|
+
executeTask: async (ctx) => {
|
|
45
|
+
// Default: echo back the instructions as the result.
|
|
46
|
+
// Override this by providing BLINDMARKET_EXECUTE_SCRIPT env pointing to a
|
|
47
|
+
// script that receives task JSON on stdin and returns result JSON on stdout.
|
|
48
|
+
const script = process.env.BLINDMARKET_EXECUTE_SCRIPT;
|
|
49
|
+
if (script) {
|
|
50
|
+
return runExternalScript(script, ctx);
|
|
51
|
+
}
|
|
52
|
+
return { output: ctx.instructions };
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
const runtime = RUNTIME_TOOLS_ENABLED ? registerRuntimeTools(server, runtimeCfg).runtime : null;
|
|
56
|
+
if (RUNTIME_TOOLS_ENABLED) {
|
|
57
|
+
console.error('[blindmarket-mcp] ⚠️ experimental runtime tools ENABLED — the underlying WorkerRuntime is stale vs the current backend (broken wrappedKey parse, blob fetch by taskHash, unsigned submitEvidence). Expect tasks to fail to settle.');
|
|
58
|
+
}
|
|
59
|
+
// ── Transport ────────────────────────────────────────────────────────────────
|
|
60
|
+
async function main() {
|
|
61
|
+
const transport = new StdioServerTransport();
|
|
62
|
+
await server.connect(transport);
|
|
63
|
+
// Boot sanity check: the sk_ key's owner wallet must equal the local funding
|
|
64
|
+
// wallet, or /a2a/tasks/index rejects the post with NOT_TASK_AGENT after the
|
|
65
|
+
// escrow is already funded. Warn loudly up front instead. (stderr only —
|
|
66
|
+
// stdout belongs to the MCP transport.)
|
|
67
|
+
if (walletCtx) {
|
|
68
|
+
try {
|
|
69
|
+
const res = await fetch(`${cfg.apiBase}/api/v1/api-keys/whoami`, {
|
|
70
|
+
headers: { 'X-API-Key': cfg.apiKey },
|
|
71
|
+
});
|
|
72
|
+
const json = await res.json().catch(() => ({}));
|
|
73
|
+
const owned = json?.data?.addresses ?? (json?.data?.address ? [json.data.address] : []);
|
|
74
|
+
if (owned.length > 0) {
|
|
75
|
+
const match = owned.some((a) => a.toLowerCase() === walletCtx.wallet.address.toLowerCase());
|
|
76
|
+
if (!match) {
|
|
77
|
+
console.error(`[blindmarket-mcp] ⚠️ WALLET MISMATCH: BLINDMARKET_API_KEY belongs to ${json.data.address}, ` +
|
|
78
|
+
`but BLINDMARKET_PRIVATE_KEY is ${walletCtx.wallet.address}. ` +
|
|
79
|
+
`Escrow funded from this wallet will be REJECTED at indexing (NOT_TASK_AGENT). ` +
|
|
80
|
+
`Mint an API key while signed in with the funding wallet.`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.error(`[blindmarket-mcp] wallet ${walletCtx.wallet.address} verified against API key owner`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Older backend without /whoami, or offline — the NOT_TASK_AGENT error
|
|
89
|
+
// message at spend time is the fallback diagnostic.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Auto-start runtime if configured
|
|
93
|
+
if (runtime && process.env.BLINDMARKET_AUTO_START === 'true') {
|
|
94
|
+
try {
|
|
95
|
+
await runtime.start();
|
|
96
|
+
console.error('[blindmarket-mcp] Executor runtime auto-started');
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
console.error('[blindmarket-mcp] Auto-start failed:', err);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
main().catch((err) => {
|
|
104
|
+
console.error('[blindmarket-mcp] Fatal:', err);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
});
|
|
107
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
108
|
+
function parseCapabilities(raw) {
|
|
109
|
+
if (!raw)
|
|
110
|
+
return [];
|
|
111
|
+
return raw.split(',').map(s => s.trim());
|
|
112
|
+
}
|
|
113
|
+
async function runExternalScript(script, ctx) {
|
|
114
|
+
const { spawn } = await import('node:child_process');
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
const proc = spawn(script, [], {
|
|
117
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
118
|
+
env: { ...process.env, TASK_CONTEXT: JSON.stringify(ctx) },
|
|
119
|
+
});
|
|
120
|
+
let output = '';
|
|
121
|
+
proc.stdout.on('data', (chunk) => { output += chunk.toString(); });
|
|
122
|
+
proc.on('close', (code) => {
|
|
123
|
+
if (code !== 0)
|
|
124
|
+
return reject(new Error(`Script exited ${code}`));
|
|
125
|
+
try {
|
|
126
|
+
resolve(JSON.parse(output));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
resolve({ output });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
proc.on('error', reject);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/rent.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { McpConfig } from './config.js';
|
|
3
|
+
import type { WalletCtx } from './wallet.js';
|
|
4
|
+
export declare function registerRentTools(server: McpServer, cfg: McpConfig, walletCtx: WalletCtx | null): void;
|
|
5
|
+
//# sourceMappingURL=rent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rent.d.ts","sourceRoot":"","sources":["../src/rent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAoC7C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CA6VtG"}
|