@agentwonderland/mcp 0.1.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.
Files changed (71) hide show
  1. package/dist/core/api-client.d.ts +14 -0
  2. package/dist/core/api-client.js +98 -0
  3. package/dist/core/config.d.ts +77 -0
  4. package/dist/core/config.js +297 -0
  5. package/dist/core/formatters.d.ts +70 -0
  6. package/dist/core/formatters.js +193 -0
  7. package/dist/core/index.d.ts +6 -0
  8. package/dist/core/index.js +6 -0
  9. package/dist/core/ows-adapter.d.ts +43 -0
  10. package/dist/core/ows-adapter.js +100 -0
  11. package/dist/core/payments.d.ts +41 -0
  12. package/dist/core/payments.js +254 -0
  13. package/dist/core/types.d.ts +27 -0
  14. package/dist/core/types.js +4 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +53 -0
  17. package/dist/prompts/index.d.ts +2 -0
  18. package/dist/prompts/index.js +89 -0
  19. package/dist/resources/agents.d.ts +2 -0
  20. package/dist/resources/agents.js +34 -0
  21. package/dist/resources/jobs.d.ts +2 -0
  22. package/dist/resources/jobs.js +15 -0
  23. package/dist/resources/wallet.d.ts +2 -0
  24. package/dist/resources/wallet.js +26 -0
  25. package/dist/tools/_token-cache.d.ts +5 -0
  26. package/dist/tools/_token-cache.js +9 -0
  27. package/dist/tools/agent-info.d.ts +2 -0
  28. package/dist/tools/agent-info.js +97 -0
  29. package/dist/tools/favorites.d.ts +2 -0
  30. package/dist/tools/favorites.js +51 -0
  31. package/dist/tools/index.d.ts +9 -0
  32. package/dist/tools/index.js +9 -0
  33. package/dist/tools/jobs.d.ts +2 -0
  34. package/dist/tools/jobs.js +49 -0
  35. package/dist/tools/rate.d.ts +2 -0
  36. package/dist/tools/rate.js +44 -0
  37. package/dist/tools/run.d.ts +2 -0
  38. package/dist/tools/run.js +80 -0
  39. package/dist/tools/search.d.ts +2 -0
  40. package/dist/tools/search.js +81 -0
  41. package/dist/tools/solve.d.ts +2 -0
  42. package/dist/tools/solve.js +124 -0
  43. package/dist/tools/tip.d.ts +2 -0
  44. package/dist/tools/tip.js +40 -0
  45. package/dist/tools/wallet.d.ts +2 -0
  46. package/dist/tools/wallet.js +197 -0
  47. package/package.json +49 -0
  48. package/src/core/api-client.ts +114 -0
  49. package/src/core/config.ts +384 -0
  50. package/src/core/formatters.ts +256 -0
  51. package/src/core/index.ts +6 -0
  52. package/src/core/ows-adapter.ts +214 -0
  53. package/src/core/payments.ts +278 -0
  54. package/src/core/types.ts +28 -0
  55. package/src/index.ts +65 -0
  56. package/src/prompts/index.ts +120 -0
  57. package/src/resources/agents.ts +37 -0
  58. package/src/resources/jobs.ts +17 -0
  59. package/src/resources/wallet.ts +30 -0
  60. package/src/tools/_token-cache.ts +18 -0
  61. package/src/tools/agent-info.ts +120 -0
  62. package/src/tools/favorites.ts +74 -0
  63. package/src/tools/index.ts +9 -0
  64. package/src/tools/jobs.ts +69 -0
  65. package/src/tools/rate.ts +62 -0
  66. package/src/tools/run.ts +97 -0
  67. package/src/tools/search.ts +96 -0
  68. package/src/tools/solve.ts +162 -0
  69. package/src/tools/tip.ts +59 -0
  70. package/src/tools/wallet.ts +268 -0
  71. package/tsconfig.json +15 -0
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ // ── Tools ────────────────────────────────────────────────────────
5
+ import { registerSearchTools } from "./tools/search.js";
6
+ import { registerRunTools } from "./tools/run.js";
7
+ import { registerSolveTools } from "./tools/solve.js";
8
+ import { registerAgentInfoTools } from "./tools/agent-info.js";
9
+ import { registerJobTools } from "./tools/jobs.js";
10
+ import { registerRateTools } from "./tools/rate.js";
11
+ import { registerWalletTools } from "./tools/wallet.js";
12
+ import { registerFavoriteTools } from "./tools/favorites.js";
13
+ import { registerTipTools } from "./tools/tip.js";
14
+ // ── Resources ────────────────────────────────────────────────────
15
+ import { registerAgentResources } from "./resources/agents.js";
16
+ import { registerWalletResources } from "./resources/wallet.js";
17
+ import { registerJobResources } from "./resources/jobs.js";
18
+ // ── Prompts ──────────────────────────────────────────────────────
19
+ import { registerPrompts } from "./prompts/index.js";
20
+ export async function startMcpServer() {
21
+ const server = new McpServer({
22
+ name: "agentwonderland",
23
+ version: "0.2.0",
24
+ });
25
+ // Register tools
26
+ registerSearchTools(server);
27
+ registerRunTools(server);
28
+ registerSolveTools(server);
29
+ registerAgentInfoTools(server);
30
+ registerJobTools(server);
31
+ registerRateTools(server);
32
+ registerWalletTools(server);
33
+ registerFavoriteTools(server);
34
+ registerTipTools(server);
35
+ // Register resources
36
+ registerAgentResources(server);
37
+ registerWalletResources(server);
38
+ registerJobResources(server);
39
+ // Register prompts
40
+ registerPrompts(server);
41
+ const transport = new StdioServerTransport();
42
+ await server.connect(transport);
43
+ }
44
+ // ── Direct execution ─────────────────────────────────────────────
45
+ // When run as a binary (agentwonderland-mcp), start the server immediately.
46
+ const isCli = process.argv[1]?.endsWith("agentwonderland-mcp") ||
47
+ process.argv[1]?.includes("packages/mcp");
48
+ if (isCli) {
49
+ startMcpServer().catch((err) => {
50
+ console.error("MCP server error:", err);
51
+ process.exit(1);
52
+ });
53
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerPrompts(server: McpServer): void;
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ export function registerPrompts(server) {
3
+ server.prompt("get-started", "Get started with Agent Wonderland — check wallet, discover agents, learn the tools", {}, async () => ({
4
+ messages: [{
5
+ role: "user",
6
+ content: {
7
+ type: "text",
8
+ text: [
9
+ "Help me get started with Agent Wonderland.",
10
+ "",
11
+ "Please:",
12
+ "1. Check my wallet status with wallet_status",
13
+ "2. If no wallet is configured, help me create one with wallet_setup",
14
+ "3. Show me some popular agents with search_agents",
15
+ "4. Briefly explain how solve, run_agent, rating, and tipping work",
16
+ ].join("\n"),
17
+ },
18
+ }],
19
+ }));
20
+ server.prompt("wallet-setup", "Create and fund a wallet for paying agents", {}, async () => ({
21
+ messages: [{
22
+ role: "user",
23
+ content: {
24
+ type: "text",
25
+ text: [
26
+ "Help me set up a payment wallet for Agent Wonderland.",
27
+ "",
28
+ "Please:",
29
+ "1. Check if I already have a wallet with wallet_status",
30
+ "2. If not, create one with wallet_setup",
31
+ "3. Show me the address I need to fund",
32
+ "4. Explain what USDC I need and on which network (Tempo, Base, or Solana)",
33
+ ].join("\n"),
34
+ },
35
+ }],
36
+ }));
37
+ server.prompt("find-agent", "Find the best agent for a task", { task: z.string().describe("What you need done") }, async ({ task }) => ({
38
+ messages: [{
39
+ role: "user",
40
+ content: {
41
+ type: "text",
42
+ text: [
43
+ `Find the best agent on Agent Wonderland for this task: "${task}"`,
44
+ "",
45
+ "Steps:",
46
+ "1. Use search_agents to find relevant agents",
47
+ "2. Use compare_agents on the top 2-3 candidates",
48
+ "3. Recommend the best one based on price, rating, and success rate",
49
+ "4. Ask if I want to run it",
50
+ ].join("\n"),
51
+ },
52
+ }],
53
+ }));
54
+ server.prompt("budget-run", "Complete a task within a budget", {
55
+ task: z.string().describe("What you need done"),
56
+ budget: z.string().optional().describe("Max spend in USD (default: $1)"),
57
+ }, async ({ task, budget }) => ({
58
+ messages: [{
59
+ role: "user",
60
+ content: {
61
+ type: "text",
62
+ text: [
63
+ `Complete this task on Agent Wonderland within $${budget || "1.00"}: "${task}"`,
64
+ "",
65
+ "Use the solve tool with the budget parameter. Show me what agent was selected and why.",
66
+ ].join("\n"),
67
+ },
68
+ }],
69
+ }));
70
+ server.prompt("run-with-review", "Run an agent and review the output", {
71
+ agent_id: z.string().describe("Agent ID to run"),
72
+ input: z.string().describe("JSON input for the agent"),
73
+ }, async ({ agent_id, input }) => ({
74
+ messages: [{
75
+ role: "user",
76
+ content: {
77
+ type: "text",
78
+ text: [
79
+ `Run agent ${agent_id} with this input: ${input}`,
80
+ "",
81
+ "After getting the result:",
82
+ "1. Summarize the output",
83
+ "2. Assess the quality",
84
+ "3. Ask if I want to rate the agent",
85
+ ].join("\n"),
86
+ },
87
+ }],
88
+ }));
89
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerAgentResources(server: McpServer): void;
@@ -0,0 +1,34 @@
1
+ import { apiGet } from "../core/api-client.js";
2
+ import { formatPrice, stars, compactNumber } from "../core/formatters.js";
3
+ export function registerAgentResources(server) {
4
+ // Agent directory — browsable list of all agents
5
+ server.resource("agent-directory", "aw://agents", async () => {
6
+ const agents = await apiGet("/agents?limit=50");
7
+ const lines = agents.map(a => {
8
+ const rating = stars(a.reputationScore);
9
+ const jobs = compactNumber(a.totalExecutions);
10
+ const price = formatPrice(a.pricePer1kTokens);
11
+ return `${a.name} ${rating} ${jobs} jobs | ${price}/req — ${a.description || ""}`;
12
+ });
13
+ return {
14
+ contents: [{
15
+ uri: "aw://agents",
16
+ mimeType: "text/plain",
17
+ text: `Agent Wonderland Marketplace (${agents.length} agents)\n\n${lines.join("\n")}`,
18
+ }],
19
+ };
20
+ });
21
+ // Agent schema — input schema for a specific agent
22
+ server.resource("agent-schema", "aw://agents/{id}/schema", async (uri) => {
23
+ const id = uri.pathname?.split("/").pop() || uri.href.split("/").pop()?.split("?")[0];
24
+ const agent = await apiGet(`/agents/${id}`);
25
+ const schema = agent.mcpSchema ? JSON.stringify(agent.mcpSchema, null, 2) : "No schema defined";
26
+ return {
27
+ contents: [{
28
+ uri: uri.href,
29
+ mimeType: "application/json",
30
+ text: schema,
31
+ }],
32
+ };
33
+ });
34
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerJobResources(server: McpServer): void;
@@ -0,0 +1,15 @@
1
+ import { apiGet } from "../core/api-client.js";
2
+ import { formatRunResult } from "../core/formatters.js";
3
+ export function registerJobResources(server) {
4
+ server.resource("job-result", "aw://jobs/{id}", async (uri) => {
5
+ const id = uri.pathname?.split("/").pop() || uri.href.split("/").pop()?.split("?")[0];
6
+ const job = await apiGet(`/jobs/${id}`);
7
+ return {
8
+ contents: [{
9
+ uri: uri.href,
10
+ mimeType: "text/plain",
11
+ text: formatRunResult(job),
12
+ }],
13
+ };
14
+ });
15
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerWalletResources(server: McpServer): void;
@@ -0,0 +1,26 @@
1
+ import { getWallets, getCardConfig } from "../core/config.js";
2
+ import { getWalletAddress, getConfiguredMethods } from "../core/payments.js";
3
+ export function registerWalletResources(server) {
4
+ server.resource("wallet-config", "aw://wallet", async () => {
5
+ const wallets = getWallets();
6
+ const card = getCardConfig();
7
+ const methods = getConfiguredMethods();
8
+ const lines = ["Wallet Configuration", ""];
9
+ for (const w of wallets) {
10
+ const addr = await getWalletAddress(w.id);
11
+ const storage = w.keyType === "ows" ? "[encrypted]" : "[plaintext]";
12
+ lines.push(`${w.id} ${storage}: ${w.chains.join(", ")} — ${addr}`);
13
+ }
14
+ if (card) {
15
+ lines.push(`Card: ${card.brand} ****${card.last4}`);
16
+ }
17
+ lines.push("", `Configured methods: ${methods.join(", ") || "none"}`);
18
+ return {
19
+ contents: [{
20
+ uri: "aw://wallet",
21
+ mimeType: "text/plain",
22
+ text: lines.join("\n"),
23
+ }],
24
+ };
25
+ });
26
+ }
@@ -0,0 +1,5 @@
1
+ export declare function storeFeedbackToken(jobId: string, token: string, agentId: string): void;
2
+ export declare function getFeedbackToken(jobId: string): {
3
+ token: string;
4
+ agent_id: string;
5
+ } | undefined;
@@ -0,0 +1,9 @@
1
+ // Feedback token cache — stores tokens from recent run/solve results
2
+ // Tokens expire after 1 hour on the server, so no need for client-side cleanup
3
+ const cache = new Map();
4
+ export function storeFeedbackToken(jobId, token, agentId) {
5
+ cache.set(jobId, { token, agent_id: agentId });
6
+ }
7
+ export function getFeedbackToken(jobId) {
8
+ return cache.get(jobId);
9
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerAgentInfoTools(server: McpServer): void;
@@ -0,0 +1,97 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../core/api-client.js";
3
+ import { formatPrice, stars, compactNumber, outputTypeHint, agentWebUrl, formatFeedbackSummary, formatLastActive } from "../core/formatters.js";
4
+ function text(t) {
5
+ return { content: [{ type: "text", text: t }] };
6
+ }
7
+ export function registerAgentInfoTools(server) {
8
+ // ── get_agent (renamed from agent_profile) ──────────────────────
9
+ server.tool("get_agent", "Get detailed information about a specific agent including description, pricing, success rate, latency, and tags.", {
10
+ agent_id: z.string().describe("Agent ID (UUID) or slug"),
11
+ }, async ({ agent_id }) => {
12
+ const a = await apiGet(`/agents/${agent_id}`);
13
+ const s = (a.stats ?? {});
14
+ const payment = (a.payment ?? {});
15
+ const _pricing = (payment.pricing ?? {});
16
+ const lines = [
17
+ `${a.name}`,
18
+ `${stars(a.avgRating ?? s.avgRating)} (${s.ratingCount ?? 0} reviews) • ${compactNumber((s.completedJobs ?? a.totalExecutions ?? 0))} jobs`,
19
+ "",
20
+ a.description ?? "",
21
+ "",
22
+ `Pricing: ${formatPrice(a.pricePer1kTokens, a.pricingModel)}`,
23
+ `Reliability: ${a.successRate != null ? (Number(a.successRate) * 100).toFixed(0) + "%" : "N/A"}`,
24
+ `Avg latency: ${a.avgResponseTimeMs != null ? a.avgResponseTimeMs + "ms" : "N/A"}`,
25
+ ...(() => {
26
+ const lastActive = formatLastActive(a.lastActiveAt);
27
+ return lastActive ? [lastActive] : [];
28
+ })(),
29
+ "",
30
+ `Tags: ${a.tags?.join(", ") ?? "none"}`,
31
+ ...(() => {
32
+ const hint = outputTypeHint(a.tags);
33
+ return hint ? [`Output: ${hint}`] : [];
34
+ })(),
35
+ ];
36
+ // Feedback summary (rating + tips)
37
+ const feedbackSummary = formatFeedbackSummary(s);
38
+ if (feedbackSummary) {
39
+ lines.push("", feedbackSummary);
40
+ }
41
+ // Fetch recent reviews with comments
42
+ try {
43
+ const reviews = await apiGet(`/agents/${a.id}/reviews?limit=3&sort=recent`);
44
+ const withComments = reviews.reviews?.filter((r) => r.comment);
45
+ if (withComments?.length) {
46
+ lines.push("", "Recent reviews:");
47
+ for (const r of withComments) {
48
+ lines.push(` ${stars(r.rating)} "${r.comment}"`);
49
+ }
50
+ }
51
+ }
52
+ catch {
53
+ // Reviews endpoint may not be available
54
+ }
55
+ // Input schema — show what fields the agent accepts
56
+ const schema = a.schema?.input;
57
+ const inputSchema = (schema?.inputSchema ?? a.mcpSchema?.inputSchema);
58
+ if (inputSchema?.properties) {
59
+ const props = inputSchema.properties;
60
+ const required = new Set(inputSchema.required ?? []);
61
+ lines.push("", "Input fields:");
62
+ for (const [name, def] of Object.entries(props)) {
63
+ const req = required.has(name) ? " (required)" : "";
64
+ const desc = def.description ? ` — ${def.description}` : "";
65
+ lines.push(` ${name}: ${def.type ?? "string"}${req}${desc}`);
66
+ }
67
+ }
68
+ lines.push("", `ID: ${a.id}`, `View: ${agentWebUrl(a.id)}`);
69
+ return text(lines.join("\n"));
70
+ });
71
+ // ── compare_agents ──────────────────────────────────────────────
72
+ server.tool("compare_agents", "Compare multiple agents side-by-side on rating, price, success rate, and job count.", {
73
+ agent_ids: z
74
+ .array(z.string())
75
+ .min(2)
76
+ .max(5)
77
+ .describe("Agent IDs to compare (2-5)"),
78
+ }, async ({ agent_ids }) => {
79
+ const agents = await Promise.all(agent_ids.map((id) => apiGet(`/agents/${id}`)));
80
+ const header = "Agent Comparison:\n";
81
+ const lines = agents.map((a) => {
82
+ const s = (a.stats ?? {});
83
+ const rating = a.avgRating ?? s.avgRating;
84
+ const jobs = (s.completedJobs ?? a.totalExecutions ?? 0);
85
+ const tipCount = (s.tipCount ?? 0);
86
+ return [
87
+ ` ${a.name}`,
88
+ ` ${stars(rating)} (${s.ratingCount ?? 0} reviews)${tipCount > 0 ? ` • ${tipCount} tips` : ""}`,
89
+ ` ${compactNumber(jobs)} jobs • ${formatPrice(a.pricePer1kTokens, a.pricingModel)}`,
90
+ ` Success: ${a.successRate != null ? (Number(a.successRate) * 100).toFixed(0) + "%" : "N/A"}`,
91
+ ` ${agentWebUrl(a.id)}`,
92
+ "",
93
+ ].join("\n");
94
+ });
95
+ return text(header + lines.join("\n"));
96
+ });
97
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerFavoriteTools(server: McpServer): void;
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+ import { getFavorites, addFavorite, removeFavorite } from "../core/config.js";
3
+ import { apiGet } from "../core/api-client.js";
4
+ import { formatPrice, stars, compactNumber } from "../core/formatters.js";
5
+ function text(t) {
6
+ return { content: [{ type: "text", text: t }] };
7
+ }
8
+ export function registerFavoriteTools(server) {
9
+ // favorite_agent — add an agent to favorites
10
+ server.tool("favorite_agent", "Save an agent to your favorites for quick access", {
11
+ agent_id: z.string().describe("Agent ID to favorite"),
12
+ }, async ({ agent_id }) => {
13
+ // Verify agent exists
14
+ const agent = await apiGet(`/agents/${agent_id}`);
15
+ addFavorite(agent_id);
16
+ return text(`★ Added ${agent.name} to favorites`);
17
+ });
18
+ // unfavorite_agent — remove from favorites
19
+ server.tool("unfavorite_agent", "Remove an agent from your favorites", {
20
+ agent_id: z.string().describe("Agent ID to remove"),
21
+ }, async ({ agent_id }) => {
22
+ removeFavorite(agent_id);
23
+ return text("Removed from favorites");
24
+ });
25
+ // list_favorites — show all favorited agents with details
26
+ server.tool("list_favorites", "List your favorite agents", {}, async () => {
27
+ const ids = getFavorites();
28
+ if (ids.length === 0) {
29
+ return text("No favorites yet. Use favorite_agent to save agents you like.");
30
+ }
31
+ const lines = ["Your favorite agents:", ""];
32
+ for (const id of ids) {
33
+ try {
34
+ const agent = await apiGet(`/agents/${id}`);
35
+ const rating = stars(agent.avgRating);
36
+ const jobs = compactNumber(agent.totalExecutions);
37
+ const price = formatPrice(agent.pricePer1kTokens, agent.pricingModel);
38
+ lines.push(`${agent.name} ${rating} ${jobs} jobs | ${price}`);
39
+ lines.push(` ID: ${id}`);
40
+ if (agent.description)
41
+ lines.push(` ${agent.description}`);
42
+ lines.push("");
43
+ }
44
+ catch {
45
+ lines.push(`${id} (not found — may have been removed)`);
46
+ lines.push("");
47
+ }
48
+ }
49
+ return text(lines.join("\n"));
50
+ });
51
+ }
@@ -0,0 +1,9 @@
1
+ export { registerSearchTools } from "./search.js";
2
+ export { registerRunTools } from "./run.js";
3
+ export { registerSolveTools } from "./solve.js";
4
+ export { registerAgentInfoTools } from "./agent-info.js";
5
+ export { registerJobTools } from "./jobs.js";
6
+ export { registerRateTools } from "./rate.js";
7
+ export { registerWalletTools } from "./wallet.js";
8
+ export { registerFavoriteTools } from "./favorites.js";
9
+ export { registerTipTools } from "./tip.js";
@@ -0,0 +1,9 @@
1
+ export { registerSearchTools } from "./search.js";
2
+ export { registerRunTools } from "./run.js";
3
+ export { registerSolveTools } from "./solve.js";
4
+ export { registerAgentInfoTools } from "./agent-info.js";
5
+ export { registerJobTools } from "./jobs.js";
6
+ export { registerRateTools } from "./rate.js";
7
+ export { registerWalletTools } from "./wallet.js";
8
+ export { registerFavoriteTools } from "./favorites.js";
9
+ export { registerTipTools } from "./tip.js";
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerJobTools(server: McpServer): void;
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../core/api-client.js";
3
+ import { isAuthenticated } from "../core/config.js";
4
+ import { hasWalletConfigured, getWalletAddress } from "../core/payments.js";
5
+ import { formatRunResult } from "../core/formatters.js";
6
+ function text(t) {
7
+ return { content: [{ type: "text", text: t }] };
8
+ }
9
+ export function registerJobTools(server) {
10
+ // ── get_job ─────────────────────────────────────────────────────
11
+ server.tool("get_job", "Get the status and output of a job by ID. Use to poll async jobs until they complete.", {
12
+ job_id: z.string().describe("Job ID (UUID)"),
13
+ }, async ({ job_id }) => {
14
+ const result = await apiGet(`/jobs/${job_id}`);
15
+ if (result.status === "processing") {
16
+ return text(`Job ${job_id} is still processing...`);
17
+ }
18
+ return text(formatRunResult(result));
19
+ });
20
+ // ── list_jobs (renamed from list_my_jobs) ───────────────────────
21
+ server.tool("list_jobs", "List your recent jobs with status, cost, and agent info.", {
22
+ limit: z.coerce.number().optional().default(10).describe("Max results (1-50)"),
23
+ }, async ({ limit }) => {
24
+ let url = `/jobs?limit=${limit ?? 10}`;
25
+ // If not authenticated via API key, use wallet address for lookup
26
+ if (!isAuthenticated() && hasWalletConfigured()) {
27
+ const address = await getWalletAddress();
28
+ if (address) {
29
+ url += `&wallet=${encodeURIComponent(address)}`;
30
+ }
31
+ }
32
+ const jobs = await apiGet(url);
33
+ if (jobs.length === 0)
34
+ return text("No jobs found.");
35
+ const lines = [`Recent jobs (${jobs.length}):`];
36
+ for (const j of jobs) {
37
+ const status = j.status === "completed"
38
+ ? "\u2713"
39
+ : j.status === "processing"
40
+ ? "\u2026"
41
+ : "\u2717";
42
+ const cost = j.estimated_cost != null
43
+ ? `$${Number(j.estimated_cost).toFixed(4)}`
44
+ : "";
45
+ lines.push(` ${status} ${j.job_id?.slice(0, 8)}\u2026 ${j.agent_id ? String(j.agent_id).slice(0, 8) + "\u2026" : ""} ${cost}`);
46
+ }
47
+ return text(lines.join("\n"));
48
+ });
49
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerRateTools(server: McpServer): void;
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ import { apiPost } from "../core/api-client.js";
3
+ import { stars } from "../core/formatters.js";
4
+ import { getFeedbackToken } from "./_token-cache.js";
5
+ function text(t) {
6
+ return { content: [{ type: "text", text: t }] };
7
+ }
8
+ export function registerRateTools(server) {
9
+ server.tool("rate_agent", "Rate an agent after running it. Provide the job ID from the run result. Must be used within 1 hour of running the agent.", {
10
+ job_id: z.string().describe("Job ID from the run result"),
11
+ rating: z.number().min(1).max(5).describe("Rating 1-5 stars"),
12
+ comment: z.string().optional().describe("Optional feedback comment"),
13
+ }, async ({ job_id, rating, comment }) => {
14
+ const tokenData = getFeedbackToken(job_id);
15
+ if (!tokenData) {
16
+ return text("No feedback token found for this job. You can only rate agents immediately after running them.");
17
+ }
18
+ try {
19
+ await apiPost("/feedback", {
20
+ job_id,
21
+ feedback_token: tokenData.token,
22
+ rating,
23
+ thumb: rating >= 3 ? "up" : "down",
24
+ ...(comment ? { comment } : {}),
25
+ });
26
+ const starStr = stars(rating);
27
+ return text(`${starStr} Rating submitted for job ${job_id}${comment ? ` \u2014 "${comment}"` : ""}`);
28
+ }
29
+ catch (err) {
30
+ const apiErr = err;
31
+ if (apiErr?.status === 401) {
32
+ return text("Feedback token expired. Ratings must be submitted within 1 hour of running the agent.");
33
+ }
34
+ if (apiErr?.status === 409) {
35
+ return text("You've already rated this job.");
36
+ }
37
+ if (apiErr?.status === 429) {
38
+ return text("You can only rate this agent once every 30 days.");
39
+ }
40
+ const msg = apiErr?.body?.error || apiErr?.message || "Rating failed";
41
+ return text(`Could not submit rating: ${msg}`);
42
+ }
43
+ });
44
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerRunTools(server: McpServer): void;
@@ -0,0 +1,80 @@
1
+ import { z } from "zod";
2
+ import { apiGet, apiPostWithPayment } from "../core/api-client.js";
3
+ import { getConfiguredMethods, hasWalletConfigured } from "../core/payments.js";
4
+ import { formatRunResult } from "../core/formatters.js";
5
+ import { storeFeedbackToken } from "./_token-cache.js";
6
+ function text(t) {
7
+ return { content: [{ type: "text", text: t }] };
8
+ }
9
+ export function registerRunTools(server) {
10
+ server.tool("run_agent", "Run an AI agent from the marketplace. Pays automatically via configured wallet. Returns the agent's output, cost, and job ID for tracking.", {
11
+ agent_id: z.string().describe("Agent ID (UUID or slug)"),
12
+ input: z.record(z.unknown()).describe("Input payload for the agent"),
13
+ pay_with: z.string().optional().describe("Payment method — wallet ID, chain name (tempo, base, etc.), or 'card'. Auto-detected if omitted."),
14
+ }, async ({ agent_id, input, pay_with }) => {
15
+ if (!hasWalletConfigured()) {
16
+ return text("No wallet configured. Set one up first:\n\n" +
17
+ ' wallet_setup({ action: "create", name: "my-wallet" })\n\n' +
18
+ "Then fund it with USDC on Tempo and try again.");
19
+ }
20
+ // Resolve slug to UUID if needed (slugs don't contain hyphens in UUID positions)
21
+ let resolvedId = agent_id;
22
+ const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(agent_id);
23
+ if (!isUuid) {
24
+ try {
25
+ const agent = await apiGet(`/agents/${agent_id}`);
26
+ resolvedId = agent.id;
27
+ }
28
+ catch {
29
+ return text(`Agent "${agent_id}" not found. Use search_agents to find available agents.`);
30
+ }
31
+ }
32
+ const method = pay_with;
33
+ let result;
34
+ try {
35
+ result = await apiPostWithPayment(`/agents/${resolvedId}/run`, { input }, method);
36
+ }
37
+ catch (err) {
38
+ const apiErr = err;
39
+ if (apiErr?.status === 402) {
40
+ return text("Payment failed — your wallet may not have enough USDC.\n\n" +
41
+ "Check your balance and fund your wallet, then try again.\n" +
42
+ "Use wallet_status to check your current payment methods.");
43
+ }
44
+ const msg = apiErr?.message ?? "Failed to run agent";
45
+ if (msg.includes("Missing required field") || msg.includes("validation failed")) {
46
+ return text(`Error: ${msg}\n\nUse get_agent("${agent_id}") to see the required input fields.`);
47
+ }
48
+ return text(`Error: ${msg}`);
49
+ }
50
+ const formatted = formatRunResult(result, {
51
+ paymentMethod: method ?? getConfiguredMethods()[0],
52
+ });
53
+ const jobId = result.job_id ?? "";
54
+ const agentId = result.agent_id ?? agent_id;
55
+ if (result.feedback_token) {
56
+ storeFeedbackToken(jobId, result.feedback_token, agentId);
57
+ }
58
+ const status = result.status;
59
+ let prompt;
60
+ if (status === "success") {
61
+ prompt = [
62
+ "",
63
+ "---",
64
+ "How was this result? You can:",
65
+ ` • rate_agent with job_id "${jobId}" and a score (1-5) — within 1 hour`,
66
+ " • tip_agent to show appreciation — within 1 hour",
67
+ " • favorite_agent to save this agent for later",
68
+ ].join("\n");
69
+ }
70
+ else {
71
+ prompt = [
72
+ "",
73
+ "---",
74
+ "The agent execution failed. A refund has been initiated automatically",
75
+ "and will be returned to your wallet.",
76
+ ].join("\n");
77
+ }
78
+ return text(formatted + prompt);
79
+ });
80
+ }
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerSearchTools(server: McpServer): void;