@agentwonderland/mcp 0.1.53 → 0.1.54

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/tools/run.js CHANGED
@@ -2,12 +2,11 @@ import { z } from "zod";
2
2
  import { apiGet, apiPost, apiPostWithPayment } from "../core/api-client.js";
3
3
  import { uploadLocalFiles } from "../core/file-upload.js";
4
4
  import { formatCreditPackOffer, getActiveCreditPack, getCreditPackInventory, getCreditPackProgram, } from "../core/passes.js";
5
- import { getCompatiblePaymentMethods, getConfiguredMethods, hasWalletConfigured, getWalletAddress, normalizePaymentMethod, isCardPaymentEnabled, } from "../core/payments.js";
5
+ import { getCompatiblePaymentMethods, getConfiguredMethods, hasWalletConfigured, getWalletAddress, normalizePaymentMethod, } from "../core/payments.js";
6
6
  import { requiresSpendConfirmation, getDefaultTipAmount } from "../core/config.js";
7
7
  import { formatRunResult } from "../core/formatters.js";
8
8
  import { canSpend, recordSpend, requiresPolicyConfirmation } from "../core/spend-policy.js";
9
9
  import { storeFeedbackToken } from "./_token-cache.js";
10
- import { getOrCreatePendingCardSetup, formatCardSetupBlocks } from "../core/card-setup.js";
11
10
  import { formatPaymentLabel, formatRunConfirmationCommand, resolveConfirmationMethod, } from "./_payment-confirmation.js";
12
11
  const POLL_INTERVAL_MS = 3000;
13
12
  const POLL_MAX_MS = 300000;
@@ -88,30 +87,17 @@ export function registerRunTools(server) {
88
87
  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. If spending confirmation is enabled, first call returns a price quote — call again with confirmed: true to execute. Local file paths in the input (e.g. /Users/.../photo.jpg) are automatically uploaded to temporary storage and replaced with download URLs before execution. If a file you need isn't on this MCP server's filesystem (e.g. a sandboxed /mnt/... attachment), call upload_file first to get a presigned upload URL, PUT the bytes to it, then pass the returned GET URL as input instead — that keeps the bytes out of the conversation context.", {
89
88
  agent_id: z.string().describe("Agent ID (UUID, slug, or name)"),
90
89
  input: z.record(z.string(), z.unknown()).describe("Input payload for the agent"),
91
- pay_with: z.string().trim().min(1).optional().describe("Payment method — wallet ID, chain name (tempo, base, solana), 'link', or 'card'. Auto-detected if omitted."),
90
+ pay_with: z.string().trim().min(1).optional().describe("Launch payment method — wallet ID or chain name (tempo, base, solana). Auto-detected if omitted."),
92
91
  confirmed: z.boolean().optional().describe("Set to true to confirm spending after seeing the price quote."),
93
92
  }, async ({ agent_id, input, pay_with, confirmed }) => {
94
93
  if (!hasWalletConfigured()) {
95
- if (isCardPaymentEnabled()) {
96
- try {
97
- const { url } = await getOrCreatePendingCardSetup();
98
- return multiText(...formatCardSetupBlocks(url));
99
- }
100
- catch {
101
- // Fall through to the setup message below.
102
- }
103
- }
104
94
  const setupLines = [
105
95
  "No payment method configured.",
106
96
  "",
107
- "Recommended: wallet_setup({ action: \"add-link\" }) to connect a Link card or bank account.",
108
- "You can also run wallet_setup({ action: \"start\" }) to see all payment options.",
97
+ "Run wallet_setup({ action: \"start\" }) to configure a launch USDC payment method.",
109
98
  "",
110
- "USDC options: Tempo, Base, or Solana.",
99
+ "Launch options: Tempo USDC, Base USDC, or Solana USDC.",
111
100
  ];
112
- if (isCardPaymentEnabled()) {
113
- setupLines.push("", "Or wallet_setup({ action: \"add-card\" }) to connect a credit card.");
114
- }
115
101
  return text(setupLines.join("\n"));
116
102
  }
117
103
  let agent;
@@ -1,7 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { apiGet, apiPost, apiPostWithPayment } from "../core/api-client.js";
3
- import { getOrCreatePendingCardSetup, formatCardSetupBlocks } from "../core/card-setup.js";
4
- import { getCompatiblePaymentMethods, hasWalletConfigured, getConfiguredMethods, getAcceptedPaymentMethods, getWalletAddress, normalizePaymentMethod, toRegistryPaymentMethod, isCardPaymentEnabled, } from "../core/payments.js";
3
+ import { getCompatiblePaymentMethods, hasWalletConfigured, getConfiguredMethods, getAcceptedPaymentMethods, getWalletAddress, normalizePaymentMethod, toRegistryPaymentMethod, } from "../core/payments.js";
5
4
  import { requiresSpendConfirmation, getDefaultTipAmount } from "../core/config.js";
6
5
  import { agentList, formatRunResult } from "../core/formatters.js";
7
6
  import { canSpend, recordSpend, requiresPolicyConfirmation } from "../core/spend-policy.js";
@@ -126,33 +125,20 @@ export function registerSolveTools(server) {
126
125
  .trim()
127
126
  .min(1)
128
127
  .optional()
129
- .describe("Payment method — wallet ID, chain name (tempo, base, solana), 'link', or 'card'. Auto-detected if omitted."),
128
+ .describe("Launch payment method — wallet ID or chain name (tempo, base, solana). Auto-detected if omitted."),
130
129
  confirmed: z
131
130
  .boolean()
132
131
  .optional()
133
132
  .describe("Set to true to confirm spending after seeing the price quote."),
134
133
  }, async ({ intent, input, budget, pay_with, confirmed }) => {
135
134
  if (!hasWalletConfigured()) {
136
- if (isCardPaymentEnabled()) {
137
- try {
138
- const { url } = await getOrCreatePendingCardSetup();
139
- return multiText(...formatCardSetupBlocks(url));
140
- }
141
- catch {
142
- // Fall through to the setup message below.
143
- }
144
- }
145
135
  const setupLines = [
146
136
  "No payment method configured.",
147
137
  "",
148
- "Recommended: wallet_setup({ action: \"add-link\" }) to connect a Link card or bank account.",
149
- "You can also run wallet_setup({ action: \"start\" }) to see all payment options.",
138
+ "Run wallet_setup({ action: \"start\" }) to configure a launch USDC payment method.",
150
139
  "",
151
- "USDC options: Tempo, Base, or Solana.",
140
+ "Launch options: Tempo USDC, Base USDC, or Solana USDC.",
152
141
  ];
153
- if (isCardPaymentEnabled()) {
154
- setupLines.push("", "Or wallet_setup({ action: \"add-card\" }) to connect a credit card.");
155
- }
156
142
  return text(setupLines.join("\n"));
157
143
  }
158
144
  const pendingKey = makeSolvePendingKey(intent, input, budget);
@@ -30,21 +30,18 @@ function isFreshLinkSetup(pending) {
30
30
  }
31
31
  function formatPaymentSetupMenu() {
32
32
  return [
33
- "Choose a payment method to set up:",
33
+ "Choose a launch payment method to set up:",
34
34
  "",
35
- "1. Link card or bank account (recommended)",
36
- " wallet_setup({ action: \"add-link\" })",
37
- "",
38
- "2. Tempo USDC",
35
+ "1. Tempo USDC",
39
36
  " wallet_setup({ action: \"create\", chain: \"tempo\" })",
40
37
  "",
41
- "3. Base USDC",
38
+ "2. Base USDC",
42
39
  " wallet_setup({ action: \"create\", chain: \"base\" })",
43
40
  "",
44
- "4. Solana USDC",
41
+ "3. Solana USDC",
45
42
  " wallet_setup({ action: \"create\", chain: \"solana\" })",
46
43
  "",
47
- "5. Import an existing wallet",
44
+ "4. Import an existing wallet",
48
45
  " wallet_setup({ action: \"import\", chain: \"base\", key: \"<private key>\" })",
49
46
  ].join("\n");
50
47
  }
@@ -53,7 +50,7 @@ function setDefaultCryptoPaymentMethod(chain) {
53
50
  }
54
51
  export function registerWalletTools(server) {
55
52
  // ── wallet_status (extracted from check_wallet) ─────────────────
56
- server.tool("wallet_status", "Check payment readiness. Shows all configured wallets, their chains, addresses, and card status.", {}, async () => {
53
+ server.tool("wallet_status", "Check launch payment readiness. Shows configured wallets, chains, addresses, and USDC balances.", {}, async () => {
57
54
  const wallets = getWallets();
58
55
  const card = getCardConfig();
59
56
  const link = getLinkConfig();
@@ -133,10 +130,10 @@ export function registerWalletTools(server) {
133
130
  return text(lines.join("\n"));
134
131
  });
135
132
  // ── wallet_setup ────────────────────────────────────────────────
136
- server.tool("wallet_setup", "Set up or manage an Agent Wonderland payment method. Use 'start' for a guided setup menu. Link card/bank is recommended for most users. 'add-link' connects a Link card or bank account for agent payments. 'create' makes a new crypto wallet (encrypted via OWS if available, otherwise plaintext — run 'enable-ows' to upgrade). 'import' takes an existing private key. 'enable-ows' installs the Open Wallet Standard native module for encrypted at-rest storage. Tempo/Base share one EVM key; Solana uses a separate ed25519 key. NEVER delete or rotate keys programmatically; direct users to edit ~/.agentwonderland/config.json or ~/.ows/ manually.", {
133
+ server.tool("wallet_setup", "Set up or manage an Agent Wonderland launch payment method. Use 'start' for a guided USDC setup menu. 'create' makes a new crypto wallet (encrypted via OWS if available, otherwise plaintext — run 'enable-ows' to upgrade). 'import' takes an existing private key. 'enable-ows' installs the Open Wallet Standard native module for encrypted at-rest storage. Tempo/Base share one EVM key; Solana uses a separate ed25519 key. Card and Link actions are present for non-launch compatibility only and should not be recommended for launch runs. NEVER delete or rotate keys programmatically; direct users to edit ~/.agentwonderland/config.json or ~/.ows/ manually.", {
137
134
  action: z
138
135
  .enum(["start", "create", "import", "add-card", "remove-card", "add-link", "remove-link", "enable-ows"])
139
- .describe("'start' shows the guided payment setup menu, 'add-link' connects Link card/bank, 'create' makes a crypto wallet, 'import' imports an existing key, 'enable-ows' installs encrypted key storage"),
136
+ .describe("'start' shows the guided launch USDC setup menu, 'create' makes a crypto wallet, 'import' imports an existing key, 'enable-ows' installs encrypted key storage; add-card/add-link are non-launch compatibility actions"),
140
137
  name: z
141
138
  .string()
142
139
  .optional()
@@ -150,7 +147,7 @@ export function registerWalletTools(server) {
150
147
  link_payment_method_id: z.string().optional()
151
148
  .describe("Link payment method ID from `npx @stripe/link-cli payment-methods list`; used with action 'add-link'."),
152
149
  link_payment_method: z.string().optional()
153
- .describe("Friendly Link payment method selector, such as a card/bank name or last4; used with action 'add-link'."),
150
+ .describe("Friendly Link payment method selector, such as a saved payment method label or last4; used with action 'add-link'."),
154
151
  }, async ({ action, name, key, chain, link_payment_method_id, link_payment_method }) => {
155
152
  if (action === "start") {
156
153
  return text(formatPaymentSetupMenu());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentwonderland/mcp",
3
- "version": "0.1.53",
3
+ "version": "0.1.54",
4
4
  "type": "module",
5
5
  "description": "MCP server for the Agent Wonderland AI agent marketplace",
6
6
  "bin": {
@@ -86,4 +86,48 @@ describe("api-client headers", () => {
86
86
  }),
87
87
  );
88
88
  });
89
+
90
+ it("labels playbook API calls with MCP surface, version, tool, and action headers", async () => {
91
+ const fetchMock = vi.fn(async () => new Response(JSON.stringify({ ok: true }), {
92
+ status: 200,
93
+ headers: { "content-type": "application/json" },
94
+ }));
95
+ vi.stubGlobal("fetch", fetchMock);
96
+ const { apiGet, apiPost } = await import("../api-client.js");
97
+
98
+ await apiGet("/playbooks?limit=1");
99
+ await apiGet("/playbooks/competitor-ads");
100
+ await apiGet("/playbooks/competitor-ads/versions");
101
+ await apiGet("/playbooks/competitor-ads/versions/1");
102
+ await apiPost("/playbooks/competitor-ads/favorite", {});
103
+ await apiPost("/playbooks/competitor-ads/feedback", { rating: 5 });
104
+ await apiPost("/playbook-quotes", { slug: "competitor-ads", budget: 5 });
105
+ await apiPost("/playbook-runs", { slug: "competitor-ads", budget: 5 });
106
+ await apiGet("/playbook-runs/run-1");
107
+ await apiPost("/playbook-runs/run-1/steps/ads", { status: "running" });
108
+
109
+ const calls = (fetchMock.mock.calls as unknown as Array<[unknown, { headers?: unknown }]>).map(([url, init]) => ({
110
+ url: String(url).replace("https://api.agentwonderland.test", ""),
111
+ headers: init.headers as Record<string, string>,
112
+ }));
113
+
114
+ for (const call of calls) {
115
+ expect(call.headers).toMatchObject({
116
+ "Content-Type": "application/json",
117
+ Accept: "application/json",
118
+ "X-AW-Surface": "mcp",
119
+ "X-AW-MCP-Version": MCP_PACKAGE_VERSION,
120
+ });
121
+ }
122
+ expect(calls[0]).toMatchObject({ url: "/playbooks?limit=1", headers: { "X-AW-MCP-Tool": "search_playbooks", "X-AW-MCP-Action": "search" } });
123
+ expect(calls[1]).toMatchObject({ url: "/playbooks/competitor-ads", headers: { "X-AW-MCP-Tool": "get_playbook", "X-AW-MCP-Action": "view" } });
124
+ expect(calls[2]).toMatchObject({ url: "/playbooks/competitor-ads/versions", headers: { "X-AW-MCP-Tool": "get_playbook", "X-AW-MCP-Action": "view" } });
125
+ expect(calls[3]).toMatchObject({ url: "/playbooks/competitor-ads/versions/1", headers: { "X-AW-MCP-Tool": "get_playbook", "X-AW-MCP-Action": "view" } });
126
+ expect(calls[4]).toMatchObject({ url: "/playbooks/competitor-ads/favorite", headers: { "X-AW-MCP-Tool": "favorite_playbook", "X-AW-MCP-Action": "favorite" } });
127
+ expect(calls[5]).toMatchObject({ url: "/playbooks/competitor-ads/feedback", headers: { "X-AW-MCP-Tool": "rate_playbook", "X-AW-MCP-Action": "feedback" } });
128
+ expect(calls[6]).toMatchObject({ url: "/playbook-quotes", headers: { "X-AW-MCP-Tool": "run_playbook", "X-AW-MCP-Action": "quote" } });
129
+ expect(calls[7]).toMatchObject({ url: "/playbook-runs", headers: { "X-AW-MCP-Tool": "run_playbook", "X-AW-MCP-Action": "execute" } });
130
+ expect(calls[8]).toMatchObject({ url: "/playbook-runs/run-1", headers: { "X-AW-MCP-Tool": "run_playbook", "X-AW-MCP-Action": "poll" } });
131
+ expect(calls[9]).toMatchObject({ url: "/playbook-runs/run-1/steps/ads", headers: { "X-AW-MCP-Tool": "run_playbook", "X-AW-MCP-Action": "execute" } });
132
+ });
89
133
  });
@@ -40,6 +40,24 @@ function inferToolHeaders(path: string, method: string): Record<string, string>
40
40
  if (path.startsWith("/agents?") || path === "/agents" || path === "/agents/search") {
41
41
  return { "X-AW-MCP-Tool": "search_agents", "X-AW-MCP-Action": "search" };
42
42
  }
43
+ if (path.startsWith("/playbooks?") || path === "/playbooks") {
44
+ return { "X-AW-MCP-Tool": "search_playbooks", "X-AW-MCP-Action": "search" };
45
+ }
46
+ if (/^\/playbooks\/[^/]+(?:\/versions(?:\/[^/]+)?)?$/.test(path)) {
47
+ return { "X-AW-MCP-Tool": "get_playbook", "X-AW-MCP-Action": "view" };
48
+ }
49
+ if (/^\/playbooks\/[^/]+\/favorite$/.test(path)) {
50
+ return { "X-AW-MCP-Tool": "favorite_playbook", "X-AW-MCP-Action": "favorite" };
51
+ }
52
+ if (/^\/playbooks\/[^/]+\/feedback$/.test(path)) {
53
+ return { "X-AW-MCP-Tool": "rate_playbook", "X-AW-MCP-Action": "feedback" };
54
+ }
55
+ if (path === "/playbook-quotes") {
56
+ return { "X-AW-MCP-Tool": "run_playbook", "X-AW-MCP-Action": "quote" };
57
+ }
58
+ if (path === "/playbook-runs" || path.startsWith("/playbook-runs/")) {
59
+ return { "X-AW-MCP-Tool": "run_playbook", "X-AW-MCP-Action": method === "GET" ? "poll" : "execute" };
60
+ }
43
61
  if (/^\/agents\/[^/]+$/.test(path)) {
44
62
  return { "X-AW-MCP-Tool": "get_agent", "X-AW-MCP-Action": "view" };
45
63
  }
@@ -1 +1 @@
1
- export const MCP_PACKAGE_VERSION = "0.1.51";
1
+ export const MCP_PACKAGE_VERSION = "0.1.54";
package/src/index.ts CHANGED
@@ -18,6 +18,7 @@ import { registerRebateTools } from "./tools/rebates.js";
18
18
  import { registerUploadTools } from "./tools/upload.js";
19
19
  import { registerProbeTools } from "./tools/probe.js";
20
20
  import { registerProviderTools } from "./tools/providers.js";
21
+ import { registerPlaybookTools } from "./tools/playbooks.js";
21
22
 
22
23
  // ── Resources ────────────────────────────────────────────────────
23
24
  import { registerAgentResources } from "./resources/agents.js";
@@ -48,16 +49,17 @@ export async function startMcpServer(): Promise<void> {
48
49
  "WORKFLOW:",
49
50
  "1. solve(intent, input, budget) — one call: find best agent + pay + run. Use when the task is clear.",
50
51
  " OR: search_agents() → get_agent() to inspect schema → run_agent() with required fields.",
52
+ " For multi-agent workflows, use search_playbooks() → get_playbook() → run_playbook().",
51
53
  "2. If the agent returns status 'processing', poll with get_job(). Async runs resolve automatically.",
52
- "3. After a successful run, rate_agent() and optionally tip_agent() if the result was useful.",
54
+ "3. After a successful agent run, rate_agent() and optionally tip_agent() if the result was useful.",
55
+ " After a successful playbook run, offer favorite_playbook() or rate_playbook() using the returned run_id.",
53
56
  "4. Use list_jobs() to recover state across sessions (it checks every configured wallet).",
54
57
  "",
55
58
  "PAYMENT:",
56
- "- Supported payment methods: Link card/bank via @stripe/link-cli, Tempo USDC, Base USDC, and Solana USDC.",
57
- "- Link payments may ask the user to approve a spend request in Link before the first charge.",
59
+ "- Supported launch payment methods: Tempo USDC, Base USDC, and Solana USDC.",
58
60
  "- Tempo and Base share one EVM wallet key. Solana uses a separate ed25519 key. One OWS wallet can manage both.",
59
61
  "- If pay_with is omitted, the MCP auto-selects a compatible configured rail. Pass pay_with explicitly",
60
- " (tempo | base | solana | link | wallet-id) for deterministic behavior.",
62
+ " (tempo | base | solana | wallet-id) for deterministic behavior.",
61
63
  "- Payment is automatic: on a 402 challenge the MCP signs on-chain, submits, then retries. Failed runs are refunded.",
62
64
  "- If a specific rail fails, surface the real reason — do NOT silently retry with a different method.",
63
65
  "- Headless/automation: set wallet_set_policy() to cap max_per_tx and max_per_day so a runaway loop can't drain funds.",
@@ -73,7 +75,7 @@ export async function startMcpServer(): Promise<void> {
73
75
  "WALLET HYGIENE:",
74
76
  "- wallet_status shows per-chain USDC balance and the active network (mainnet vs testnet).",
75
77
  "- rebate_status shows accrued, pending, paid, and blocked consumer rebates plus recent payout transactions.",
76
- "- To set up payments: wallet_setup({ action: \"start\" }). Link card/bank is recommended for most users.",
78
+ "- To set up payments: wallet_setup({ action: \"start\" }). Use Tempo, Base, or Solana USDC for launch runs.",
77
79
  "- To create or import a crypto wallet directly: wallet_setup({ action: \"create\" }) or { action: \"import\", key }.",
78
80
  "- NEVER delete or rotate keys programmatically. Direct users to edit ~/.agentwonderland/config.json or ~/.ows/ manually.",
79
81
  ].join("\n"),
@@ -95,6 +97,7 @@ export async function startMcpServer(): Promise<void> {
95
97
  registerUploadTools(server);
96
98
  registerProbeTools(server);
97
99
  registerProviderTools(server);
100
+ registerPlaybookTools(server);
98
101
 
99
102
  // Register resources
100
103
  registerAgentResources(server);