@agentwonderland/mcp 0.1.37 → 0.1.39
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/core/__tests__/api-client.test.js +4 -0
- package/dist/core/__tests__/mpp-client.test.d.ts +1 -0
- package/dist/core/__tests__/mpp-client.test.js +46 -0
- package/dist/core/__tests__/payments.test.js +5 -14
- package/dist/core/api-client.js +27 -5
- package/dist/core/base-charge.js +1 -1
- package/dist/core/formatters.d.ts +4 -0
- package/dist/core/formatters.js +2 -1
- package/dist/core/mpp-client.d.ts +62 -0
- package/dist/core/mpp-client.js +208 -0
- package/dist/core/payments.js +3 -3
- package/dist/core/solana-charge.d.ts +1 -0
- package/dist/core/solana-charge.js +7 -3
- package/dist/core/tempo-charge.js +1 -1
- package/dist/core/types.d.ts +13 -0
- package/dist/index.js +2 -0
- package/dist/tools/__tests__/wallet.test.js +1 -0
- package/dist/tools/agent-info.js +4 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +1 -0
- package/dist/tools/providers.d.ts +2 -0
- package/dist/tools/providers.js +40 -0
- package/dist/tools/run.js +1 -1
- package/dist/tools/search.js +7 -1
- package/dist/tools/solve.js +1 -1
- package/package.json +3 -4
- package/src/core/__tests__/api-client.test.ts +4 -0
- package/src/core/__tests__/mpp-client.test.ts +53 -0
- package/src/core/__tests__/payments.test.ts +6 -20
- package/src/core/api-client.ts +29 -5
- package/src/core/base-charge.ts +1 -1
- package/src/core/formatters.ts +3 -1
- package/src/core/mpp-client.ts +286 -0
- package/src/core/payments.ts +3 -3
- package/src/core/solana-charge.ts +7 -3
- package/src/core/tempo-charge.ts +1 -1
- package/src/core/types.ts +13 -0
- package/src/index.ts +2 -0
- package/src/tools/__tests__/wallet.test.ts +1 -0
- package/src/tools/agent-info.ts +11 -1
- package/src/tools/index.ts +1 -0
- package/src/tools/providers.ts +64 -0
- package/src/tools/run.ts +1 -1
- package/src/tools/search.ts +5 -1
- package/src/tools/solve.ts +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Sends an SPL Token transfer on Solana mainnet and returns the transaction
|
|
5
5
|
* signature as the payment credential.
|
|
6
6
|
*/
|
|
7
|
-
import { Credential, Method, z } from "
|
|
7
|
+
import { Credential, Method, z } from "./mpp-client.js";
|
|
8
8
|
import { Connection, Keypair, PublicKey, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
|
|
9
9
|
import {
|
|
10
10
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
@@ -18,7 +18,9 @@ import { toAtomicAmount } from "./amount-utils.js";
|
|
|
18
18
|
|
|
19
19
|
export const SOLANA_USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" as const;
|
|
20
20
|
export const SOLANA_CHAIN_ID = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" as const;
|
|
21
|
+
export const SOLANA_CHAIN_ID_DEVNET = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG" as const;
|
|
21
22
|
const SOLANA_RPC = "https://api.mainnet-beta.solana.com";
|
|
23
|
+
const SOLANA_RPC_DEVNET = "https://api.devnet.solana.com";
|
|
22
24
|
|
|
23
25
|
const solanaChargeMethod = Method.from({
|
|
24
26
|
name: "solana" as const,
|
|
@@ -116,13 +118,15 @@ export function solanaChargeClient(config: SolanaChargeClientConfig) {
|
|
|
116
118
|
return Method.toClient(solanaChargeMethod as any, {
|
|
117
119
|
async createCredential({ challenge }: any) {
|
|
118
120
|
const { request } = challenge;
|
|
121
|
+
const chainId = request.chainId ?? request.methodDetails?.chainId ?? SOLANA_CHAIN_ID;
|
|
122
|
+
const rpcUrl = config.rpcUrl ?? (chainId === SOLANA_CHAIN_ID_DEVNET ? SOLANA_RPC_DEVNET : SOLANA_RPC);
|
|
119
123
|
const amount = toAtomicAmount(request.amount, request.decimals ?? 6);
|
|
120
124
|
const decimals = request.decimals ?? 6;
|
|
121
125
|
const mint = new PublicKey(request.currency ?? SOLANA_USDC_MINT);
|
|
122
126
|
const recipient = new PublicKey(request.recipient);
|
|
123
127
|
const keypair = await getKeypair(config.wallet);
|
|
124
128
|
const owner = keypair.publicKey;
|
|
125
|
-
const connection = new Connection(
|
|
129
|
+
const connection = new Connection(rpcUrl, "confirmed");
|
|
126
130
|
|
|
127
131
|
const sourceTokenAccount = getAssociatedTokenAddressSync(
|
|
128
132
|
mint,
|
|
@@ -177,7 +181,7 @@ export function solanaChargeClient(config: SolanaChargeClientConfig) {
|
|
|
177
181
|
return Credential.serialize({
|
|
178
182
|
challenge,
|
|
179
183
|
payload: { signature, type: "signature" as const },
|
|
180
|
-
source: `did:pkh:${
|
|
184
|
+
source: `did:pkh:${chainId}:${owner.toBase58()}`,
|
|
181
185
|
});
|
|
182
186
|
},
|
|
183
187
|
});
|
package/src/core/tempo-charge.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Sends a standard ERC-20 transfer on Tempo and returns the tx hash as the
|
|
5
5
|
* payment credential.
|
|
6
6
|
*/
|
|
7
|
-
import { Method, Credential, z } from "
|
|
7
|
+
import { Method, Credential, z } from "./mpp-client.js";
|
|
8
8
|
import type { LocalAccount } from "viem/accounts";
|
|
9
9
|
import { toAtomicAmount } from "./amount-utils.js";
|
|
10
10
|
|
package/src/core/types.ts
CHANGED
|
@@ -19,6 +19,19 @@ export interface AgentRecord {
|
|
|
19
19
|
ratingCount?: number;
|
|
20
20
|
[key: string]: unknown;
|
|
21
21
|
};
|
|
22
|
+
provider?: {
|
|
23
|
+
id?: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
slug?: string;
|
|
26
|
+
website_url?: string | null;
|
|
27
|
+
} | null;
|
|
28
|
+
urls?: {
|
|
29
|
+
public_url?: string;
|
|
30
|
+
normalized_x402_url?: string;
|
|
31
|
+
mirrored_x402_url?: string | null;
|
|
32
|
+
agent_card_url?: string;
|
|
33
|
+
provider_url?: string | null;
|
|
34
|
+
};
|
|
22
35
|
payment?: {
|
|
23
36
|
pricing?: Record<string, unknown>;
|
|
24
37
|
accepted_payments?: string[];
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { registerTipTools } from "./tools/tip.js";
|
|
|
16
16
|
import { registerPassTools } from "./tools/passes.js";
|
|
17
17
|
import { registerUploadTools } from "./tools/upload.js";
|
|
18
18
|
import { registerProbeTools } from "./tools/probe.js";
|
|
19
|
+
import { registerProviderTools } from "./tools/providers.js";
|
|
19
20
|
|
|
20
21
|
// ── Resources ────────────────────────────────────────────────────
|
|
21
22
|
import { registerAgentResources } from "./resources/agents.js";
|
|
@@ -86,6 +87,7 @@ export async function startMcpServer(): Promise<void> {
|
|
|
86
87
|
registerPassTools(server);
|
|
87
88
|
registerUploadTools(server);
|
|
88
89
|
registerProbeTools(server);
|
|
90
|
+
registerProviderTools(server);
|
|
89
91
|
|
|
90
92
|
// Register resources
|
|
91
93
|
registerAgentResources(server);
|
package/src/tools/agent-info.ts
CHANGED
|
@@ -32,6 +32,8 @@ export function registerAgentInfoTools(server: McpServer): void {
|
|
|
32
32
|
} | null | undefined;
|
|
33
33
|
|
|
34
34
|
const totalJobs = (s.completedJobs ?? a.totalExecutions ?? 0) as number;
|
|
35
|
+
const provider = a.provider ?? null;
|
|
36
|
+
const urls = a.urls ?? {};
|
|
35
37
|
const acceptedPayments = (payment.accepted_payments as string[] | undefined) ?? [];
|
|
36
38
|
const paymentLabelMap: Record<string, string> = {
|
|
37
39
|
tempo_usdc: "tempo",
|
|
@@ -47,6 +49,7 @@ export function registerAgentInfoTools(server: McpServer): void {
|
|
|
47
49
|
"",
|
|
48
50
|
(a.description as string) ?? "",
|
|
49
51
|
"",
|
|
52
|
+
...(provider?.name ? [`Provider: ${provider.name}${provider.slug ? ` (${provider.slug})` : ""}`] : []),
|
|
50
53
|
`Pricing: ${formatPrice(a.pricePerRunUsd)}`,
|
|
51
54
|
...(paymentLabels.length > 0 ? [`Accepted payments: ${paymentLabels.join(", ")}`] : []),
|
|
52
55
|
...(totalJobs > 0 && a.successRate != null
|
|
@@ -113,7 +116,14 @@ export function registerAgentInfoTools(server: McpServer): void {
|
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
lines.push(
|
|
119
|
+
lines.push(
|
|
120
|
+
"",
|
|
121
|
+
`ID: ${a.id}`,
|
|
122
|
+
`View: ${urls.public_url ?? agentWebUrl(a.id)}`,
|
|
123
|
+
...(urls.mirrored_x402_url ? [`Mirrored x402: ${urls.mirrored_x402_url}`] : []),
|
|
124
|
+
...(urls.normalized_x402_url ? [`Agent x402: ${urls.normalized_x402_url}`] : []),
|
|
125
|
+
...(urls.agent_card_url ? [`AgentCard: ${urls.agent_card_url}`] : []),
|
|
126
|
+
);
|
|
117
127
|
return text(lines.join("\n"));
|
|
118
128
|
},
|
|
119
129
|
);
|
package/src/tools/index.ts
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { apiGet } from "../core/api-client.js";
|
|
4
|
+
import { agentLine } from "../core/formatters.js";
|
|
5
|
+
import type { AgentRecord } from "../core/types.js";
|
|
6
|
+
|
|
7
|
+
function text(t: string) {
|
|
8
|
+
return { content: [{ type: "text" as const, text: t }] };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface ProviderRecord {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
slug: string;
|
|
15
|
+
description?: string | null;
|
|
16
|
+
website_url?: string | null;
|
|
17
|
+
logo_url?: string | null;
|
|
18
|
+
support_email?: string | null;
|
|
19
|
+
stats?: { live_endpoints?: number; total_executions?: number };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function registerProviderTools(server: McpServer): void {
|
|
23
|
+
server.tool(
|
|
24
|
+
"search_providers",
|
|
25
|
+
"Search API providers listed on Agent Wonderland.",
|
|
26
|
+
{
|
|
27
|
+
query: z.string().optional().describe("Provider name or keyword"),
|
|
28
|
+
limit: z.number().int().min(1).max(25).default(10),
|
|
29
|
+
},
|
|
30
|
+
async ({ query, limit }) => {
|
|
31
|
+
const params = new URLSearchParams();
|
|
32
|
+
if (query) params.set("q", query);
|
|
33
|
+
params.set("limit", String(limit));
|
|
34
|
+
const providers = await apiGet<ProviderRecord[]>(`/providers?${params}`);
|
|
35
|
+
if (providers.length === 0) return text(query ? `No providers found matching "${query}".` : "No providers found.");
|
|
36
|
+
return text([
|
|
37
|
+
`Found ${providers.length} provider${providers.length === 1 ? "" : "s"}:`,
|
|
38
|
+
"",
|
|
39
|
+
...providers.map((provider) => ` ${provider.name} (${provider.slug}) • ${provider.stats?.live_endpoints ?? 0} endpoints`),
|
|
40
|
+
].join("\n"));
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
server.tool(
|
|
45
|
+
"get_provider",
|
|
46
|
+
"Get an API provider profile and its live payable endpoints.",
|
|
47
|
+
{
|
|
48
|
+
provider: z.string().describe("Provider slug"),
|
|
49
|
+
limit: z.number().int().min(1).max(100).default(50),
|
|
50
|
+
},
|
|
51
|
+
async ({ provider, limit }) => {
|
|
52
|
+
const profile = await apiGet<ProviderRecord>(`/providers/${provider}`);
|
|
53
|
+
const agents = await apiGet<AgentRecord[]>(`/providers/${provider}/agents?limit=${limit}`);
|
|
54
|
+
return text([
|
|
55
|
+
`${profile.name} (${profile.slug})`,
|
|
56
|
+
profile.description ?? "",
|
|
57
|
+
...(profile.website_url ? [`Website: ${profile.website_url}`] : []),
|
|
58
|
+
`Live endpoints: ${profile.stats?.live_endpoints ?? agents.length}`,
|
|
59
|
+
"",
|
|
60
|
+
...agents.map((agent) => ` ${agentLine(agent)}`),
|
|
61
|
+
].filter(Boolean).join("\n"));
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
}
|
package/src/tools/run.ts
CHANGED
|
@@ -126,7 +126,7 @@ export function registerRunTools(server: McpServer): void {
|
|
|
126
126
|
"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.",
|
|
127
127
|
{
|
|
128
128
|
agent_id: z.string().describe("Agent ID (UUID, slug, or name)"),
|
|
129
|
-
input: z.record(z.unknown()).describe("Input payload for the agent"),
|
|
129
|
+
input: z.record(z.string(), z.unknown()).describe("Input payload for the agent"),
|
|
130
130
|
pay_with: z.string().trim().min(1).optional().describe("Payment method — wallet ID, chain name (tempo, base, etc.), or 'card'. Auto-detected if omitted."),
|
|
131
131
|
confirmed: z.boolean().optional().describe("Set to true to confirm spending after seeing the price quote."),
|
|
132
132
|
},
|
package/src/tools/search.ts
CHANGED
|
@@ -16,6 +16,8 @@ export function registerSearchTools(server: McpServer): void {
|
|
|
16
16
|
"Search the Agent Wonderland marketplace for AI agents. Returns a ranked list of matching agents with ratings, pricing, and job counts.",
|
|
17
17
|
{
|
|
18
18
|
query: z.string().optional().describe("Search query (natural language or keywords)"),
|
|
19
|
+
provider: z.string().optional().describe("Filter by API provider name or slug"),
|
|
20
|
+
provider_slug: z.string().optional().describe("Filter by exact API provider slug"),
|
|
19
21
|
tag: z.string().optional().describe("Filter by tag (e.g. 'code', 'image', 'data')"),
|
|
20
22
|
limit: z.number().optional().default(10).describe("Max results (1-50)"),
|
|
21
23
|
max_price: z.number().optional().describe("Maximum price per request in USD"),
|
|
@@ -23,10 +25,12 @@ export function registerSearchTools(server: McpServer): void {
|
|
|
23
25
|
sort: z.enum(["relevance", "price", "rating", "popularity", "newest"]).optional()
|
|
24
26
|
.describe("Sort results by: relevance (default), price, rating, popularity, or newest"),
|
|
25
27
|
},
|
|
26
|
-
async ({ query, tag, limit, max_price, min_rating, sort }) => {
|
|
28
|
+
async ({ query, provider, provider_slug, tag, limit, max_price, min_rating, sort }) => {
|
|
27
29
|
const requestedLimit = Math.max(1, Math.min(50, limit ?? 10));
|
|
28
30
|
const params = new URLSearchParams();
|
|
29
31
|
if (query) params.set("q", query);
|
|
32
|
+
if (provider_slug) params.set("provider_slug", provider_slug);
|
|
33
|
+
else if (provider) params.set("provider", provider);
|
|
30
34
|
if (tag) params.set("tag", tag);
|
|
31
35
|
|
|
32
36
|
// min_rating is filtered client-side on avgRating. Request extra candidates
|
package/src/tools/solve.ts
CHANGED
|
@@ -143,7 +143,7 @@ export function registerSolveTools(server: McpServer): void {
|
|
|
143
143
|
.string()
|
|
144
144
|
.describe("What you want to accomplish (natural language)"),
|
|
145
145
|
input: z
|
|
146
|
-
.record(z.unknown())
|
|
146
|
+
.record(z.string(), z.unknown())
|
|
147
147
|
.optional()
|
|
148
148
|
.default({})
|
|
149
149
|
.describe("Input payload for the agent"),
|