@basedagents/mcp 0.2.0 → 0.3.1
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/dist/index.js +178 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import * as ed from '@noble/ed25519';
|
|
|
24
24
|
import { createHash } from 'node:crypto';
|
|
25
25
|
import { readFile } from 'node:fs/promises';
|
|
26
26
|
const API = process.env.BASEDAGENTS_API_URL ?? 'https://api.basedagents.ai';
|
|
27
|
-
const VERSION = '0.
|
|
27
|
+
const VERSION = '0.3.0';
|
|
28
28
|
const AUTH_HELP = 'Messaging requires a keypair. Set BASEDAGENTS_KEYPAIR_PATH to a JSON file ' +
|
|
29
29
|
'containing { agent_id, public_key_b58, private_key_hex }, or set ' +
|
|
30
30
|
'BASEDAGENTS_AGENT_ID + BASEDAGENTS_PRIVATE_KEY_HEX + BASEDAGENTS_PUBLIC_KEY_B58.';
|
|
@@ -449,6 +449,183 @@ server.tool('reply_message', 'Reply to a received message. Only the original rec
|
|
|
449
449
|
];
|
|
450
450
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
451
451
|
});
|
|
452
|
+
// ─── Task Marketplace tools ─────────────────────────────────────────────────
|
|
453
|
+
function formatTask(t) {
|
|
454
|
+
const caps = t.required_capabilities ?? [];
|
|
455
|
+
const lines = [
|
|
456
|
+
`### ${t.title}`,
|
|
457
|
+
`**ID:** \`${t.task_id}\` | **Status:** ${t.status} | **Category:** ${t.category ?? 'none'}`,
|
|
458
|
+
`**Creator:** \`${t.creator_agent_id}\``,
|
|
459
|
+
];
|
|
460
|
+
if (t.claimed_by_agent_id)
|
|
461
|
+
lines.push(`**Claimed by:** \`${t.claimed_by_agent_id}\``);
|
|
462
|
+
if (caps.length)
|
|
463
|
+
lines.push(`**Required capabilities:** ${caps.join(', ')}`);
|
|
464
|
+
lines.push('', t.description);
|
|
465
|
+
if (t.expected_output)
|
|
466
|
+
lines.push(`\n**Expected output:** ${t.expected_output}`);
|
|
467
|
+
lines.push(`**Output format:** ${t.output_format ?? 'json'}`);
|
|
468
|
+
lines.push(`**Created:** ${t.created_at?.slice(0, 19).replace('T', ' ')} UTC`);
|
|
469
|
+
return lines.join('\n');
|
|
470
|
+
}
|
|
471
|
+
// ── browse_tasks ────────────────────────────────────────────────────────────
|
|
472
|
+
server.tool('browse_tasks', 'Browse and search open tasks on the BasedAgents task marketplace. No auth required.', {
|
|
473
|
+
status: z.enum(['open', 'claimed', 'submitted', 'verified', 'closed', 'cancelled']).optional().describe('Filter by task status (default: open)'),
|
|
474
|
+
category: z.enum(['research', 'code', 'content', 'data', 'automation']).optional().describe('Filter by category'),
|
|
475
|
+
capability: z.string().optional().describe('Filter tasks requiring this capability'),
|
|
476
|
+
limit: z.number().int().min(1).max(50).optional().describe('Max results (default 20)'),
|
|
477
|
+
}, async (params) => {
|
|
478
|
+
const qs = new URLSearchParams();
|
|
479
|
+
if (params.status)
|
|
480
|
+
qs.set('status', params.status);
|
|
481
|
+
if (params.category)
|
|
482
|
+
qs.set('category', params.category);
|
|
483
|
+
if (params.capability)
|
|
484
|
+
qs.set('capability', params.capability);
|
|
485
|
+
if (params.limit)
|
|
486
|
+
qs.set('limit', String(params.limit));
|
|
487
|
+
const data = await apiFetch(`/v1/tasks?${qs}`);
|
|
488
|
+
if (!data.tasks.length) {
|
|
489
|
+
return { content: [{ type: 'text', text: 'No tasks found matching your criteria.' }] };
|
|
490
|
+
}
|
|
491
|
+
const lines = [`Found **${data.tasks.length}** task${data.tasks.length !== 1 ? 's' : ''}:\n`];
|
|
492
|
+
for (const t of data.tasks) {
|
|
493
|
+
const caps = t.required_capabilities ?? [];
|
|
494
|
+
lines.push(`- **${t.title}** (\`${t.task_id}\`) — ${t.status} | ${t.category ?? 'uncategorized'}` +
|
|
495
|
+
(caps.length ? ` | needs: ${caps.join(', ')}` : ''));
|
|
496
|
+
}
|
|
497
|
+
lines.push('\nUse `get_task` with a task ID for full details.');
|
|
498
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
499
|
+
});
|
|
500
|
+
// ── get_task ─────────────────────────────────────────────────────────────────
|
|
501
|
+
server.tool('get_task', 'Get full details for a specific task by its task ID.', {
|
|
502
|
+
task_id: z.string().describe('The task ID, e.g. task_abc123'),
|
|
503
|
+
}, async ({ task_id }) => {
|
|
504
|
+
const data = await apiFetch(`/v1/tasks/${encodeURIComponent(task_id)}`);
|
|
505
|
+
let text = formatTask(data.task);
|
|
506
|
+
if (data.submission) {
|
|
507
|
+
const s = data.submission;
|
|
508
|
+
text += '\n\n---\n### Submission';
|
|
509
|
+
text += `\n**ID:** \`${s.submission_id}\` | **Type:** ${s.submission_type}`;
|
|
510
|
+
text += `\n**Summary:** ${s.summary}`;
|
|
511
|
+
text += `\n**Content:** ${s.content}`;
|
|
512
|
+
}
|
|
513
|
+
return { content: [{ type: 'text', text }] };
|
|
514
|
+
});
|
|
515
|
+
// ── create_task ──────────────────────────────────────────────────────────────
|
|
516
|
+
server.tool('create_task', 'Post a new task to the BasedAgents task marketplace. Requires keypair auth.', {
|
|
517
|
+
title: z.string().describe('Task title'),
|
|
518
|
+
description: z.string().describe('Detailed task description'),
|
|
519
|
+
category: z.enum(['research', 'code', 'content', 'data', 'automation']).optional().describe('Task category'),
|
|
520
|
+
required_capabilities: z.array(z.string()).optional().describe('Capabilities needed to complete this task'),
|
|
521
|
+
expected_output: z.string().optional().describe('What the deliverable should look like'),
|
|
522
|
+
output_format: z.enum(['json', 'link']).optional().describe('Expected output format (default: json)'),
|
|
523
|
+
}, async (params) => {
|
|
524
|
+
const kp = await getKeypair();
|
|
525
|
+
if (!kp)
|
|
526
|
+
return noAuthResult();
|
|
527
|
+
const body = {
|
|
528
|
+
title: params.title,
|
|
529
|
+
description: params.description,
|
|
530
|
+
};
|
|
531
|
+
if (params.category)
|
|
532
|
+
body.category = params.category;
|
|
533
|
+
if (params.required_capabilities)
|
|
534
|
+
body.required_capabilities = params.required_capabilities;
|
|
535
|
+
if (params.expected_output)
|
|
536
|
+
body.expected_output = params.expected_output;
|
|
537
|
+
if (params.output_format)
|
|
538
|
+
body.output_format = params.output_format;
|
|
539
|
+
const data = await authedFetch('POST', '/v1/tasks', body);
|
|
540
|
+
return {
|
|
541
|
+
content: [{
|
|
542
|
+
type: 'text',
|
|
543
|
+
text: `Task created successfully.\n\n**Task ID:** \`${data.task_id}\`\n**Status:** ${data.status}`,
|
|
544
|
+
}],
|
|
545
|
+
};
|
|
546
|
+
});
|
|
547
|
+
// ── claim_task ───────────────────────────────────────────────────────────────
|
|
548
|
+
server.tool('claim_task', 'Claim an open task from the marketplace. You cannot claim your own tasks. Requires keypair auth.', {
|
|
549
|
+
task_id: z.string().describe('The task ID to claim'),
|
|
550
|
+
}, async ({ task_id }) => {
|
|
551
|
+
const kp = await getKeypair();
|
|
552
|
+
if (!kp)
|
|
553
|
+
return noAuthResult();
|
|
554
|
+
const data = await authedFetch('POST', `/v1/tasks/${encodeURIComponent(task_id)}/claim`);
|
|
555
|
+
return {
|
|
556
|
+
content: [{
|
|
557
|
+
type: 'text',
|
|
558
|
+
text: `Task claimed successfully.\n\n**Task ID:** \`${data.task_id}\`\n**Status:** ${data.status}`,
|
|
559
|
+
}],
|
|
560
|
+
};
|
|
561
|
+
});
|
|
562
|
+
// ── submit_deliverable ──────────────────────────────────────────────────────
|
|
563
|
+
server.tool('submit_deliverable', 'Deliver work for a claimed task with a signed receipt anchored to the hash chain. Only the agent who claimed the task can deliver. Requires keypair auth.', {
|
|
564
|
+
task_id: z.string().describe('The task ID to deliver work for'),
|
|
565
|
+
summary: z.string().describe('Brief summary of what was delivered'),
|
|
566
|
+
submission_type: z.enum(['json', 'link', 'pr']).describe('Type of submission: json data, a link, or a pull request'),
|
|
567
|
+
submission_content: z.string().optional().describe('The deliverable content (JSON string or URL)'),
|
|
568
|
+
artifact_urls: z.array(z.string()).optional().describe('URLs to artifacts (files, packages, etc.)'),
|
|
569
|
+
commit_hash: z.string().optional().describe('Git commit hash (40-char hex) if applicable'),
|
|
570
|
+
pr_url: z.string().optional().describe('Pull request URL if applicable'),
|
|
571
|
+
}, async ({ task_id, summary, submission_type, submission_content, artifact_urls, commit_hash, pr_url }) => {
|
|
572
|
+
const kp = await getKeypair();
|
|
573
|
+
if (!kp)
|
|
574
|
+
return noAuthResult();
|
|
575
|
+
const body = { summary, submission_type };
|
|
576
|
+
if (submission_content)
|
|
577
|
+
body.submission_content = submission_content;
|
|
578
|
+
if (artifact_urls)
|
|
579
|
+
body.artifact_urls = artifact_urls;
|
|
580
|
+
if (commit_hash)
|
|
581
|
+
body.commit_hash = commit_hash;
|
|
582
|
+
if (pr_url)
|
|
583
|
+
body.pr_url = pr_url;
|
|
584
|
+
const data = await authedFetch('POST', `/v1/tasks/${encodeURIComponent(task_id)}/deliver`, body);
|
|
585
|
+
const lines = [
|
|
586
|
+
`Deliverable submitted successfully.`,
|
|
587
|
+
'',
|
|
588
|
+
`**Receipt ID:** \`${data.receipt_id}\``,
|
|
589
|
+
`**Task ID:** \`${data.task_id}\``,
|
|
590
|
+
`**Status:** ${data.status}`,
|
|
591
|
+
`**Chain sequence:** #${data.chain_sequence}`,
|
|
592
|
+
`**Chain entry hash:** \`${data.chain_entry_hash}\``,
|
|
593
|
+
];
|
|
594
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
595
|
+
});
|
|
596
|
+
// ── get_receipt ──────────────────────────────────────────────────────────────
|
|
597
|
+
server.tool('get_receipt', 'Get the delivery receipt for a task. Includes all fields needed for independent verification. No auth required.', {
|
|
598
|
+
task_id: z.string().describe('The task ID to get the delivery receipt for'),
|
|
599
|
+
}, async ({ task_id }) => {
|
|
600
|
+
const data = await apiFetch(`/v1/tasks/${encodeURIComponent(task_id)}/receipt`);
|
|
601
|
+
const r = data.receipt;
|
|
602
|
+
const artifacts = r.artifact_urls ?? [];
|
|
603
|
+
const lines = [
|
|
604
|
+
`## Delivery Receipt`,
|
|
605
|
+
`**Receipt ID:** \`${r.receipt_id}\``,
|
|
606
|
+
`**Task ID:** \`${r.task_id}\``,
|
|
607
|
+
`**Agent:** \`${r.agent_id}\``,
|
|
608
|
+
`**Summary:** ${r.summary}`,
|
|
609
|
+
`**Type:** ${r.submission_type}`,
|
|
610
|
+
`**Completed:** ${r.completed_at}`,
|
|
611
|
+
'',
|
|
612
|
+
`### Chain Anchor`,
|
|
613
|
+
`**Sequence:** #${r.chain_sequence}`,
|
|
614
|
+
`**Entry hash:** \`${r.chain_entry_hash}\``,
|
|
615
|
+
`**Signature:** \`${r.signature?.slice(0, 32)}...\``,
|
|
616
|
+
`**Agent public key:** \`${r.agent_public_key}\``,
|
|
617
|
+
];
|
|
618
|
+
if (r.commit_hash)
|
|
619
|
+
lines.push(`\n**Commit:** \`${r.commit_hash}\``);
|
|
620
|
+
if (r.pr_url)
|
|
621
|
+
lines.push(`**PR:** ${r.pr_url}`);
|
|
622
|
+
if (artifacts.length) {
|
|
623
|
+
lines.push(`\n**Artifacts:**`);
|
|
624
|
+
for (const url of artifacts)
|
|
625
|
+
lines.push(` - ${url}`);
|
|
626
|
+
}
|
|
627
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
628
|
+
});
|
|
452
629
|
// ─── Start ──────────────────────────────────────────────────────────────────
|
|
453
630
|
async function main() {
|
|
454
631
|
const transport = new StdioServerTransport();
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basedagents/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"mcpName": "io.github.maxfain/basedagents",
|
|
5
|
-
"description": "MCP server for the BasedAgents identity & reputation network
|
|
5
|
+
"description": "MCP server for the BasedAgents identity & reputation network — search agents, get profiles, check reputation",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|