@aibtc/mcp-server 1.76.2 → 1.77.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 +15 -0
- package/dist/services/taskmarket.service.d.ts +92 -0
- package/dist/services/taskmarket.service.js +100 -0
- package/dist/tools/inbox-x402.tools.js +2 -0
- package/dist/tools/index.js +3 -0
- package/dist/tools/taskmarket.tools.d.ts +12 -0
- package/dist/tools/taskmarket.tools.js +166 -0
- package/dist/transactions/clarity-values.js +10 -2
- package/package.json +6 -6
- package/skill/SKILL.md +15 -1
- package/skill/references/taskmarket.md +26 -0
package/README.md
CHANGED
|
@@ -524,6 +524,21 @@ For autonomous agents, use `pillar_direct_*` tools (no browser needed).
|
|
|
524
524
|
| `scaffold_x402_endpoint` | Generate x402 Cloudflare Worker project |
|
|
525
525
|
| `scaffold_x402_ai_endpoint` | Generate x402 AI API with OpenRouter |
|
|
526
526
|
|
|
527
|
+
### TaskMarket (Work Marketplace on Base)
|
|
528
|
+
Read-only discovery of onchain agent work on [TaskMarket](https://taskmarket.dev) (USDC escrow on Base). The tools are public and anonymous: no wallet, no spend.
|
|
529
|
+
|
|
530
|
+
| Tool | Description |
|
|
531
|
+
|------|-------------|
|
|
532
|
+
| `taskmarket_search` | List/search open tasks (filters: status, phase, mode, tags, reward range) |
|
|
533
|
+
| `taskmarket_get` | Full task detail + live status by task ID |
|
|
534
|
+
| `taskmarket_submissions` | List a task's submissions |
|
|
535
|
+
| `taskmarket_stats` | Public market/agent statistics (reputation check) |
|
|
536
|
+
|
|
537
|
+
### Inbox Messaging (aibtc.com)
|
|
538
|
+
| Tool | Description |
|
|
539
|
+
|------|-------------|
|
|
540
|
+
| `send_inbox_message_direct` | Send a paid x402 message to another agent's inbox (sBTC cost; STX gas is sponsored when the inbox offers it) |
|
|
541
|
+
|
|
527
542
|
## Usage Examples
|
|
528
543
|
|
|
529
544
|
**Wallet management:**
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskMarket service — read-only discovery.
|
|
3
|
+
*
|
|
4
|
+
* TaskMarket (https://taskmarket.dev) is an onchain agent work marketplace on
|
|
5
|
+
* Base: requesters escrow USDC, workers submit deliverables, and the requester
|
|
6
|
+
* accepts a winner. This service reads the public, anonymous API (search, get,
|
|
7
|
+
* list-submissions, market-stats). It never signs or spends.
|
|
8
|
+
*/
|
|
9
|
+
export interface TaskmarketTask {
|
|
10
|
+
id: string;
|
|
11
|
+
requester: string;
|
|
12
|
+
description: string;
|
|
13
|
+
reward: string;
|
|
14
|
+
netReward?: string;
|
|
15
|
+
escrowTxHash?: string;
|
|
16
|
+
createdAt: string;
|
|
17
|
+
expiryTime: string;
|
|
18
|
+
status: string;
|
|
19
|
+
phase?: string;
|
|
20
|
+
tags: string[];
|
|
21
|
+
mode?: string;
|
|
22
|
+
taskVisibility?: string;
|
|
23
|
+
submissionVisibility?: string;
|
|
24
|
+
submissionCount?: number;
|
|
25
|
+
platformFeeBps?: number;
|
|
26
|
+
requesterAgentId?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface TaskmarketSubmission {
|
|
29
|
+
id: string;
|
|
30
|
+
taskId: string;
|
|
31
|
+
workerAddress: string;
|
|
32
|
+
workerAgentId?: string;
|
|
33
|
+
submittedAt: string;
|
|
34
|
+
rejectedAt?: string | null;
|
|
35
|
+
deliverableHash?: string;
|
|
36
|
+
submitTxHash?: string;
|
|
37
|
+
artifacts?: Array<{
|
|
38
|
+
id: string;
|
|
39
|
+
fileName: string;
|
|
40
|
+
mimeType: string;
|
|
41
|
+
sizeBytes?: number;
|
|
42
|
+
storageUri?: string;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
/** Convert base-unit reward (e.g. "2000000") to human USDC (e.g. "2"). */
|
|
46
|
+
export declare function baseUnitsToUsdc(raw: string | undefined | null): string;
|
|
47
|
+
/** Convert human USDC (e.g. "2") to base units (e.g. "2000000"). */
|
|
48
|
+
export declare function usdcToBaseUnits(amount: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* List/search tasks. Public, anonymous, read-only.
|
|
51
|
+
*/
|
|
52
|
+
export declare function listTasks(options: {
|
|
53
|
+
status?: string;
|
|
54
|
+
phase?: string;
|
|
55
|
+
mode?: string;
|
|
56
|
+
tags?: string;
|
|
57
|
+
rewardMin?: string;
|
|
58
|
+
rewardMax?: string;
|
|
59
|
+
limit?: number;
|
|
60
|
+
signal?: AbortSignal;
|
|
61
|
+
}): Promise<{
|
|
62
|
+
tasks: TaskmarketTask[];
|
|
63
|
+
hasMore: boolean;
|
|
64
|
+
nextCursor: string | null;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Get a single task with its live status. Public, anonymous, read-only.
|
|
68
|
+
*/
|
|
69
|
+
export declare function getTask(taskId: string, signal?: AbortSignal): Promise<TaskmarketTask>;
|
|
70
|
+
/**
|
|
71
|
+
* List submissions for a task so the requester can review them for real work.
|
|
72
|
+
* Public, anonymous, read-only. Never auto-accepts or auto-rejects anything.
|
|
73
|
+
*/
|
|
74
|
+
export declare function listSubmissions(taskId: string, signal?: AbortSignal): Promise<TaskmarketSubmission[]>;
|
|
75
|
+
export interface TaskmarketStats {
|
|
76
|
+
address?: string;
|
|
77
|
+
agentId?: string;
|
|
78
|
+
completedTasks?: number;
|
|
79
|
+
ratedTasks?: number;
|
|
80
|
+
totalStars?: number;
|
|
81
|
+
averageRating?: number;
|
|
82
|
+
[key: string]: unknown;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Market/agent statistics. Anonymous read of a public stats endpoint.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getMarketStats(options: {
|
|
88
|
+
address?: string;
|
|
89
|
+
agentId?: string;
|
|
90
|
+
signal?: AbortSignal;
|
|
91
|
+
}): Promise<TaskmarketStats>;
|
|
92
|
+
//# sourceMappingURL=taskmarket.service.d.ts.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskMarket service — read-only discovery.
|
|
3
|
+
*
|
|
4
|
+
* TaskMarket (https://taskmarket.dev) is an onchain agent work marketplace on
|
|
5
|
+
* Base: requesters escrow USDC, workers submit deliverables, and the requester
|
|
6
|
+
* accepts a winner. This service reads the public, anonymous API (search, get,
|
|
7
|
+
* list-submissions, market-stats). It never signs or spends.
|
|
8
|
+
*/
|
|
9
|
+
const TASKMARKET_API_URL = process.env.TASKMARKET_API_URL || "https://api.taskmarket.dev";
|
|
10
|
+
/** Bound every read so a hung TaskMarket API cannot hold a tool call open. */
|
|
11
|
+
const READ_TIMEOUT_MS = 15_000;
|
|
12
|
+
/** Convert base-unit reward (e.g. "2000000") to human USDC (e.g. "2"). */
|
|
13
|
+
export function baseUnitsToUsdc(raw) {
|
|
14
|
+
if (!raw || !/^\d+$/.test(raw))
|
|
15
|
+
return "0";
|
|
16
|
+
const padded = raw.padStart(7, "0");
|
|
17
|
+
const whole = padded.slice(0, padded.length - 6) || "0";
|
|
18
|
+
const frac = padded.slice(padded.length - 6).replace(/0+$/, "");
|
|
19
|
+
return frac ? `${whole}.${frac}` : whole;
|
|
20
|
+
}
|
|
21
|
+
/** Convert human USDC (e.g. "2") to base units (e.g. "2000000"). */
|
|
22
|
+
export function usdcToBaseUnits(amount) {
|
|
23
|
+
if (!/^\d+(\.\d+)?$/.test(amount)) {
|
|
24
|
+
throw new Error(`Invalid USDC amount: "${amount}"`);
|
|
25
|
+
}
|
|
26
|
+
const [whole, frac = ""] = amount.split(".");
|
|
27
|
+
if (frac.length > 6) {
|
|
28
|
+
throw new Error(`USDC amount has more than 6 decimals: "${amount}"`);
|
|
29
|
+
}
|
|
30
|
+
const wholeInt = BigInt(whole || "0");
|
|
31
|
+
const fracPadded = frac.padEnd(6, "0");
|
|
32
|
+
const fracInt = fracPadded ? BigInt(fracPadded) : 0n;
|
|
33
|
+
return (wholeInt * 1000000n + fracInt).toString();
|
|
34
|
+
}
|
|
35
|
+
async function apiGet(path, signal) {
|
|
36
|
+
const response = await fetch(`${TASKMARKET_API_URL}${path}`, {
|
|
37
|
+
signal: signal ?? AbortSignal.timeout(READ_TIMEOUT_MS),
|
|
38
|
+
headers: { accept: "application/json" },
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
const text = await response.text().catch(() => "Unknown error");
|
|
42
|
+
throw new Error(`TaskMarket API error ${response.status}: ${text}`);
|
|
43
|
+
}
|
|
44
|
+
const json = (await response.json());
|
|
45
|
+
return (json.data ?? json);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* List/search tasks. Public, anonymous, read-only.
|
|
49
|
+
*/
|
|
50
|
+
export async function listTasks(options) {
|
|
51
|
+
const params = new URLSearchParams();
|
|
52
|
+
if (options.status)
|
|
53
|
+
params.set("status", options.status);
|
|
54
|
+
if (options.phase)
|
|
55
|
+
params.set("phase", options.phase);
|
|
56
|
+
if (options.mode)
|
|
57
|
+
params.set("mode", options.mode);
|
|
58
|
+
if (options.tags)
|
|
59
|
+
params.set("tags", options.tags);
|
|
60
|
+
if (options.rewardMin)
|
|
61
|
+
params.set("minReward", usdcToBaseUnits(options.rewardMin));
|
|
62
|
+
if (options.rewardMax)
|
|
63
|
+
params.set("maxReward", usdcToBaseUnits(options.rewardMax));
|
|
64
|
+
params.set("limit", String(options.limit ?? 20));
|
|
65
|
+
const result = await apiGet(`/api/tasks?${params.toString()}`, options.signal);
|
|
66
|
+
return {
|
|
67
|
+
tasks: result.tasks ?? [],
|
|
68
|
+
hasMore: result.hasMore ?? false,
|
|
69
|
+
nextCursor: result.nextCursor ?? null,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get a single task with its live status. Public, anonymous, read-only.
|
|
74
|
+
*/
|
|
75
|
+
export async function getTask(taskId, signal) {
|
|
76
|
+
return apiGet(`/api/tasks/${taskId}`, signal);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* List submissions for a task so the requester can review them for real work.
|
|
80
|
+
* Public, anonymous, read-only. Never auto-accepts or auto-rejects anything.
|
|
81
|
+
*/
|
|
82
|
+
export async function listSubmissions(taskId, signal) {
|
|
83
|
+
const result = await apiGet(`/api/tasks/${taskId}/submissions`, signal);
|
|
84
|
+
if (Array.isArray(result))
|
|
85
|
+
return result;
|
|
86
|
+
return (result.submissions ?? []);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Market/agent statistics. Anonymous read of a public stats endpoint.
|
|
90
|
+
*/
|
|
91
|
+
export async function getMarketStats(options) {
|
|
92
|
+
const params = new URLSearchParams();
|
|
93
|
+
if (options.address)
|
|
94
|
+
params.set("address", options.address);
|
|
95
|
+
if (options.agentId)
|
|
96
|
+
params.set("agentId", options.agentId);
|
|
97
|
+
const query = params.toString();
|
|
98
|
+
return apiGet(`/api/agents/stats${query ? `?${query}` : ""}`, options.signal);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=taskmarket.service.js.map
|
|
@@ -169,6 +169,8 @@ export function registerInboxX402Tools(server) {
|
|
|
169
169
|
privateKey: account.privateKey,
|
|
170
170
|
network: NETWORK,
|
|
171
171
|
};
|
|
172
|
+
// x402-stacks is CJS, so its AxiosInstance comes from axios' .d.cts
|
|
173
|
+
// types; ours comes from .d.ts. Same runtime object, different type.
|
|
172
174
|
const api = wrapAxiosWithPayment(axios.create({ timeout: 120_000 }), stacksAccount);
|
|
173
175
|
try {
|
|
174
176
|
response = await api.post(inboxUrl, body, {
|
package/dist/tools/index.js
CHANGED
|
@@ -52,6 +52,7 @@ import { registerInboxTools } from "./inbox.tools.js";
|
|
|
52
52
|
import { registerInboxX402Tools } from "./inbox-x402.tools.js";
|
|
53
53
|
import { registerArxivResearchTools } from "./arxiv-research.tools.js";
|
|
54
54
|
import { registerEarningTools } from "./earning.tools.js";
|
|
55
|
+
import { registerTaskmarketTools } from "./taskmarket.tools.js";
|
|
55
56
|
import { getSkillForTool } from "./skill-mappings.js";
|
|
56
57
|
import { isToolSelected } from "./profiles.js";
|
|
57
58
|
/**
|
|
@@ -214,6 +215,8 @@ export function registerAllTools(server, selection) {
|
|
|
214
215
|
inGroup("dev", registerArxivResearchTools);
|
|
215
216
|
// Earning Opportunities (static "how to put your assets to work" menu)
|
|
216
217
|
inGroup("earn", registerEarningTools);
|
|
218
|
+
// TaskMarket (onchain agent work marketplace on Base — read-only discovery + gated create)
|
|
219
|
+
inGroup("earn", registerTaskmarketTools);
|
|
217
220
|
restoreRegisterTool();
|
|
218
221
|
}
|
|
219
222
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskMarket Tools (https://taskmarket.dev) — onchain agent work marketplace on Base.
|
|
3
|
+
*
|
|
4
|
+
* Read tools (public, anonymous, no wallet, no spend):
|
|
5
|
+
* - taskmarket_search — list/search open tasks (filters: status, phase, mode, tags, reward)
|
|
6
|
+
* - taskmarket_get — full task detail + live status by task ID
|
|
7
|
+
* - taskmarket_submissions — list submissions for a task
|
|
8
|
+
* - taskmarket_stats — public market/agent statistics
|
|
9
|
+
*/
|
|
10
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
11
|
+
export declare function registerTaskmarketTools(server: McpServer): void;
|
|
12
|
+
//# sourceMappingURL=taskmarket.tools.d.ts.map
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskMarket Tools (https://taskmarket.dev) — onchain agent work marketplace on Base.
|
|
3
|
+
*
|
|
4
|
+
* Read tools (public, anonymous, no wallet, no spend):
|
|
5
|
+
* - taskmarket_search — list/search open tasks (filters: status, phase, mode, tags, reward)
|
|
6
|
+
* - taskmarket_get — full task detail + live status by task ID
|
|
7
|
+
* - taskmarket_submissions — list submissions for a task
|
|
8
|
+
* - taskmarket_stats — public market/agent statistics
|
|
9
|
+
*/
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { createJsonResponse, createErrorResponse } from "../utils/index.js";
|
|
12
|
+
import { baseUnitsToUsdc, getTask, getMarketStats, listSubmissions, listTasks, } from "../services/taskmarket.service.js";
|
|
13
|
+
const TASK_ID_SCHEMA = z
|
|
14
|
+
.string()
|
|
15
|
+
.regex(/^0x[0-9a-fA-F]{64}$/)
|
|
16
|
+
.describe("TaskMarket task ID (0x + 64 hex chars)");
|
|
17
|
+
export function registerTaskmarketTools(server) {
|
|
18
|
+
// ==========================================================================
|
|
19
|
+
// Read tools — no wallet required, never spends
|
|
20
|
+
// ==========================================================================
|
|
21
|
+
server.registerTool("taskmarket_search", {
|
|
22
|
+
description: "Search open tasks on the TaskMarket agent work marketplace (Base, USDC escrow). " +
|
|
23
|
+
"Public and anonymous — no wallet or payment needed. Returns tasks with ID, reward (USDC), " +
|
|
24
|
+
"status, submission count, deadline, and a short description so you can pick work to delegate. " +
|
|
25
|
+
"Never spends anything.",
|
|
26
|
+
inputSchema: z.object({
|
|
27
|
+
status: z.string().default("open").describe("Filter by status (default: open)"),
|
|
28
|
+
phase: z.string().optional().describe("Filter by lifecycle phase (active, in_review, awaiting_settlement, resolved)"),
|
|
29
|
+
mode: z.string().optional().describe("Filter by task mode (bounty, claim, pitch, benchmark, auction)"),
|
|
30
|
+
tags: z.string().optional().describe("Comma-separated tags to filter by (e.g. 'mcp,research')"),
|
|
31
|
+
rewardMin: z.string().optional().describe("Minimum reward in human USDC (e.g. 0.5)"),
|
|
32
|
+
rewardMax: z.string().optional().describe("Maximum reward in human USDC (e.g. 50)"),
|
|
33
|
+
limit: z.number().int().min(1).max(50).default(20).describe("Max results (1-50)"),
|
|
34
|
+
}),
|
|
35
|
+
}, async (args) => {
|
|
36
|
+
try {
|
|
37
|
+
const result = await listTasks({
|
|
38
|
+
status: args.status,
|
|
39
|
+
phase: args.phase,
|
|
40
|
+
mode: args.mode,
|
|
41
|
+
tags: args.tags,
|
|
42
|
+
rewardMin: args.rewardMin,
|
|
43
|
+
rewardMax: args.rewardMax,
|
|
44
|
+
limit: args.limit,
|
|
45
|
+
});
|
|
46
|
+
return createJsonResponse({
|
|
47
|
+
success: true,
|
|
48
|
+
network: "eip155:8453",
|
|
49
|
+
taskCount: result.tasks.length,
|
|
50
|
+
hasMore: result.hasMore,
|
|
51
|
+
nextCursor: result.nextCursor,
|
|
52
|
+
tasks: result.tasks.map((t) => ({
|
|
53
|
+
id: t.id,
|
|
54
|
+
status: t.status,
|
|
55
|
+
phase: t.phase ?? null,
|
|
56
|
+
mode: t.mode ?? "bounty",
|
|
57
|
+
rewardUsdc: baseUnitsToUsdc(t.reward),
|
|
58
|
+
submissionCount: t.submissionCount ?? 0,
|
|
59
|
+
deadline: t.expiryTime,
|
|
60
|
+
tags: t.tags ?? [],
|
|
61
|
+
description: t.description.slice(0, 300),
|
|
62
|
+
})),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
return createErrorResponse(error);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
server.registerTool("taskmarket_get", {
|
|
70
|
+
description: "Get full detail and LIVE status for one TaskMarket task by ID. Public and anonymous. " +
|
|
71
|
+
"Returns description, reward, deadline, escrow tx, submission count, phase, and status. " +
|
|
72
|
+
"Use this after creating or delegating a task to check whether it is open, in review, " +
|
|
73
|
+
"awaiting settlement, or resolved. Never spends anything.",
|
|
74
|
+
inputSchema: z.object({
|
|
75
|
+
taskId: TASK_ID_SCHEMA,
|
|
76
|
+
}),
|
|
77
|
+
}, async ({ taskId }) => {
|
|
78
|
+
try {
|
|
79
|
+
const task = await getTask(taskId);
|
|
80
|
+
return createJsonResponse({
|
|
81
|
+
success: true,
|
|
82
|
+
id: task.id,
|
|
83
|
+
status: task.status,
|
|
84
|
+
phase: task.phase ?? null,
|
|
85
|
+
mode: task.mode ?? "bounty",
|
|
86
|
+
rewardUsdc: baseUnitsToUsdc(task.reward),
|
|
87
|
+
netRewardUsdc: task.netReward ? baseUnitsToUsdc(task.netReward) : null,
|
|
88
|
+
escrowTxHash: task.escrowTxHash ?? null,
|
|
89
|
+
requester: task.requester,
|
|
90
|
+
submissionCount: task.submissionCount ?? 0,
|
|
91
|
+
createdAt: task.createdAt,
|
|
92
|
+
deadline: task.expiryTime,
|
|
93
|
+
tags: task.tags ?? [],
|
|
94
|
+
link: `https://taskmarket.dev/task/${task.id}`,
|
|
95
|
+
description: task.description,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return createErrorResponse(error);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
server.registerTool("taskmarket_submissions", {
|
|
103
|
+
description: "List submissions on a TaskMarket task for HUMAN REVIEW. Public and anonymous. " +
|
|
104
|
+
"Returns each submission's worker address, submission time, deliverable file name, and " +
|
|
105
|
+
"hash. This tool NEVER accepts or rejects work — it only surfaces submissions so a human " +
|
|
106
|
+
"requester can review the deliverable before authorizing any payment.",
|
|
107
|
+
inputSchema: z.object({
|
|
108
|
+
taskId: TASK_ID_SCHEMA,
|
|
109
|
+
}),
|
|
110
|
+
}, async ({ taskId }) => {
|
|
111
|
+
try {
|
|
112
|
+
const submissions = await listSubmissions(taskId);
|
|
113
|
+
return createJsonResponse({
|
|
114
|
+
success: true,
|
|
115
|
+
taskId,
|
|
116
|
+
submissionCount: submissions.length,
|
|
117
|
+
submissions: submissions.map((s) => ({
|
|
118
|
+
id: s.id,
|
|
119
|
+
workerAddress: s.workerAddress,
|
|
120
|
+
workerAgentId: s.workerAgentId ?? null,
|
|
121
|
+
submittedAt: s.submittedAt,
|
|
122
|
+
rejectedAt: s.rejectedAt ?? null,
|
|
123
|
+
deliverableHash: s.deliverableHash ?? null,
|
|
124
|
+
submitTxHash: s.submitTxHash ?? null,
|
|
125
|
+
files: (s.artifacts ?? []).map((a) => ({
|
|
126
|
+
fileName: a.fileName,
|
|
127
|
+
mimeType: a.mimeType,
|
|
128
|
+
sizeBytes: a.sizeBytes ?? null,
|
|
129
|
+
})),
|
|
130
|
+
})),
|
|
131
|
+
note: "Human review required. This tool never auto-accepts or auto-rejects submissions.",
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return createErrorResponse(error);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
server.registerTool("taskmarket_stats", {
|
|
139
|
+
description: "Public TaskMarket statistics for an agent address or agent ID (one is required): completed tasks, rating, " +
|
|
140
|
+
"total stars. Anonymous read. Use to gauge whether a worker or requester is reputable " +
|
|
141
|
+
"before delegating work. Never spends anything.",
|
|
142
|
+
inputSchema: z.object({
|
|
143
|
+
address: z.string().optional().describe("Wallet address to look up stats for"),
|
|
144
|
+
agentId: z.string().optional().describe("Agent ID to look up stats for (alternative to address)"),
|
|
145
|
+
}),
|
|
146
|
+
}, async (args) => {
|
|
147
|
+
try {
|
|
148
|
+
if (!args.address && !args.agentId) {
|
|
149
|
+
throw new Error("Pass an address or an agentId");
|
|
150
|
+
}
|
|
151
|
+
const stats = await getMarketStats({
|
|
152
|
+
address: args.address,
|
|
153
|
+
agentId: args.agentId,
|
|
154
|
+
});
|
|
155
|
+
return createJsonResponse({
|
|
156
|
+
success: true,
|
|
157
|
+
stats,
|
|
158
|
+
note: "Stats are public market data. A low rating does not guarantee work quality — review deliverables yourself.",
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
return createErrorResponse(error);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=taskmarket.tools.js.map
|
|
@@ -48,8 +48,16 @@ export function parseArgToClarityValue(arg) {
|
|
|
48
48
|
return boolCV(typedArg.value);
|
|
49
49
|
case "principal":
|
|
50
50
|
return principalCV(typedArg.value);
|
|
51
|
-
case "buffer":
|
|
52
|
-
|
|
51
|
+
case "buffer": {
|
|
52
|
+
// Strip optional 0x/0X prefix — without this, Buffer.from("0x...", "hex")
|
|
53
|
+
// silently produces an empty buffer (aibtcdev/landing-page#1012 Finding 2)
|
|
54
|
+
const hexStr = typedArg.value.replace(/^0x/i, "");
|
|
55
|
+
// Buffer.from also stops at the first non-hex character or odd nibble
|
|
56
|
+
if (!/^([0-9a-f]{2})*$/i.test(hexStr)) {
|
|
57
|
+
throw new Error(`Invalid hex for buffer argument: "${typedArg.value}"`);
|
|
58
|
+
}
|
|
59
|
+
return bufferCV(Buffer.from(hexStr, "hex"));
|
|
60
|
+
}
|
|
53
61
|
case "none":
|
|
54
62
|
return noneCV();
|
|
55
63
|
case "some":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aibtc/mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.77.0",
|
|
4
4
|
"description": "Bitcoin-native MCP server for AI agents: BTC/STX wallets, DeFi yield, sBTC peg, NFTs, and x402 payments.",
|
|
5
5
|
"mcpName": "io.github.aibtcdev/mcp-server",
|
|
6
6
|
"type": "module",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"homepage": "https://github.com/aibtcdev/aibtc-mcp-server#readme",
|
|
49
49
|
"license": "MIT",
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@aibtc/tx-schemas": "^
|
|
51
|
+
"@aibtc/tx-schemas": "^1.1.0",
|
|
52
52
|
"@bitflowlabs/core-sdk": "^3.0.0",
|
|
53
53
|
"@buildonspark/spark-sdk": "^0.7.14",
|
|
54
54
|
"@faktoryfun/styx-sdk": "^1.3.5",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@stacks/transactions": "^7.6.0",
|
|
67
67
|
"@stacks/wallet-sdk": "^7.2.0",
|
|
68
68
|
"alex-sdk": "^3.2.1",
|
|
69
|
-
"axios": "^1.
|
|
69
|
+
"axios": "^1.20.0",
|
|
70
70
|
"light-bolt11-decoder": "^3.2.0",
|
|
71
71
|
"micro-ordinals": "^0.3.0",
|
|
72
72
|
"nostr-tools": "^2.23.3",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"tslib": "^2.8.1",
|
|
76
76
|
"ws": "^8.21.0",
|
|
77
77
|
"x402-stacks": "^2.1.0",
|
|
78
|
-
"zod": "^4.6.
|
|
78
|
+
"zod": "^4.6.7"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@types/node": "^22.19.13",
|
|
@@ -84,10 +84,10 @@
|
|
|
84
84
|
"postcss": "^8.5.18",
|
|
85
85
|
"tsx": "^4.21.0",
|
|
86
86
|
"typescript": "^5.9.3",
|
|
87
|
-
"vitest": "^4.1.
|
|
87
|
+
"vitest": "^4.1.12"
|
|
88
88
|
},
|
|
89
89
|
"overrides": {
|
|
90
90
|
"lodash": "^4.18.0",
|
|
91
|
-
"axios": "^1.
|
|
91
|
+
"axios": "^1.20.0"
|
|
92
92
|
}
|
|
93
93
|
}
|
package/skill/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: Bitcoin L1 wallet for agents - check balances, send BTC, manage UTX
|
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
6
|
author: aibtcdev
|
|
7
|
-
version: 1.
|
|
7
|
+
version: 1.77.0 # x-release-please-version
|
|
8
8
|
npm: "@aibtc/mcp-server"
|
|
9
9
|
github: https://github.com/aibtcdev/aibtc-mcp-server
|
|
10
10
|
---
|
|
@@ -242,6 +242,20 @@ unlocked wallet on the gateway's network. Every tool takes an optional `gateway`
|
|
|
242
242
|
arg (defaults to `https://inference.aibtc.com`; use `http://localhost:8787` for
|
|
243
243
|
local dev).
|
|
244
244
|
|
|
245
|
+
### TaskMarket (onchain work marketplace on Base)
|
|
246
|
+
|
|
247
|
+
Browse the [TaskMarket](https://taskmarket.dev) agent work marketplace (USDC
|
|
248
|
+
escrow on Base). The tools are public and anonymous: no wallet, no spend.
|
|
249
|
+
|
|
250
|
+
| Tool | Description | Signed |
|
|
251
|
+
|------|-------------|:------:|
|
|
252
|
+
| `taskmarket_search` | List/search open tasks (filters, reward range) | — |
|
|
253
|
+
| `taskmarket_get` | Full task detail + live status + link | — |
|
|
254
|
+
| `taskmarket_submissions` | List a task's submissions | — |
|
|
255
|
+
| `taskmarket_stats` | Public agent/market stats (reputation check) | — |
|
|
256
|
+
|
|
257
|
+
See: [references/taskmarket.md](references/taskmarket.md)
|
|
258
|
+
|
|
245
259
|
### Prediction Market + Legions (elsalvadorstakesbtc.com)
|
|
246
260
|
|
|
247
261
|
A market on one bit of Bitcoin history — did twenty frozen El Salvador reserve
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# TaskMarket (onchain work marketplace on Base)
|
|
2
|
+
|
|
3
|
+
TaskMarket (https://taskmarket.dev) is an onchain agent work marketplace on
|
|
4
|
+
Base. Requesters escrow USDC, workers submit deliverables, and the requester
|
|
5
|
+
reviews submissions and accepts a winner. This server exposes TaskMarket
|
|
6
|
+
through MCP tools.
|
|
7
|
+
|
|
8
|
+
## What works here
|
|
9
|
+
|
|
10
|
+
| Tool | Type | Notes |
|
|
11
|
+
|------|------|-------|
|
|
12
|
+
| `taskmarket_search` | read | Public, anonymous. Filters: status, phase, mode, tags, reward range. |
|
|
13
|
+
| `taskmarket_get` | read | Public, anonymous. Full detail + live status + link. |
|
|
14
|
+
| `taskmarket_submissions` | read | Public, anonymous. Lists submissions; never accepts or rejects work. |
|
|
15
|
+
| `taskmarket_stats` | read | Public, anonymous. Agent/market stats for reputation checks. |
|
|
16
|
+
|
|
17
|
+
## Review submissions
|
|
18
|
+
|
|
19
|
+
`taskmarket_submissions` lists a task's submissions (worker address, agent ID,
|
|
20
|
+
deliverable files, hashes). This tool never accepts or rejects work.
|
|
21
|
+
|
|
22
|
+
## Safety
|
|
23
|
+
|
|
24
|
+
- Every tool is a read against the public API. Nothing signs, spends or
|
|
25
|
+
needs a wallet.
|
|
26
|
+
- No private keys, seeds, tokens, or cookies are requested, stored, or logged.
|