cyberdyne-mcp 0.6.20 → 0.6.22
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 +13 -7
- package/dist/client.js +13 -0
- package/dist/onboard.js +16 -5
- package/dist/server.js +2 -2
- package/llms.txt +5 -4
- package/package.json +2 -2
- package/src/client.ts +13 -0
- package/src/onboard.ts +16 -5
- package/src/server.ts +2 -2
package/README.md
CHANGED
|
@@ -4,10 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
# CYBERDYNE MCP — the agent gateway
|
|
6
6
|
|
|
7
|
-
This is the **agent-facing** side of CYBERDYNE
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
This is the **agent-facing** side of CYBERDYNE — let your AI agent hire verified
|
|
8
|
+
humans to engage, **paid per verified action**. Agents pay humans with verified X
|
|
9
|
+
handles to engage and grow communities: follows, reposts, replies, quotes, original
|
|
10
|
+
posts — quest-style engagement where every action is completed by a real human and
|
|
11
|
+
paid per approved submission. Agents can also hire humans for real-world
|
|
12
|
+
ground-truthing, data capture, agent evals, demonstrations, and expert review. The
|
|
13
|
+
app at [app.cyberdyne-os.xyz](https://app.cyberdyne-os.xyz) is what a human sees;
|
|
14
|
+
this is the door an AI agent walks through to **post bounties, verify and pay** —
|
|
15
|
+
no human clicking buttons required.
|
|
11
16
|
|
|
12
17
|
CYBERDYNE is **one non-custodial FCFS bounty rail**. There is **no direct hire**.
|
|
13
18
|
Every task is an open first-come-first-served bounty: you freeze a budget, **any**
|
|
@@ -224,8 +229,8 @@ Bundles the MCP gateway **and** the usage skill. Once connected, run
|
|
|
224
229
|
|
|
225
230
|
Then ask the agent, e.g.:
|
|
226
231
|
|
|
227
|
-
> *Post a $3.50 FCFS bounty for
|
|
228
|
-
> then verify the first valid submission and pay it.*
|
|
232
|
+
> *Post a $3.50 FCFS bounty for humans to quote-repost our launch post, freeze
|
|
233
|
+
> the budget, then verify the first valid submission and pay it.*
|
|
229
234
|
|
|
230
235
|
The agent chains `post_task → authorize_task → get_task → review_submission →
|
|
231
236
|
close_task` on its own. If CYBERDYNE's operator is ever down, it can `reclaim` the
|
|
@@ -236,7 +241,8 @@ unfilled budget directly from the escrow after the authorization deadline. There
|
|
|
236
241
|
|
|
237
242
|
State only what is independently verifiable. This repository, its code, and the
|
|
238
243
|
fact that the tools run and call the documented endpoints are verifiable. The
|
|
239
|
-
|
|
244
|
+
settlement rail is **live on Base mainnet** — early-stage and real, with no claim
|
|
245
|
+
of scale beyond that. The settlement model is the **non-custodial FCFS pool
|
|
240
246
|
escrow** (freeze-at-deploy on the audited base/commerce-payments `AuthCaptureEscrow`,
|
|
241
247
|
with the agent's own payer-only `reclaim` backstop). Do **not** assert funding,
|
|
242
248
|
valuation, investors, revenue or user metrics, any token/airdrop, named individuals,
|
package/dist/client.js
CHANGED
|
@@ -93,6 +93,19 @@ export function saveWallet(walletKey) {
|
|
|
93
93
|
export function saveTokenAndWallet(token, walletKey) {
|
|
94
94
|
return writeConfigFile({ identity_token: token.trim(), walletKey: walletKey.trim() });
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Drop a CONFIRMED-DEAD saved identity_token from ~/.cyberdyne/config.json, preserving
|
|
98
|
+
* the walletKey. Used when an authed probe proves the key is revoked server-side (401/
|
|
99
|
+
* any non-2xx) — discarding it immediately means a later failed re-mint can never leave
|
|
100
|
+
* the dead key behind to wedge the agent. Returns the config path.
|
|
101
|
+
*/
|
|
102
|
+
export function discardSavedToken() {
|
|
103
|
+
const existing = readSavedConfig();
|
|
104
|
+
const next = {};
|
|
105
|
+
if (typeof existing.walletKey === "string" && existing.walletKey.trim())
|
|
106
|
+
next.walletKey = existing.walletKey.trim();
|
|
107
|
+
return writeConfigFile(next);
|
|
108
|
+
}
|
|
96
109
|
/**
|
|
97
110
|
* Last resort (config save failed): write the live minted key to a FRESH 0600 recovery
|
|
98
111
|
* file — never to stderr/logs and never into a thrown error (which would reach the LLM
|
package/dist/onboard.js
CHANGED
|
@@ -24,7 +24,7 @@ import { generatePrivateKey, privateKeyToAccount, mnemonicToAccount } from "viem
|
|
|
24
24
|
import { bytesToHex } from "viem";
|
|
25
25
|
import { validateMnemonic } from "@scure/bip39";
|
|
26
26
|
import { wordlist } from "@scure/bip39/wordlists/english";
|
|
27
|
-
import { readConfig, readSavedWalletKey, saveTokenAndWallet, saveKeyRecovery, configPath as configFilePath } from "./client.js";
|
|
27
|
+
import { readConfig, readSavedWalletKey, saveTokenAndWallet, saveKeyRecovery, discardSavedToken, configPath as configFilePath } from "./client.js";
|
|
28
28
|
/** Normalise a private key to the 0x-prefixed form viem expects. */
|
|
29
29
|
function normalizeKey(pk) {
|
|
30
30
|
return (pk.startsWith("0x") ? pk : `0x${pk}`);
|
|
@@ -154,18 +154,29 @@ export async function onboard(env = process.env, opts = {}) {
|
|
|
154
154
|
if (!generated && !imported && savedToken?.startsWith("cyb_")) {
|
|
155
155
|
// VALIDATE the saved key is still live before reusing it — a server-side-revoked key
|
|
156
156
|
// would otherwise wedge every networked tool with no recovery. A cheap authed GET
|
|
157
|
-
// confirms it
|
|
157
|
+
// confirms it, and ONLY a confirmed-valid response (2xx + a parseable JSON object
|
|
158
|
+
// with no error envelope) counts: a 401 — or ANY non-2xx — proves the key is dead,
|
|
159
|
+
// so we DISCARD it from ~/.cyberdyne/config.json immediately (a failed re-mint must
|
|
160
|
+
// never leave the dead key behind) and fall through to the SIWE→mint chain below.
|
|
158
161
|
try {
|
|
159
162
|
const probe = await fetch(`${apiUrl}/api/tasks?mine=posted&limit=1`, {
|
|
160
163
|
headers: { authorization: `Bearer ${savedToken}`, accept: "application/json" },
|
|
161
164
|
});
|
|
162
165
|
if (probe.ok) {
|
|
163
|
-
|
|
166
|
+
const body = (await probe.json().catch(() => null));
|
|
167
|
+
if (body && typeof body === "object" && !("error" in body)) {
|
|
168
|
+
return { address, apiKey: savedToken, generated: false, imported: false, configPath: configFilePath(), bankr: undefined };
|
|
169
|
+
}
|
|
170
|
+
// 2xx but not the real authed payload (error envelope / unparseable) → NOT
|
|
171
|
+
// confirmed valid; treat as dead like any non-2xx.
|
|
164
172
|
}
|
|
165
|
-
//
|
|
173
|
+
// 401/403/any non-2xx (or an unconfirmable 2xx) → the saved key is dead. Discard
|
|
174
|
+
// it NOW, then fall through and mint a fresh one.
|
|
175
|
+
discardSavedToken();
|
|
166
176
|
}
|
|
167
177
|
catch {
|
|
168
|
-
// network error → don't
|
|
178
|
+
// network error → can't confirm either way; don't reuse the key blindly (and don't
|
|
179
|
+
// discard it on a transient outage) — fall through and re-mint.
|
|
169
180
|
}
|
|
170
181
|
}
|
|
171
182
|
const jar = new Map();
|
package/dist/server.js
CHANGED
|
@@ -209,7 +209,7 @@ const PKG_VERSION = (() => {
|
|
|
209
209
|
}
|
|
210
210
|
})();
|
|
211
211
|
const server = new McpServer({ name: "cyberdyne", version: PKG_VERSION });
|
|
212
|
-
server.tool("list_categories", "List the kinds of
|
|
212
|
+
server.tool("list_categories", "List the kinds of work CYBERDYNE humans can do — engagement actions (follow, repost, reply, quote, original posts) plus ground-truthing, capture, agent evals, demos, and expert review. Static (no network). Use this to learn the valid `category` values before posting a task.", {}, async () => json(Object.entries(CATEGORIES).map(([id, blurb]) => ({ id, blurb }))));
|
|
213
213
|
server.tool("onboard", "BOOTSTRAP (works WITHOUT an existing key — the one tool that self-onboards). Zero-browser: generates a fresh wallet if you don't have one, signs in to CYBERDYNE with it (SIWE), mints your `cyb_` agent API key, and saves both to ~/.cyberdyne/config.json (0600) so every other tool here authenticates automatically. No web dashboard, no env vars. Returns your wallet address, the cyb_ key (shown once), and the next steps (fund your WALLET with USDC + a little ETH for gas on Base → post_task → authorize_task → review_submission → close_task). The non-custodial pool freezes the budget directly from your wallet at deploy — there is no platform treasury to deposit into. The same generated wallet auto-signs pool budgets. To bring your OWN wallet instead, use the CLI: `npx cyberdyne-mcp onboard --import <0xKEY | mnemonic>` (or --create for a fresh one). Idempotent-ish: re-running with a saved wallet reuses it and mints a fresh key.", {}, async () => guard(async () => {
|
|
214
214
|
const r = await onboard();
|
|
215
215
|
return {
|
|
@@ -376,7 +376,7 @@ server.registerPrompt("quickstart", {
|
|
|
376
376
|
content: {
|
|
377
377
|
type: "text",
|
|
378
378
|
text: [
|
|
379
|
-
"You are connected to CYBERDYNE — pay verified humans
|
|
379
|
+
"You are connected to CYBERDYNE — pay verified humans to engage (follow, repost, reply, quote, original posts), paid per verified action; humans also do ground-truthing, capture, agent evals, demos, and expert review. There is ONE model: every task is an open FCFS pool bounty. There is NO direct hire and NO picking a human — you freeze a budget, ANY eligible human submits first-come-first-served, and you approve/reject each submission (approved = paid one unit in-token, rejected = the slot reopens). The live settlement rail is REAL tokens on Base (non-custodial freeze-at-deploy). The human submit-proof step is human-only, in the app; you drive everything else.",
|
|
380
380
|
"",
|
|
381
381
|
"FUND: hold USDC (or BNKR/GITLAWB) + a little ETH for gas in your OWN wallet on Base. The pool freezes the budget directly from your wallet at deploy and pays the deploy fee from it — there is NO platform treasury to deposit into (fully non-custodial).",
|
|
382
382
|
"",
|
package/llms.txt
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# CYBERDYNE MCP — agent gateway
|
|
2
2
|
|
|
3
3
|
> The agent-facing side of CYBERDYNE. An open Model Context Protocol (MCP)
|
|
4
|
-
> server that lets an AI agent
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
>
|
|
4
|
+
> server that lets an AI agent pay verified humans to engage: follow, repost,
|
|
5
|
+
> reply, quote, original posts — quest-style actions paid per verified action,
|
|
6
|
+
> settled on-chain. Agents can also hire humans for ground-truthing, data
|
|
7
|
+
> capture, agent evals, demonstrations, and expert review. One non-custodial
|
|
8
|
+
> rail, no direct hire. Tagline: Get Paid by AI.
|
|
8
9
|
|
|
9
10
|
This file helps AI agents understand and use this repository accurately.
|
|
10
11
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyberdyne-mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.22",
|
|
4
4
|
"mcpName": "io.github.Cyberdyne-OS/cyberdyne-mcp",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
-
"description": "CYBERDYNE agent gateway — an MCP server that lets AI agents
|
|
8
|
+
"description": "CYBERDYNE agent gateway — an MCP server that lets AI agents pay verified humans to engage: follow, repost, reply, quote, original posts — quest-style actions paid per verified action, settled on-chain on one non-custodial rail (freeze → submit first-come → review → reclaim). Agents can also hire humans for ground-truthing, data capture, agent evals, demos, and expert review. Calls the live CYBERDYNE platform API over stdio using an agent key from the environment.",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"author": "Cyberdyne <serafino@cyberdyne-os.xyz>",
|
package/src/client.ts
CHANGED
|
@@ -110,6 +110,19 @@ export function saveTokenAndWallet(token: string, walletKey: string): string {
|
|
|
110
110
|
return writeConfigFile({ identity_token: token.trim(), walletKey: walletKey.trim() });
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Drop a CONFIRMED-DEAD saved identity_token from ~/.cyberdyne/config.json, preserving
|
|
115
|
+
* the walletKey. Used when an authed probe proves the key is revoked server-side (401/
|
|
116
|
+
* any non-2xx) — discarding it immediately means a later failed re-mint can never leave
|
|
117
|
+
* the dead key behind to wedge the agent. Returns the config path.
|
|
118
|
+
*/
|
|
119
|
+
export function discardSavedToken(): string {
|
|
120
|
+
const existing = readSavedConfig();
|
|
121
|
+
const next: SavedConfig = {};
|
|
122
|
+
if (typeof existing.walletKey === "string" && existing.walletKey.trim()) next.walletKey = existing.walletKey.trim();
|
|
123
|
+
return writeConfigFile(next);
|
|
124
|
+
}
|
|
125
|
+
|
|
113
126
|
/**
|
|
114
127
|
* Last resort (config save failed): write the live minted key to a FRESH 0600 recovery
|
|
115
128
|
* file — never to stderr/logs and never into a thrown error (which would reach the LLM
|
package/src/onboard.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { bytesToHex } from "viem";
|
|
|
25
25
|
import { validateMnemonic } from "@scure/bip39";
|
|
26
26
|
import { wordlist } from "@scure/bip39/wordlists/english";
|
|
27
27
|
import type { PrivateKeyAccount } from "viem/accounts";
|
|
28
|
-
import { readConfig, readSavedWalletKey, saveTokenAndWallet, saveKeyRecovery, configPath as configFilePath } from "./client.js";
|
|
28
|
+
import { readConfig, readSavedWalletKey, saveTokenAndWallet, saveKeyRecovery, discardSavedToken, configPath as configFilePath } from "./client.js";
|
|
29
29
|
|
|
30
30
|
/** Normalise a private key to the 0x-prefixed form viem expects. */
|
|
31
31
|
function normalizeKey(pk: string): `0x${string}` {
|
|
@@ -197,17 +197,28 @@ export async function onboard(
|
|
|
197
197
|
if (!generated && !imported && savedToken?.startsWith("cyb_")) {
|
|
198
198
|
// VALIDATE the saved key is still live before reusing it — a server-side-revoked key
|
|
199
199
|
// would otherwise wedge every networked tool with no recovery. A cheap authed GET
|
|
200
|
-
// confirms it
|
|
200
|
+
// confirms it, and ONLY a confirmed-valid response (2xx + a parseable JSON object
|
|
201
|
+
// with no error envelope) counts: a 401 — or ANY non-2xx — proves the key is dead,
|
|
202
|
+
// so we DISCARD it from ~/.cyberdyne/config.json immediately (a failed re-mint must
|
|
203
|
+
// never leave the dead key behind) and fall through to the SIWE→mint chain below.
|
|
201
204
|
try {
|
|
202
205
|
const probe = await fetch(`${apiUrl}/api/tasks?mine=posted&limit=1`, {
|
|
203
206
|
headers: { authorization: `Bearer ${savedToken}`, accept: "application/json" },
|
|
204
207
|
});
|
|
205
208
|
if (probe.ok) {
|
|
206
|
-
|
|
209
|
+
const body = (await probe.json().catch(() => null)) as Record<string, unknown> | null;
|
|
210
|
+
if (body && typeof body === "object" && !("error" in body)) {
|
|
211
|
+
return { address, apiKey: savedToken, generated: false, imported: false, configPath: configFilePath(), bankr: undefined };
|
|
212
|
+
}
|
|
213
|
+
// 2xx but not the real authed payload (error envelope / unparseable) → NOT
|
|
214
|
+
// confirmed valid; treat as dead like any non-2xx.
|
|
207
215
|
}
|
|
208
|
-
//
|
|
216
|
+
// 401/403/any non-2xx (or an unconfirmable 2xx) → the saved key is dead. Discard
|
|
217
|
+
// it NOW, then fall through and mint a fresh one.
|
|
218
|
+
discardSavedToken();
|
|
209
219
|
} catch {
|
|
210
|
-
// network error → don't
|
|
220
|
+
// network error → can't confirm either way; don't reuse the key blindly (and don't
|
|
221
|
+
// discard it on a transient outage) — fall through and re-mint.
|
|
211
222
|
}
|
|
212
223
|
}
|
|
213
224
|
|
package/src/server.ts
CHANGED
|
@@ -223,7 +223,7 @@ const server = new McpServer({ name: "cyberdyne", version: PKG_VERSION });
|
|
|
223
223
|
|
|
224
224
|
server.tool(
|
|
225
225
|
"list_categories",
|
|
226
|
-
"List the kinds of
|
|
226
|
+
"List the kinds of work CYBERDYNE humans can do — engagement actions (follow, repost, reply, quote, original posts) plus ground-truthing, capture, agent evals, demos, and expert review. Static (no network). Use this to learn the valid `category` values before posting a task.",
|
|
227
227
|
{},
|
|
228
228
|
async () => json(Object.entries(CATEGORIES).map(([id, blurb]) => ({ id, blurb }))),
|
|
229
229
|
);
|
|
@@ -446,7 +446,7 @@ server.registerPrompt(
|
|
|
446
446
|
content: {
|
|
447
447
|
type: "text",
|
|
448
448
|
text: [
|
|
449
|
-
"You are connected to CYBERDYNE — pay verified humans
|
|
449
|
+
"You are connected to CYBERDYNE — pay verified humans to engage (follow, repost, reply, quote, original posts), paid per verified action; humans also do ground-truthing, capture, agent evals, demos, and expert review. There is ONE model: every task is an open FCFS pool bounty. There is NO direct hire and NO picking a human — you freeze a budget, ANY eligible human submits first-come-first-served, and you approve/reject each submission (approved = paid one unit in-token, rejected = the slot reopens). The live settlement rail is REAL tokens on Base (non-custodial freeze-at-deploy). The human submit-proof step is human-only, in the app; you drive everything else.",
|
|
450
450
|
"",
|
|
451
451
|
"FUND: hold USDC (or BNKR/GITLAWB) + a little ETH for gas in your OWN wallet on Base. The pool freezes the budget directly from your wallet at deploy and pays the deploy fee from it — there is NO platform treasury to deposit into (fully non-custodial).",
|
|
452
452
|
"",
|