@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.
- package/dist/core/api-client.d.ts +14 -0
- package/dist/core/api-client.js +98 -0
- package/dist/core/config.d.ts +77 -0
- package/dist/core/config.js +297 -0
- package/dist/core/formatters.d.ts +70 -0
- package/dist/core/formatters.js +193 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +6 -0
- package/dist/core/ows-adapter.d.ts +43 -0
- package/dist/core/ows-adapter.js +100 -0
- package/dist/core/payments.d.ts +41 -0
- package/dist/core/payments.js +254 -0
- package/dist/core/types.d.ts +27 -0
- package/dist/core/types.js +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +53 -0
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/index.js +89 -0
- package/dist/resources/agents.d.ts +2 -0
- package/dist/resources/agents.js +34 -0
- package/dist/resources/jobs.d.ts +2 -0
- package/dist/resources/jobs.js +15 -0
- package/dist/resources/wallet.d.ts +2 -0
- package/dist/resources/wallet.js +26 -0
- package/dist/tools/_token-cache.d.ts +5 -0
- package/dist/tools/_token-cache.js +9 -0
- package/dist/tools/agent-info.d.ts +2 -0
- package/dist/tools/agent-info.js +97 -0
- package/dist/tools/favorites.d.ts +2 -0
- package/dist/tools/favorites.js +51 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/jobs.d.ts +2 -0
- package/dist/tools/jobs.js +49 -0
- package/dist/tools/rate.d.ts +2 -0
- package/dist/tools/rate.js +44 -0
- package/dist/tools/run.d.ts +2 -0
- package/dist/tools/run.js +80 -0
- package/dist/tools/search.d.ts +2 -0
- package/dist/tools/search.js +81 -0
- package/dist/tools/solve.d.ts +2 -0
- package/dist/tools/solve.js +124 -0
- package/dist/tools/tip.d.ts +2 -0
- package/dist/tools/tip.js +40 -0
- package/dist/tools/wallet.d.ts +2 -0
- package/dist/tools/wallet.js +197 -0
- package/package.json +49 -0
- package/src/core/api-client.ts +114 -0
- package/src/core/config.ts +384 -0
- package/src/core/formatters.ts +256 -0
- package/src/core/index.ts +6 -0
- package/src/core/ows-adapter.ts +214 -0
- package/src/core/payments.ts +278 -0
- package/src/core/types.ts +28 -0
- package/src/index.ts +65 -0
- package/src/prompts/index.ts +120 -0
- package/src/resources/agents.ts +37 -0
- package/src/resources/jobs.ts +17 -0
- package/src/resources/wallet.ts +30 -0
- package/src/tools/_token-cache.ts +18 -0
- package/src/tools/agent-info.ts +120 -0
- package/src/tools/favorites.ts +74 -0
- package/src/tools/index.ts +9 -0
- package/src/tools/jobs.ts +69 -0
- package/src/tools/rate.ts +62 -0
- package/src/tools/run.ts +97 -0
- package/src/tools/search.ts +96 -0
- package/src/tools/solve.ts +162 -0
- package/src/tools/tip.ts +59 -0
- package/src/tools/wallet.ts +268 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OWS (Open Wallet Standard) adapter.
|
|
3
|
+
*
|
|
4
|
+
* Bridges OWS native signing with viem's Account type so that mppx and
|
|
5
|
+
* any other viem-based flow can use OWS-managed keys transparently.
|
|
6
|
+
*
|
|
7
|
+
* The OWS SDK (`@open-wallet-standard/core`) is a NAPI native module.
|
|
8
|
+
* ALL imports are dynamic so the CLI works without OWS installed.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { LocalAccount } from "viem/accounts";
|
|
12
|
+
import type { Hex } from "viem";
|
|
13
|
+
|
|
14
|
+
// Note: OWS provides encrypted key storage at rest (~/.ows/, AES-256-GCM).
|
|
15
|
+
// For EVM signing, we export the secp256k1 key and use viem's native
|
|
16
|
+
// privateKeyToAccount, which handles custom transaction types (Tempo EIP-5806)
|
|
17
|
+
// that OWS's built-in signing doesn't support.
|
|
18
|
+
|
|
19
|
+
// Re-declare the subset of OWS types we use so callers don't need the SDK
|
|
20
|
+
// installed at typecheck time.
|
|
21
|
+
interface OwsAccountInfo {
|
|
22
|
+
chainId: string;
|
|
23
|
+
address: string;
|
|
24
|
+
derivationPath: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface OwsWalletInfo {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
accounts: OwsAccountInfo[];
|
|
31
|
+
createdAt: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface OwsSignResult {
|
|
35
|
+
signature: string;
|
|
36
|
+
recoveryId?: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface OwsSdk {
|
|
40
|
+
createWallet(
|
|
41
|
+
name: string,
|
|
42
|
+
passphrase?: string | null,
|
|
43
|
+
words?: number | null,
|
|
44
|
+
vaultPathOpt?: string | null,
|
|
45
|
+
): OwsWalletInfo;
|
|
46
|
+
importWalletPrivateKey(
|
|
47
|
+
name: string,
|
|
48
|
+
privateKeyHex: string,
|
|
49
|
+
passphrase?: string | null,
|
|
50
|
+
vaultPathOpt?: string | null,
|
|
51
|
+
chain?: string | null,
|
|
52
|
+
): OwsWalletInfo;
|
|
53
|
+
listWallets(vaultPathOpt?: string | null): OwsWalletInfo[];
|
|
54
|
+
getWallet(
|
|
55
|
+
nameOrId: string,
|
|
56
|
+
vaultPathOpt?: string | null,
|
|
57
|
+
): OwsWalletInfo;
|
|
58
|
+
signTransaction(
|
|
59
|
+
wallet: string,
|
|
60
|
+
chain: string,
|
|
61
|
+
txHex: string,
|
|
62
|
+
passphrase?: string | null,
|
|
63
|
+
index?: number | null,
|
|
64
|
+
vaultPathOpt?: string | null,
|
|
65
|
+
): OwsSignResult;
|
|
66
|
+
signMessage(
|
|
67
|
+
wallet: string,
|
|
68
|
+
chain: string,
|
|
69
|
+
message: string,
|
|
70
|
+
passphrase?: string | null,
|
|
71
|
+
encoding?: string | null,
|
|
72
|
+
index?: number | null,
|
|
73
|
+
vaultPathOpt?: string | null,
|
|
74
|
+
): OwsSignResult;
|
|
75
|
+
signTypedData(
|
|
76
|
+
wallet: string,
|
|
77
|
+
chain: string,
|
|
78
|
+
typedDataJson: string,
|
|
79
|
+
passphrase?: string | null,
|
|
80
|
+
index?: number | null,
|
|
81
|
+
vaultPathOpt?: string | null,
|
|
82
|
+
): OwsSignResult;
|
|
83
|
+
exportWallet(
|
|
84
|
+
nameOrId: string,
|
|
85
|
+
passphrase?: string | null,
|
|
86
|
+
vaultPathOpt?: string | null,
|
|
87
|
+
): string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ── Helpers ──────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
const OWS_INSTALL_HINT =
|
|
93
|
+
"OWS is not installed. Install with: npm install -g @open-wallet-standard/core";
|
|
94
|
+
|
|
95
|
+
async function loadOws(): Promise<OwsSdk> {
|
|
96
|
+
try {
|
|
97
|
+
// @ts-ignore — optional peer dep, dynamically imported
|
|
98
|
+
return (await import("@open-wallet-standard/core")) as unknown as OwsSdk;
|
|
99
|
+
} catch {
|
|
100
|
+
throw new Error(OWS_INSTALL_HINT);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function findEvmAccount(
|
|
105
|
+
wallet: OwsWalletInfo,
|
|
106
|
+
): OwsAccountInfo {
|
|
107
|
+
// OWS uses CAIP-2 chain IDs: "eip155:1" for EVM, or "evm" shorthand
|
|
108
|
+
const evm = wallet.accounts.find((a) =>
|
|
109
|
+
a.chainId.startsWith("eip155") || a.chainId.startsWith("evm"),
|
|
110
|
+
);
|
|
111
|
+
if (!evm) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`Wallet "${wallet.name}" (${wallet.id}) has no EVM account.`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return evm;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── Public API ───────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Check whether the OWS native module can be loaded.
|
|
123
|
+
*/
|
|
124
|
+
export async function isOwsAvailable(): Promise<boolean> {
|
|
125
|
+
try {
|
|
126
|
+
// @ts-ignore — optional peer dep, dynamically imported
|
|
127
|
+
await import("@open-wallet-standard/core");
|
|
128
|
+
return true;
|
|
129
|
+
} catch {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Build a viem-compatible `LocalAccount` backed by an OWS wallet.
|
|
136
|
+
*
|
|
137
|
+
* @param walletId - OWS wallet name or ID
|
|
138
|
+
* @param chain - OWS chain identifier (default "evm")
|
|
139
|
+
*/
|
|
140
|
+
export async function owsAccountFromWalletId(
|
|
141
|
+
walletId: string,
|
|
142
|
+
_chain?: string,
|
|
143
|
+
): Promise<LocalAccount> {
|
|
144
|
+
const ows = await loadOws();
|
|
145
|
+
const wallet = ows.getWallet(walletId);
|
|
146
|
+
findEvmAccount(wallet); // Validate EVM account exists
|
|
147
|
+
|
|
148
|
+
// Export the secp256k1 key from OWS and use viem's privateKeyToAccount.
|
|
149
|
+
// This is necessary because mppx uses Tempo's custom transaction types
|
|
150
|
+
// (EIP-5806 delegate calls) which OWS's native signing can't serialize.
|
|
151
|
+
// OWS provides encrypted storage at rest; viem handles signing in memory.
|
|
152
|
+
const exported = ows.exportWallet(walletId);
|
|
153
|
+
const keys = JSON.parse(exported) as { secp256k1?: string; ed25519?: string };
|
|
154
|
+
if (!keys.secp256k1) {
|
|
155
|
+
throw new Error(`Wallet "${wallet.name}" has no secp256k1 key for EVM signing.`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
159
|
+
return privateKeyToAccount(`0x${keys.secp256k1}` as Hex);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Create a new OWS wallet and return its ID + EVM address.
|
|
164
|
+
*/
|
|
165
|
+
export async function createOwsWallet(
|
|
166
|
+
name: string,
|
|
167
|
+
): Promise<{ walletId: string; address: string }> {
|
|
168
|
+
const ows = await loadOws();
|
|
169
|
+
const wallet = ows.createWallet(name);
|
|
170
|
+
const evmAccount = findEvmAccount(wallet);
|
|
171
|
+
return { walletId: wallet.id, address: evmAccount.address };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Import an existing EVM private key into OWS.
|
|
176
|
+
*/
|
|
177
|
+
export async function importKeyToOws(
|
|
178
|
+
privateKey: string,
|
|
179
|
+
name: string,
|
|
180
|
+
): Promise<{ walletId: string; address: string }> {
|
|
181
|
+
const ows = await loadOws();
|
|
182
|
+
const normalizedKey = privateKey.startsWith("0x")
|
|
183
|
+
? privateKey.slice(2)
|
|
184
|
+
: privateKey;
|
|
185
|
+
const wallet = ows.importWalletPrivateKey(
|
|
186
|
+
name,
|
|
187
|
+
normalizedKey,
|
|
188
|
+
null,
|
|
189
|
+
null,
|
|
190
|
+
"evm",
|
|
191
|
+
);
|
|
192
|
+
const evmAccount = findEvmAccount(wallet);
|
|
193
|
+
return { walletId: wallet.id, address: evmAccount.address };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* List all OWS wallets that have an EVM account.
|
|
198
|
+
*/
|
|
199
|
+
export async function listOwsWallets(): Promise<
|
|
200
|
+
Array<{ id: string; name: string; address: string }>
|
|
201
|
+
> {
|
|
202
|
+
const ows = await loadOws();
|
|
203
|
+
const wallets = ows.listWallets();
|
|
204
|
+
const result: Array<{ id: string; name: string; address: string }> = [];
|
|
205
|
+
|
|
206
|
+
for (const w of wallets) {
|
|
207
|
+
const evm = w.accounts.find((a) => a.chainId.startsWith("eip155") || a.chainId.startsWith("evm"));
|
|
208
|
+
if (evm) {
|
|
209
|
+
result.push({ id: w.id, name: w.name, address: evm.address });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MPP client-side payment handler.
|
|
3
|
+
*
|
|
4
|
+
* All chains use MPP protocol (mppx):
|
|
5
|
+
* - tempo chain → MPP protocol (mppx)
|
|
6
|
+
* - base → MPP protocol (mppx)
|
|
7
|
+
* - card → MPP + SPT (mppx) via Stripe
|
|
8
|
+
*
|
|
9
|
+
* Users can configure multiple wallets with different chains and select
|
|
10
|
+
* which to use per-request via `--pay-with <wallet-id|chain|card>`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
getWallets,
|
|
15
|
+
getDefaultWallet,
|
|
16
|
+
getCardConfig,
|
|
17
|
+
resolveWalletAndChain,
|
|
18
|
+
getApiUrl,
|
|
19
|
+
type WalletEntry,
|
|
20
|
+
} from "./config.js";
|
|
21
|
+
|
|
22
|
+
// Cache per wallet+chain combo to avoid re-initializing
|
|
23
|
+
const fetchCache = new Map<string, typeof fetch>();
|
|
24
|
+
|
|
25
|
+
// ── Helpers ─────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
function normalizeKey(key: string): `0x${string}` {
|
|
28
|
+
return (key.startsWith("0x") ? key : `0x${key}`) as `0x${string}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function cacheKey(walletId: string, chain: string): string {
|
|
32
|
+
return `${walletId}:${chain}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ── Per-protocol initializers ───────────────────────────────────
|
|
36
|
+
|
|
37
|
+
async function initMpp(wallet: WalletEntry): Promise<typeof fetch | null> {
|
|
38
|
+
try {
|
|
39
|
+
const { Mppx, tempo } = await import("mppx/client");
|
|
40
|
+
let account;
|
|
41
|
+
|
|
42
|
+
if (wallet.keyType === "ows" && wallet.owsWalletId) {
|
|
43
|
+
const { owsAccountFromWalletId } = await import("./ows-adapter.js");
|
|
44
|
+
account = await owsAccountFromWalletId(wallet.owsWalletId);
|
|
45
|
+
} else if (wallet.key) {
|
|
46
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
47
|
+
account = privateKeyToAccount(normalizeKey(wallet.key));
|
|
48
|
+
} else {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const mppx = Mppx.create({ methods: [tempo({ account })] as any });
|
|
53
|
+
return mppx.fetch.bind(mppx) as typeof fetch;
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function initCard(): Promise<typeof fetch | null> {
|
|
60
|
+
const cardConfig = getCardConfig();
|
|
61
|
+
if (!cardConfig) return null;
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const { Mppx, stripe } = await import("mppx/client");
|
|
65
|
+
const apiUrl = getApiUrl();
|
|
66
|
+
const pmId = cardConfig.paymentMethodId ?? undefined;
|
|
67
|
+
const mppx = Mppx.create({
|
|
68
|
+
methods: [stripe({
|
|
69
|
+
paymentMethod: pmId,
|
|
70
|
+
createToken: async (params: {
|
|
71
|
+
amount: string;
|
|
72
|
+
currency: string;
|
|
73
|
+
networkId?: string;
|
|
74
|
+
expiresAt: number;
|
|
75
|
+
}) => {
|
|
76
|
+
const res = await fetch(`${apiUrl}/card/spt`, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "Content-Type": "application/json" },
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
consumer_token: cardConfig.consumerToken,
|
|
81
|
+
amount: params.amount,
|
|
82
|
+
currency: params.currency,
|
|
83
|
+
network_id: params.networkId,
|
|
84
|
+
expires_at: params.expiresAt,
|
|
85
|
+
}),
|
|
86
|
+
});
|
|
87
|
+
if (!res.ok) throw new Error(`SPT creation failed: ${await res.text()}`);
|
|
88
|
+
const { spt } = await res.json() as { spt: string };
|
|
89
|
+
return spt;
|
|
90
|
+
},
|
|
91
|
+
})] as any,
|
|
92
|
+
});
|
|
93
|
+
return mppx.fetch.bind(mppx) as typeof fetch;
|
|
94
|
+
} catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Initialize a payment-aware fetch for a given wallet + chain.
|
|
101
|
+
*/
|
|
102
|
+
async function initForChain(wallet: WalletEntry, _chain: string): Promise<typeof fetch | null> {
|
|
103
|
+
return initMpp(wallet);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── Public API ──────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Returns a payment-aware fetch for a specific method, or the best
|
|
110
|
+
* available method if none is specified.
|
|
111
|
+
*
|
|
112
|
+
* @param method - wallet ID, chain name, or "card". Omit for auto-detection.
|
|
113
|
+
*/
|
|
114
|
+
export async function getPaymentFetch(method?: string): Promise<typeof fetch> {
|
|
115
|
+
// Card payment
|
|
116
|
+
if (method === "card") {
|
|
117
|
+
const ck = "card:card";
|
|
118
|
+
if (fetchCache.has(ck)) return fetchCache.get(ck)!;
|
|
119
|
+
const pf = await initCard();
|
|
120
|
+
if (pf) {
|
|
121
|
+
fetchCache.set(ck, pf);
|
|
122
|
+
return pf;
|
|
123
|
+
}
|
|
124
|
+
throw new Error('Payment method "card" is not configured. Run: aw wallet setup');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Explicit method requested (wallet ID or chain name)
|
|
128
|
+
if (method) {
|
|
129
|
+
const resolved = resolveWalletAndChain(method);
|
|
130
|
+
if (!resolved) {
|
|
131
|
+
throw new Error(`Payment method "${method}" is not configured. Run: aw wallet setup`);
|
|
132
|
+
}
|
|
133
|
+
const ck = cacheKey(resolved.wallet.id, resolved.chain);
|
|
134
|
+
if (fetchCache.has(ck)) return fetchCache.get(ck)!;
|
|
135
|
+
const pf = await initForChain(resolved.wallet, resolved.chain);
|
|
136
|
+
if (pf) {
|
|
137
|
+
fetchCache.set(ck, pf);
|
|
138
|
+
return pf;
|
|
139
|
+
}
|
|
140
|
+
throw new Error(`Payment method "${method}" is not configured. Run: aw wallet setup`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Auto-detect: try default wallet, then card
|
|
144
|
+
const configured = getConfiguredMethods();
|
|
145
|
+
for (const m of configured) {
|
|
146
|
+
if (m === "card") {
|
|
147
|
+
const ck = "card:card";
|
|
148
|
+
if (fetchCache.has(ck)) return fetchCache.get(ck)!;
|
|
149
|
+
const pf = await initCard();
|
|
150
|
+
if (pf) {
|
|
151
|
+
fetchCache.set(ck, pf);
|
|
152
|
+
return pf;
|
|
153
|
+
}
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// It's a chain name — resolve to wallet
|
|
158
|
+
const resolved = resolveWalletAndChain(m);
|
|
159
|
+
if (!resolved) continue;
|
|
160
|
+
const ck = cacheKey(resolved.wallet.id, resolved.chain);
|
|
161
|
+
if (fetchCache.has(ck)) return fetchCache.get(ck)!;
|
|
162
|
+
const pf = await initForChain(resolved.wallet, resolved.chain);
|
|
163
|
+
if (pf) {
|
|
164
|
+
fetchCache.set(ck, pf);
|
|
165
|
+
return pf;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return fetch;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* List all configured payment identifiers. Returns chain names from wallets
|
|
174
|
+
* (with default wallet's default chain first) + "card" if configured.
|
|
175
|
+
*/
|
|
176
|
+
export function getConfiguredMethods(): string[] {
|
|
177
|
+
const methods: string[] = [];
|
|
178
|
+
const wallets = getWallets();
|
|
179
|
+
|
|
180
|
+
// Collect all chains from wallets, default wallet's chains first
|
|
181
|
+
const defaultWallet = getDefaultWallet();
|
|
182
|
+
if (defaultWallet) {
|
|
183
|
+
const defChain = defaultWallet.defaultChain ?? defaultWallet.chains[0];
|
|
184
|
+
if (defChain) methods.push(defChain);
|
|
185
|
+
// Add remaining chains from default wallet
|
|
186
|
+
for (const c of defaultWallet.chains) {
|
|
187
|
+
if (!methods.includes(c)) methods.push(c);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Add chains from other wallets
|
|
192
|
+
for (const w of wallets) {
|
|
193
|
+
if (w.id === defaultWallet?.id) continue;
|
|
194
|
+
for (const c of w.chains) {
|
|
195
|
+
if (!methods.includes(c)) methods.push(c);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Add card if configured
|
|
200
|
+
if (getCardConfig()) {
|
|
201
|
+
methods.push("card");
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return methods;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Human-friendly display name for a payment method identifier.
|
|
209
|
+
*/
|
|
210
|
+
export function paymentMethodDisplayName(method: string): string {
|
|
211
|
+
switch (method) {
|
|
212
|
+
case "tempo": return "Tempo USDC";
|
|
213
|
+
case "base": return "Base USDC";
|
|
214
|
+
case "solana": return "Solana USDC";
|
|
215
|
+
case "card": return "Card";
|
|
216
|
+
default: return method;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Return the consumer's configured payment methods in registry API format.
|
|
222
|
+
* Maps CLI method names (tempo, base, card) to registry identifiers
|
|
223
|
+
* (tempo_usdc, base_usdc, stripe_card).
|
|
224
|
+
*/
|
|
225
|
+
export function getAcceptedPaymentMethods(): string[] {
|
|
226
|
+
const methods = getConfiguredMethods();
|
|
227
|
+
const map: Record<string, string> = {
|
|
228
|
+
tempo: "tempo_usdc",
|
|
229
|
+
base: "base_usdc",
|
|
230
|
+
solana: "solana_usdc",
|
|
231
|
+
card: "stripe_card",
|
|
232
|
+
};
|
|
233
|
+
return methods.map((m) => map[m]).filter(Boolean);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Check whether any payment method is configured.
|
|
238
|
+
*/
|
|
239
|
+
export function hasWalletConfigured(): boolean {
|
|
240
|
+
return getWallets().length > 0 || getCardConfig() !== null;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get address for a specific method, or the first configured one.
|
|
245
|
+
*/
|
|
246
|
+
export async function getWalletAddress(method?: string): Promise<string | null> {
|
|
247
|
+
let wallet: WalletEntry | undefined;
|
|
248
|
+
|
|
249
|
+
if (method && method !== "card") {
|
|
250
|
+
const resolved = resolveWalletAndChain(method);
|
|
251
|
+
wallet = resolved?.wallet;
|
|
252
|
+
} else if (!method) {
|
|
253
|
+
wallet = getDefaultWallet();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (!wallet) return null;
|
|
257
|
+
|
|
258
|
+
// OWS-managed wallet: derive address via the adapter
|
|
259
|
+
if (wallet.keyType === "ows" && wallet.owsWalletId) {
|
|
260
|
+
try {
|
|
261
|
+
const { owsAccountFromWalletId } = await import("./ows-adapter.js");
|
|
262
|
+
const account = await owsAccountFromWalletId(wallet.owsWalletId);
|
|
263
|
+
return account.address;
|
|
264
|
+
} catch {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Raw EVM key path
|
|
270
|
+
if (!wallet.key) return null;
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
274
|
+
return privateKeyToAccount(normalizeKey(wallet.key)).address;
|
|
275
|
+
} catch {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared type definitions for the MCP package.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface AgentRecord {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
pricePer1kTokens?: string;
|
|
10
|
+
pricingModel?: string;
|
|
11
|
+
avgRating?: number | null;
|
|
12
|
+
totalExecutions?: number;
|
|
13
|
+
successRate?: number | string | null;
|
|
14
|
+
avgResponseTimeMs?: number | null;
|
|
15
|
+
lastActiveAt?: string | null;
|
|
16
|
+
tags?: string[];
|
|
17
|
+
stats?: {
|
|
18
|
+
completedJobs?: number;
|
|
19
|
+
avgRating?: number | null;
|
|
20
|
+
ratingCount?: number;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
};
|
|
23
|
+
payment?: {
|
|
24
|
+
pricing?: Record<string, unknown>;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
};
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
|
|
6
|
+
// ── Tools ────────────────────────────────────────────────────────
|
|
7
|
+
import { registerSearchTools } from "./tools/search.js";
|
|
8
|
+
import { registerRunTools } from "./tools/run.js";
|
|
9
|
+
import { registerSolveTools } from "./tools/solve.js";
|
|
10
|
+
import { registerAgentInfoTools } from "./tools/agent-info.js";
|
|
11
|
+
import { registerJobTools } from "./tools/jobs.js";
|
|
12
|
+
import { registerRateTools } from "./tools/rate.js";
|
|
13
|
+
import { registerWalletTools } from "./tools/wallet.js";
|
|
14
|
+
import { registerFavoriteTools } from "./tools/favorites.js";
|
|
15
|
+
import { registerTipTools } from "./tools/tip.js";
|
|
16
|
+
|
|
17
|
+
// ── Resources ────────────────────────────────────────────────────
|
|
18
|
+
import { registerAgentResources } from "./resources/agents.js";
|
|
19
|
+
import { registerWalletResources } from "./resources/wallet.js";
|
|
20
|
+
import { registerJobResources } from "./resources/jobs.js";
|
|
21
|
+
|
|
22
|
+
// ── Prompts ──────────────────────────────────────────────────────
|
|
23
|
+
import { registerPrompts } from "./prompts/index.js";
|
|
24
|
+
|
|
25
|
+
export async function startMcpServer(): Promise<void> {
|
|
26
|
+
const server = new McpServer({
|
|
27
|
+
name: "agentwonderland",
|
|
28
|
+
version: "0.2.0",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Register tools
|
|
32
|
+
registerSearchTools(server);
|
|
33
|
+
registerRunTools(server);
|
|
34
|
+
registerSolveTools(server);
|
|
35
|
+
registerAgentInfoTools(server);
|
|
36
|
+
registerJobTools(server);
|
|
37
|
+
registerRateTools(server);
|
|
38
|
+
registerWalletTools(server);
|
|
39
|
+
registerFavoriteTools(server);
|
|
40
|
+
registerTipTools(server);
|
|
41
|
+
|
|
42
|
+
// Register resources
|
|
43
|
+
registerAgentResources(server);
|
|
44
|
+
registerWalletResources(server);
|
|
45
|
+
registerJobResources(server);
|
|
46
|
+
|
|
47
|
+
// Register prompts
|
|
48
|
+
registerPrompts(server);
|
|
49
|
+
|
|
50
|
+
const transport = new StdioServerTransport();
|
|
51
|
+
await server.connect(transport);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ── Direct execution ─────────────────────────────────────────────
|
|
55
|
+
// When run as a binary (agentwonderland-mcp), start the server immediately.
|
|
56
|
+
const isCli =
|
|
57
|
+
process.argv[1]?.endsWith("agentwonderland-mcp") ||
|
|
58
|
+
process.argv[1]?.includes("packages/mcp");
|
|
59
|
+
|
|
60
|
+
if (isCli) {
|
|
61
|
+
startMcpServer().catch((err) => {
|
|
62
|
+
console.error("MCP server error:", err);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
export function registerPrompts(server: McpServer) {
|
|
5
|
+
server.prompt(
|
|
6
|
+
"get-started",
|
|
7
|
+
"Get started with Agent Wonderland — check wallet, discover agents, learn the tools",
|
|
8
|
+
{},
|
|
9
|
+
async () => ({
|
|
10
|
+
messages: [{
|
|
11
|
+
role: "user" as const,
|
|
12
|
+
content: {
|
|
13
|
+
type: "text" as const,
|
|
14
|
+
text: [
|
|
15
|
+
"Help me get started with Agent Wonderland.",
|
|
16
|
+
"",
|
|
17
|
+
"Please:",
|
|
18
|
+
"1. Check my wallet status with wallet_status",
|
|
19
|
+
"2. If no wallet is configured, help me create one with wallet_setup",
|
|
20
|
+
"3. Show me some popular agents with search_agents",
|
|
21
|
+
"4. Briefly explain how solve, run_agent, rating, and tipping work",
|
|
22
|
+
].join("\n"),
|
|
23
|
+
},
|
|
24
|
+
}],
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
server.prompt(
|
|
29
|
+
"wallet-setup",
|
|
30
|
+
"Create and fund a wallet for paying agents",
|
|
31
|
+
{},
|
|
32
|
+
async () => ({
|
|
33
|
+
messages: [{
|
|
34
|
+
role: "user" as const,
|
|
35
|
+
content: {
|
|
36
|
+
type: "text" as const,
|
|
37
|
+
text: [
|
|
38
|
+
"Help me set up a payment wallet for Agent Wonderland.",
|
|
39
|
+
"",
|
|
40
|
+
"Please:",
|
|
41
|
+
"1. Check if I already have a wallet with wallet_status",
|
|
42
|
+
"2. If not, create one with wallet_setup",
|
|
43
|
+
"3. Show me the address I need to fund",
|
|
44
|
+
"4. Explain what USDC I need and on which network (Tempo, Base, or Solana)",
|
|
45
|
+
].join("\n"),
|
|
46
|
+
},
|
|
47
|
+
}],
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
server.prompt(
|
|
52
|
+
"find-agent",
|
|
53
|
+
"Find the best agent for a task",
|
|
54
|
+
{ task: z.string().describe("What you need done") },
|
|
55
|
+
async ({ task }) => ({
|
|
56
|
+
messages: [{
|
|
57
|
+
role: "user" as const,
|
|
58
|
+
content: {
|
|
59
|
+
type: "text" as const,
|
|
60
|
+
text: [
|
|
61
|
+
`Find the best agent on Agent Wonderland for this task: "${task}"`,
|
|
62
|
+
"",
|
|
63
|
+
"Steps:",
|
|
64
|
+
"1. Use search_agents to find relevant agents",
|
|
65
|
+
"2. Use compare_agents on the top 2-3 candidates",
|
|
66
|
+
"3. Recommend the best one based on price, rating, and success rate",
|
|
67
|
+
"4. Ask if I want to run it",
|
|
68
|
+
].join("\n"),
|
|
69
|
+
},
|
|
70
|
+
}],
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
server.prompt(
|
|
75
|
+
"budget-run",
|
|
76
|
+
"Complete a task within a budget",
|
|
77
|
+
{
|
|
78
|
+
task: z.string().describe("What you need done"),
|
|
79
|
+
budget: z.string().optional().describe("Max spend in USD (default: $1)"),
|
|
80
|
+
},
|
|
81
|
+
async ({ task, budget }) => ({
|
|
82
|
+
messages: [{
|
|
83
|
+
role: "user" as const,
|
|
84
|
+
content: {
|
|
85
|
+
type: "text" as const,
|
|
86
|
+
text: [
|
|
87
|
+
`Complete this task on Agent Wonderland within $${budget || "1.00"}: "${task}"`,
|
|
88
|
+
"",
|
|
89
|
+
"Use the solve tool with the budget parameter. Show me what agent was selected and why.",
|
|
90
|
+
].join("\n"),
|
|
91
|
+
},
|
|
92
|
+
}],
|
|
93
|
+
}),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
server.prompt(
|
|
97
|
+
"run-with-review",
|
|
98
|
+
"Run an agent and review the output",
|
|
99
|
+
{
|
|
100
|
+
agent_id: z.string().describe("Agent ID to run"),
|
|
101
|
+
input: z.string().describe("JSON input for the agent"),
|
|
102
|
+
},
|
|
103
|
+
async ({ agent_id, input }) => ({
|
|
104
|
+
messages: [{
|
|
105
|
+
role: "user" as const,
|
|
106
|
+
content: {
|
|
107
|
+
type: "text" as const,
|
|
108
|
+
text: [
|
|
109
|
+
`Run agent ${agent_id} with this input: ${input}`,
|
|
110
|
+
"",
|
|
111
|
+
"After getting the result:",
|
|
112
|
+
"1. Summarize the output",
|
|
113
|
+
"2. Assess the quality",
|
|
114
|
+
"3. Ask if I want to rate the agent",
|
|
115
|
+
].join("\n"),
|
|
116
|
+
},
|
|
117
|
+
}],
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
}
|