@agentwonderland/mcp 0.1.11 → 0.1.13

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.
@@ -6,4 +6,17 @@ export declare function isLocalFilePath(value: string): boolean;
6
6
  * Scan input object for local file paths, upload them to temporary storage,
7
7
  * and replace with download URLs. Non-file values are left unchanged.
8
8
  */
9
- export declare function uploadLocalFiles(input: Record<string, unknown>): Promise<Record<string, unknown>>;
9
+ export interface UploadResult {
10
+ input: Record<string, unknown>;
11
+ uploads: Array<{
12
+ field: string;
13
+ originalPath: string;
14
+ url: string;
15
+ }>;
16
+ }
17
+ /**
18
+ * Scan input object for local file paths, upload them to temporary storage,
19
+ * and replace with download URLs. Returns the processed input and a list
20
+ * of uploads performed.
21
+ */
22
+ export declare function uploadLocalFiles(input: Record<string, unknown>): Promise<UploadResult>;
@@ -78,10 +78,12 @@ async function uploadFile(filePath) {
78
78
  }
79
79
  /**
80
80
  * Scan input object for local file paths, upload them to temporary storage,
81
- * and replace with download URLs. Non-file values are left unchanged.
81
+ * and replace with download URLs. Returns the processed input and a list
82
+ * of uploads performed.
82
83
  */
83
84
  export async function uploadLocalFiles(input) {
84
85
  const result = { ...input };
86
+ const uploads = [];
85
87
  for (const [key, value] of Object.entries(result)) {
86
88
  if (typeof value !== "string")
87
89
  continue;
@@ -91,12 +93,14 @@ export async function uploadLocalFiles(input) {
91
93
  if (!existsSync(resolved))
92
94
  continue;
93
95
  try {
94
- result[key] = await uploadFile(value);
96
+ const url = await uploadFile(value);
97
+ result[key] = url;
98
+ uploads.push({ field: key, originalPath: value, url });
95
99
  }
96
100
  catch (err) {
97
101
  const msg = err instanceof Error ? err.message : "unknown error";
98
102
  throw new Error(`Failed to upload file "${value}" for field "${key}": ${msg}`);
99
103
  }
100
104
  }
101
- return result;
105
+ return { input: result, uploads };
102
106
  }
package/dist/index.js CHANGED
@@ -23,25 +23,28 @@ export async function startMcpServer() {
23
23
  version: "0.2.0",
24
24
  }, {
25
25
  instructions: [
26
- "Agent Wonderland is an AI agent marketplace. Use these tools to discover, run, and rate AI agents.",
26
+ "Agent Wonderland AI agent marketplace. Discover, run, and rate agents.",
27
27
  "",
28
- "IMPORTANT — File handling:",
29
- "When an agent needs a file (image, PDF, document, etc.), pass the LOCAL FILE PATH directly as the input value.",
30
- "Example: run_agent({ agent_id: \"bg-remover\", input: { image: \"/Users/you/photo.jpg\", bgColor: \"transparent\", outputFormat: \"png\" } })",
31
- "The MCP automatically uploads local files to temporary cloud storage and replaces them with download URLs before sending to the agent.",
32
- "NEVER base64-encode files. NEVER ask the user to upload files manually. Just pass the path.",
28
+ "FILE HANDLING:",
29
+ "Pass local file paths directly as input values (e.g. image: \"/path/to/photo.jpg\").",
30
+ "The MCP auto-uploads to cloud storage and replaces with a URL. Never base64-encode.",
33
31
  "",
34
- "IMPORTANT — Required fields:",
35
- "Always call get_agent() first to check the agent's input schema before running it.",
36
- "The 402 payment challenge includes the schema in the X-Agent-Input-Schema header use it to construct correct input on the first attempt.",
32
+ "WORKFLOW:",
33
+ "1. wallet_status() check payment is configured (Tempo USDC, Base USDC, or Card)",
34
+ "2. search_agents() or solve()find agents for the task",
35
+ "3. get_agent() — check required input fields before running",
36
+ "4. run_agent() or solve() with ALL required fields",
37
+ "5. Ask user to rate or tip after a successful run",
37
38
  "",
38
- "Workflow:",
39
- "1. search_agents or solve to find agents",
40
- "2. get_agent to check required input fields and pricing",
41
- "3. run_agent or solve with ALL required fields filled in",
42
- "4. After a successful run, ask the user if they want to rate or tip",
39
+ "PAYMENT:",
40
+ "- Automatic via configured wallet. User does nothing.",
41
+ "- Supports Tempo USDC, Base USDC, and Stripe Card.",
42
+ "- Input validation runs before payment invalid input is never charged.",
43
+ "- Failed agent executions trigger automatic refunds to the consumer's wallet.",
43
44
  "",
44
- "Payment is automatic via the configured wallet. The user does not need to do anything for payment.",
45
+ "REQUIRED FIELDS:",
46
+ "Always check the agent's input schema (via get_agent) before calling run_agent.",
47
+ "Include ALL required fields in the first attempt to avoid validation errors.",
45
48
  ].join("\n"),
46
49
  });
47
50
  // Register tools
package/dist/tools/run.js CHANGED
@@ -56,8 +56,15 @@ export function registerRunTools(server) {
56
56
  }
57
57
  const method = pay_with;
58
58
  let processedInput;
59
+ let uploadSummary = "";
59
60
  try {
60
- processedInput = await uploadLocalFiles(input);
61
+ const uploadResult = await uploadLocalFiles(input);
62
+ processedInput = uploadResult.input;
63
+ if (uploadResult.uploads.length > 0) {
64
+ uploadSummary = uploadResult.uploads
65
+ .map((u) => `Uploaded ${u.field}: ${u.originalPath} → ${u.url.slice(0, 80)}...`)
66
+ .join("\n");
67
+ }
61
68
  }
62
69
  catch (err) {
63
70
  const msg = err instanceof Error ? err.message : "File upload failed";
@@ -110,7 +117,7 @@ export function registerRunTools(server) {
110
117
  }
111
118
  }
112
119
  if (status !== "success") {
113
- return multiText(formatted, "The agent execution failed. A refund has been initiated automatically.");
120
+ return multiText(uploadSummary ? `${uploadSummary}\n\n${formatted}` : formatted, "The agent execution failed. A refund has been initiated automatically.");
114
121
  }
115
122
  const costLine = actualCost != null ? `Paid $${actualCost.toFixed(actualCost < 0.01 ? 4 : 2)}.` : "";
116
123
  // Separate the feedback ask into its own content block so the LLM
@@ -127,6 +134,6 @@ export function registerRunTools(server) {
127
134
  ] : []),
128
135
  `To save for later: favorite_agent({ agent_id: "${resultAgentId}" })`,
129
136
  ].join("\n");
130
- return multiText(formatted, feedbackAsk);
137
+ return multiText(uploadSummary ? `${uploadSummary}\n\n${formatted}` : formatted, feedbackAsk);
131
138
  });
132
139
  }
@@ -78,7 +78,8 @@ export function registerSolveTools(server) {
78
78
  // Path 1: If authenticated, use the platform /solve route
79
79
  let processedInput;
80
80
  try {
81
- processedInput = await uploadLocalFiles(input);
81
+ const uploadResult = await uploadLocalFiles(input);
82
+ processedInput = uploadResult.input;
82
83
  }
83
84
  catch (err) {
84
85
  const msg = err instanceof Error ? err.message : "File upload failed";
@@ -149,7 +150,8 @@ export function registerSolveTools(server) {
149
150
  let result;
150
151
  let processedInput2;
151
152
  try {
152
- processedInput2 = await uploadLocalFiles(input);
153
+ const uploadResult2 = await uploadLocalFiles(input);
154
+ processedInput2 = uploadResult2.input;
153
155
  }
154
156
  catch (err) {
155
157
  const msg = err instanceof Error ? err.message : "File upload failed";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentwonderland/mcp",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "description": "MCP server for the Agent Wonderland AI agent marketplace",
6
6
  "bin": {
@@ -91,10 +91,21 @@ async function uploadFile(filePath: string): Promise<string> {
91
91
  * Scan input object for local file paths, upload them to temporary storage,
92
92
  * and replace with download URLs. Non-file values are left unchanged.
93
93
  */
94
+ export interface UploadResult {
95
+ input: Record<string, unknown>;
96
+ uploads: Array<{ field: string; originalPath: string; url: string }>;
97
+ }
98
+
99
+ /**
100
+ * Scan input object for local file paths, upload them to temporary storage,
101
+ * and replace with download URLs. Returns the processed input and a list
102
+ * of uploads performed.
103
+ */
94
104
  export async function uploadLocalFiles(
95
105
  input: Record<string, unknown>,
96
- ): Promise<Record<string, unknown>> {
106
+ ): Promise<UploadResult> {
97
107
  const result = { ...input };
108
+ const uploads: UploadResult["uploads"] = [];
98
109
 
99
110
  for (const [key, value] of Object.entries(result)) {
100
111
  if (typeof value !== "string") continue;
@@ -104,12 +115,14 @@ export async function uploadLocalFiles(
104
115
  if (!existsSync(resolved)) continue;
105
116
 
106
117
  try {
107
- result[key] = await uploadFile(value);
118
+ const url = await uploadFile(value);
119
+ result[key] = url;
120
+ uploads.push({ field: key, originalPath: value, url });
108
121
  } catch (err) {
109
122
  const msg = err instanceof Error ? err.message : "unknown error";
110
123
  throw new Error(`Failed to upload file "${value}" for field "${key}": ${msg}`);
111
124
  }
112
125
  }
113
126
 
114
- return result;
127
+ return { input: result, uploads };
115
128
  }
package/src/index.ts CHANGED
@@ -30,25 +30,28 @@ export async function startMcpServer(): Promise<void> {
30
30
  },
31
31
  {
32
32
  instructions: [
33
- "Agent Wonderland is an AI agent marketplace. Use these tools to discover, run, and rate AI agents.",
33
+ "Agent Wonderland AI agent marketplace. Discover, run, and rate agents.",
34
34
  "",
35
- "IMPORTANT — File handling:",
36
- "When an agent needs a file (image, PDF, document, etc.), pass the LOCAL FILE PATH directly as the input value.",
37
- "Example: run_agent({ agent_id: \"bg-remover\", input: { image: \"/Users/you/photo.jpg\", bgColor: \"transparent\", outputFormat: \"png\" } })",
38
- "The MCP automatically uploads local files to temporary cloud storage and replaces them with download URLs before sending to the agent.",
39
- "NEVER base64-encode files. NEVER ask the user to upload files manually. Just pass the path.",
35
+ "FILE HANDLING:",
36
+ "Pass local file paths directly as input values (e.g. image: \"/path/to/photo.jpg\").",
37
+ "The MCP auto-uploads to cloud storage and replaces with a URL. Never base64-encode.",
40
38
  "",
41
- "IMPORTANT — Required fields:",
42
- "Always call get_agent() first to check the agent's input schema before running it.",
43
- "The 402 payment challenge includes the schema in the X-Agent-Input-Schema header use it to construct correct input on the first attempt.",
39
+ "WORKFLOW:",
40
+ "1. wallet_status() check payment is configured (Tempo USDC, Base USDC, or Card)",
41
+ "2. search_agents() or solve()find agents for the task",
42
+ "3. get_agent() — check required input fields before running",
43
+ "4. run_agent() or solve() with ALL required fields",
44
+ "5. Ask user to rate or tip after a successful run",
44
45
  "",
45
- "Workflow:",
46
- "1. search_agents or solve to find agents",
47
- "2. get_agent to check required input fields and pricing",
48
- "3. run_agent or solve with ALL required fields filled in",
49
- "4. After a successful run, ask the user if they want to rate or tip",
46
+ "PAYMENT:",
47
+ "- Automatic via configured wallet. User does nothing.",
48
+ "- Supports Tempo USDC, Base USDC, and Stripe Card.",
49
+ "- Input validation runs before payment invalid input is never charged.",
50
+ "- Failed agent executions trigger automatic refunds to the consumer's wallet.",
50
51
  "",
51
- "Payment is automatic via the configured wallet. The user does not need to do anything for payment.",
52
+ "REQUIRED FIELDS:",
53
+ "Always check the agent's input schema (via get_agent) before calling run_agent.",
54
+ "Include ALL required fields in the first attempt to avoid validation errors.",
52
55
  ].join("\n"),
53
56
  },
54
57
  );
package/src/tools/run.ts CHANGED
@@ -75,8 +75,15 @@ export function registerRunTools(server: McpServer): void {
75
75
 
76
76
  const method = pay_with;
77
77
  let processedInput: Record<string, unknown>;
78
+ let uploadSummary = "";
78
79
  try {
79
- processedInput = await uploadLocalFiles(input);
80
+ const uploadResult = await uploadLocalFiles(input);
81
+ processedInput = uploadResult.input;
82
+ if (uploadResult.uploads.length > 0) {
83
+ uploadSummary = uploadResult.uploads
84
+ .map((u) => `Uploaded ${u.field}: ${u.originalPath} → ${u.url.slice(0, 80)}...`)
85
+ .join("\n");
86
+ }
80
87
  } catch (err) {
81
88
  const msg = err instanceof Error ? err.message : "File upload failed";
82
89
  return text(`Error: ${msg}`);
@@ -139,7 +146,7 @@ export function registerRunTools(server: McpServer): void {
139
146
 
140
147
  if (status !== "success") {
141
148
  return multiText(
142
- formatted,
149
+ uploadSummary ? `${uploadSummary}\n\n${formatted}` : formatted,
143
150
  "The agent execution failed. A refund has been initiated automatically.",
144
151
  );
145
152
  }
@@ -161,7 +168,7 @@ export function registerRunTools(server: McpServer): void {
161
168
  `To save for later: favorite_agent({ agent_id: "${resultAgentId}" })`,
162
169
  ].join("\n");
163
170
 
164
- return multiText(formatted, feedbackAsk);
171
+ return multiText(uploadSummary ? `${uploadSummary}\n\n${formatted}` : formatted, feedbackAsk);
165
172
  },
166
173
  );
167
174
  }
@@ -97,7 +97,8 @@ export function registerSolveTools(server: McpServer): void {
97
97
  // Path 1: If authenticated, use the platform /solve route
98
98
  let processedInput: Record<string, unknown>;
99
99
  try {
100
- processedInput = await uploadLocalFiles(input);
100
+ const uploadResult = await uploadLocalFiles(input);
101
+ processedInput = uploadResult.input;
101
102
  } catch (err) {
102
103
  const msg = err instanceof Error ? err.message : "File upload failed";
103
104
  return text(`Error: ${msg}`);
@@ -177,7 +178,8 @@ export function registerSolveTools(server: McpServer): void {
177
178
  let result: Record<string, unknown>;
178
179
  let processedInput2: Record<string, unknown>;
179
180
  try {
180
- processedInput2 = await uploadLocalFiles(input);
181
+ const uploadResult2 = await uploadLocalFiles(input);
182
+ processedInput2 = uploadResult2.input;
181
183
  } catch (err) {
182
184
  const msg = err instanceof Error ? err.message : "File upload failed";
183
185
  return text(`Error: ${msg}`);