@paybox-sh/sdk 0.8.5 → 1.0.0

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/README.md CHANGED
@@ -4,10 +4,9 @@ Typed Node SDK and `paybox` CLI for the PayBox agent API. It mirrors the MCP too
4
4
  surface — `list_credentials`, `request_payment`, `claim_payment_credentials`,
5
5
  `request_wallet_sign`, `request_secret`, `request_swap`, `discover_services`,
6
6
  `pay_x402`, `use_service`, `get_portfolio`, `get_buy_link`,
7
- `request_account_change`, `get_request`, and read-only plugin tools (`world_*`,
8
- `hyperliquid_*`) — but talks to the REST API directly, with no MCP host and no
9
- signing iframe.
10
- Geofenced World money tools are MCP-only.
7
+ `request_account_change`, `get_request`, and the generic plugin discovery,
8
+ contract, and invocation flow. Core operations use the REST API; plugins use
9
+ the same MCP tools as connector hosts, with no hardcoded per-plugin paths.
11
10
 
12
11
  Wallet signing is **non-custodial and runs in-process**: the SDK reuses the exact
13
12
  signing core from the wallet-sign iframe (`@paybox/mcp-app`), builds the chain
@@ -24,7 +23,7 @@ npx @paybox-sh/sdk login # or use the CLI directly
24
23
  Driving this CLI from an agent? [`SKILL.md`](SKILL.md) ships in the package and
25
24
  describes the install and login flow as an agent skill: what the human has to do
26
25
  (approve wallets, paste one signing key), and what the agent should not do
27
- around it. Use the CLI on **Grok Bot**, **Grok Computer**, and any agent on a
26
+ around it. Use the CLI on **Muse**, **Grok Bot**, **Grok Computer**, and any agent on a
28
27
  computer with no connector screen — not the grok.com MCP connector path.
29
28
 
30
29
  ## CLI
@@ -60,8 +59,9 @@ paybox account-change --note "need a wallet grant" # manage_url for the user to
60
59
  paybox request <request_id> --wait # poll a pending request
61
60
 
62
61
  # Plugins (enable them in the paybox app first)
63
- paybox world markets --status active # browse prediction markets
64
- paybox hyperliquid markets # spot discovery
62
+ paybox plugins list --status enabled
63
+ paybox plugins contract paybox://plugins/world
64
+ paybox plugins use world world_get_events --input '{"status":"active"}'
65
65
 
66
66
  paybox version # installed version (+ update check)
67
67
  paybox update # update the global install to latest
@@ -77,7 +77,7 @@ its own binary). For project installs use `pnpm up`/`pnpm rm`, or `npx
77
77
  @paybox-sh/sdk@latest` to always run the latest without installing.
78
78
 
79
79
  `sign`, `swap`, `pay-x402`, and `use-service` can complete in-process with a
80
- configured `pbxk1.` key. World buy/sell/redeem are MCP-only.
80
+ configured `pbxk1.` key. Plugin calls return the raw MCP tool result.
81
81
 
82
82
  For a Solana `swap` the SDK re-pins a fresh recent blockhash immediately before
83
83
  signing (parity with the signing window — the quote-time blockhash expires
@@ -85,7 +85,7 @@ within ~60–90s, often before signing), so a swap that dwells for approval no
85
85
  longer broadcasts as `BlockhashNotFound`. EVM swaps are unaffected.
86
86
 
87
87
  `pay-x402` is header mode — on success `output.value.x_payment` is the `X-PAYMENT`
88
- header to replay on the original request. `use-service` is gateway mode — paybox
88
+ header to replay on the original request. `use-service` is gateway mode — PayBox
89
89
  makes the paid call for you and returns the resource's reply on
90
90
  `output.value.response`. Pass `--accepts` from the resource's own 402 (start from
91
91
  the curated Bazaar set with `paybox discover`).
@@ -122,6 +122,15 @@ const services = await paybox.discoverServices("weather api");
122
122
  const rawServices = await paybox.discoverServices("weather api", { raw: true }); // debug only
123
123
  const paid = await paybox.useService({ credentialId: walletId, url: services[0].resource });
124
124
  // paid.response.output.value.response holds the resource's reply
125
+
126
+ const plugins = await paybox.discoverPlugins({ status: "enabled" });
127
+ const selected = plugins.plugins.find((plugin) => plugin.id === "aave");
128
+ const contract = await paybox.getPluginContract(selected!.contract_uri!);
129
+ const result = await paybox.usePlugin({
130
+ pluginId: contract.contract.id,
131
+ toolId: contract.contract.tools[0].id,
132
+ input: {},
133
+ });
125
134
  ```
126
135
 
127
136
  ## Configuration
package/SKILL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: PayBox CLI setup
3
- version: 0.8.8
3
+ version: 0.8.13
4
4
  description: >-
5
5
  Install and log in to the PayBox CLI (@paybox-sh/sdk) so an agent can pay,
6
6
  sign, and hold wallet, card, and secret credentials on the user's behalf. Use
@@ -12,11 +12,11 @@ description: >-
12
12
 
13
13
  The human and agent guide is `https://docs.paybox.sh` (start at
14
14
  getting-started and connect/mcp). This file is only the CLI film. Grok
15
- (grok.com) and Grok Bots are different hosts; do not treat one as the other.
15
+ (grok.com), Grok Bots, and Muse are different hosts; do not treat one as another.
16
16
 
17
17
  ## Which host
18
18
 
19
- - **Grok Bot, Grok Computer, or any agent on a computer or VM with no connector
19
+ - **Muse, Grok Bot, Grok Computer, or any agent on a computer or VM with no connector
20
20
  screen:** this skill is the path. Install and run `paybox login` on that
21
21
  machine. Do not send the user to grok.com/connectors and do not paste the MCP
22
22
  URL as setup.
@@ -24,13 +24,65 @@ getting-started and connect/mcp). This file is only the CLI film. Grok
24
24
  grok.com/connectors. Do not run this CLI install flow unless they explicitly
25
25
  want the CLI on a separate machine.
26
26
 
27
- When the user says "install PayBox" and you are Grok Bot or running on a
27
+ When the user says "install PayBox" and you are Muse, Grok Bot, or running on a
28
28
  computer, start here immediately.
29
29
 
30
30
  The user asks to install PayBox. Two things need them: they approve wallet
31
31
  access with a passkey, and they paste one signing key. Everything else is yours,
32
32
  and they should not see it happen.
33
33
 
34
+ ## Muse
35
+
36
+ On Muse this section wins over Grok Bot phone-app and masked-field rules below.
37
+ Prod is `https://api.paybox.sh` / `https://app.paybox.sh`. Stay quiet until they
38
+ say install PayBox / install paybox / Install Paybox. English. Few words. No
39
+ secret dumps. No invented click paths.
40
+
41
+ Do not send them to Settings → Connectors → Add custom, or to paste an MCP URL.
42
+ Muse **Manage Connectors** (OpenAI, Anthropic, and the rest) is not where
43
+ PayBox is added. Do not run passkey inside Muse. Muse is a chat host, not a
44
+ Grok Bot computer VM. Do not ask for done, listo, or a screenshot. Do not
45
+ fake ready.
46
+ Never wipe `~/.config/paybox`.
47
+
48
+ Two chat controls, then Welcome. Muse does **not** open those links the way
49
+ Grok Bot does. Every link you send must tell them to tap it. A bare
50
+ markdown pill with no "tap this" line is a failed take.
51
+
52
+ 1. Run device-code login (`paybox login`, or the PayBox capability Authorize
53
+ flow if this host already has it). The moment you have
54
+ `verification_uri_complete` and `user_code`, send **one** message:
55
+ **Tap [Authorize wallets](verification_uri_complete) on your phone
56
+ browser.** plus `Code: XXXX-XXXX`. One short extra line only if the
57
+ PayBox **Capability** screen shows **Authorize**: "Or tap Authorize on
58
+ Paybox under Capabilities." Never mention Add custom. Phone browser
59
+ (Safari or Chrome), not the native PayBox app and not inside Muse.
60
+ You do not open the URL. Poll until OAuth is live. Do not end the
61
+ turn while polling.
62
+ 2. When OAuth is live and the signing key is missing, send **Tap
63
+ [Provision agent key](https://app.paybox.sh/agent-key?client_id=<cid>)
64
+ on your phone browser.** Then this exact line: **Muse does not have a
65
+ secure field for the signing key yet; the team is working on it. For
66
+ now paste the pbxk1 here and rotate it after.** `cid` is the
67
+ access-token UUID, never `oauth.clientId`. Muse has no masked field.
68
+ Write `signingKey` into an isolated config. Never `login --signing-key`
69
+ on argv. Never echo the key.
70
+
71
+ Ready only when OAuth or an API key is live **and** `canSign` is true. Then
72
+ Welcome to PayBox with two buttons: **Swap 20 USDC to SOL**, **Pay a Solana
73
+ briefing**. Do the one they tap. Stop when that job is done.
74
+
75
+ If token exchange fails (`refresh_rejected` / egress): one stop line, "Host
76
+ blocks PayBox token exchange. Install NOT complete." Do not offer Settings →
77
+ Add custom as a workaround. If a PayBox capability with **Authorize** is
78
+ visible, point only there. If MCP is already Connected under Manage your MCP
79
+ servers, use that grant — still no Add custom story.
80
+
81
+ Install the CLI only when this host still needs device-code:
82
+ `npm install -g @paybox-sh/sdk@latest`, then `paybox --json version` (0.8.5+).
83
+ Fresh `PAYBOX_CONFIG_DIR`. Unset `PAYBOX_API_URL` `PAYBOX_API_KEY`
84
+ `PAYBOX_SIGNING_KEY` `PAYBOX_ACCESS_TOKEN`.
85
+
34
86
  ## Install
35
87
 
36
88
  ```bash
@@ -90,9 +142,10 @@ Send that link even though the CLI also tries to open a browser. When the CLI
90
142
  is not on the user's machine, that local open is useless or invisible, and your
91
143
  message is the only way they reach the page.
92
144
 
93
- On a phone, Authorize wallets should open the PayBox app. That is the
94
- correct path. After they tap Connect CLI, the app opens Generate a signing
95
- key by itself. Do not tell them to come back to chat first.
145
+ On Grok Bot, Authorize wallets should open the PayBox app. That is the
146
+ correct path there. After they tap Connect CLI, the app opens Generate a
147
+ signing key by itself. Do not tell them to come back to chat first. On Muse
148
+ use the Muse section: phone browser, not the native app, not inside Muse.
96
149
 
97
150
  Then wait. The poll is the continue signal. Do not ask the user to type `done`,
98
151
  confirm, or send a screenshot, and do not end your turn while login is running.
@@ -120,9 +173,12 @@ showing the box does not need that machine.
120
173
  The moment **this** login has an agent-key URL (stderr, or `cid` from the oauth
121
174
  it just saved), put **Generate Signing Key** in chat as that link plus a
122
175
  **masked input** for the `pbxk1.` value, in the same turn. Seconds after they
123
- finish Authorize wallets, not minutes. That chat link must use the JWT `cid`
124
- and must open the PayBox app on the first tap, the same way Authorize wallets
125
- does. Do not `Start-Process`, `open`, `rundll32`, or `xdg-open` the authorize,
176
+ finish Authorize wallets, not minutes. That chat link must use the JWT `cid`.
177
+ On Grok Bot it must open the PayBox app on the first tap, the same way
178
+ Authorize wallets does. On Muse tell them to tap the link, then say Muse does
179
+ not have a secure field for the signing key yet; the team is working
180
+ on it. For now paste the pbxk1 here and rotate it after. There is no
181
+ masked field. The link opens in the phone browser. Do not `Start-Process`, `open`, `rundll32`, or `xdg-open` the authorize,
126
182
  connect, or agent-key URL yourself. Write what they give you to login's
127
183
  prompt stdin when that prompt is alive. If login is wedged after this oauth
128
184
  write, keep the box on screen and merge `signingKey` when the host can write
@@ -153,9 +209,15 @@ rather than continuing, because signing and swaps will fail without it.
153
209
  From the install request until `canSign` is `true`, exactly two messages, in
154
210
  this order:
155
211
 
156
- 1. The **Authorize wallets** link plus the code.
157
- 2. **Generate Signing Key** plus the masked `pbxk1.` field, as soon as
212
+ 1. The **Authorize wallets** link plus the code. On Muse, the line says
213
+ to tap that link on the phone browser. Grok Bot can omit that; it
214
+ opens the link itself.
215
+ 2. **Generate Signing Key** plus the signing-key control, as soon as
158
216
  **this** login prints `/agent-key?client_id=` or writes a new `oauth`.
217
+ Grok Bot: masked `pbxk1.` field. Muse: tell them to tap Provision
218
+ agent key on the phone browser, then: Muse does not have a secure
219
+ field for the signing key yet; the team is working on it. For now
220
+ paste the pbxk1 here and rotate it after.
159
221
 
160
222
  Nothing else. No "Installing…", "Opening…", "Got it", no CLI version, package
161
223
  manager, config path, or request id, and no narration of a retry or fallback. If
@@ -232,24 +294,30 @@ catalog index. There may be tens or thousands.
232
294
  app, not a host Settings → Plugins screen. Ask them to turn on what
233
295
  they want to use, then say when they are back.
234
296
 
235
- 2. Then call `discover_plugins` with `status` `enabled`, no `query`, and
236
- a small `limit`. That page is what they have on, not the store. From
297
+ 2. Then run `paybox --json plugins list --status enabled --limit 10`. That page
298
+ is what they have on, not the store. From
237
299
  those plugins plus the portfolio, suggest a few concrete next moves
238
300
  (about six, not one row per plugin). Use each result's `name` and
239
301
  contract. Be specific: amounts, which wallet UUID, which market or
240
302
  vault from the contract. Mix two enabled plugins in one suggestion
241
303
  when that serves the same goal (for example fund or swap, then put
242
- the result to work). If nothing is enabled, skip the suggestion list
243
- and stay on the Plugins link.
244
-
245
- When they name a plugin or a job, search: `discover_plugins` with `query`
246
- set to what they asked, `status` `enabled` if they already turned it on,
247
- then page with `next_cursor` only while the current page has no match.
248
- Official plugin money uses MCP: `get_contract` with `contract_uri`
249
- unchanged → `use_plugin` with that contract's `plugin_id`, `tool_id`,
250
- and `input`. Do not invent a `paybox <plugin>` command; only use CLI
251
- groups that `paybox --help` already lists. Enabled plugin tools may also
252
- appear on `tools/list`. Plugin money always pauses for passkey.
304
+ the result to work). On Muse, Welcome is those two buttons first:
305
+ **Swap 20 USDC to SOL** on the granted Solana wallet, then **Pay a
306
+ Solana briefing**. Do not offer 0.001 SOL to USDC. If nothing is
307
+ enabled, skip the extra plugin list and stay on the Plugins link.
308
+
309
+ When they name a plugin or a job, search with `paybox --json plugins list
310
+ <query> --status enabled`, then page with `--cursor <next_cursor>` only while
311
+ the current page has no match. For an official plugin, run `paybox --json
312
+ plugins contract <contract_uri>` with the URI unchanged, then `paybox --json
313
+ plugins use <plugin_id> <tool_id> --input <json>` with input matching that
314
+ contract. Unofficial discovery results already contain their tool schemas;
315
+ reuse `--invocation-id` only to retrieve the exact same ambiguous call. Plugin
316
+ money always pauses for passkey.
317
+
318
+ There are no per-plugin commands. `paybox world …` and `paybox hyperliquid …`
319
+ were removed in 1.0.0; reach World and Hyperliquid through `paybox plugins`
320
+ like every other plugin.
253
321
 
254
322
  If prod MCP (`https://api.paybox.sh/mcp`) is `unreachable` or `needsAuth` while
255
323
  `paybox --json whoami` still works, say that. Do not send the human to Settings.
@@ -272,3 +340,9 @@ Do not switch to staging. Do not report the dollar as sent.
272
340
  got its own window).
273
341
  - Setup chat contained anything besides those two messages.
274
342
  - A token, API key, or `pbxk1.` value reached the transcript.
343
+ - On Muse you sent Settings → Connectors → Add custom, or Manage Connectors.
344
+ - On Muse you opened passkey inside Muse.
345
+ - On Muse Authorize wallets opened in the PayBox app or inside Muse.
346
+ - On Muse you sent a link without telling them to tap it.
347
+ - On Muse you faked ready before `canSign` was true.
348
+ - On Muse token exchange failed and you invented an MCP Add custom path.
@@ -133,7 +133,7 @@ async function loginDevice(baseUrl, opts = {}) {
133
133
  const meta = await metadata(baseUrl);
134
134
  if (!meta.device_authorization_endpoint) {
135
135
  throw new Error(
136
- "this Paybox API does not advertise device_authorization_endpoint \u2014 upgrade the API and retry `paybox login`"
136
+ "this PayBox API does not advertise device_authorization_endpoint \u2014 upgrade the API and retry `paybox login`"
137
137
  );
138
138
  }
139
139
  const resource = mcpResource(baseUrl);
@@ -301,18 +301,52 @@ import { Buffer as Buffer2 } from "buffer";
301
301
  import nacl from "tweetnacl";
302
302
  import { MoonXEvmSigner, EvmSchemeMismatchError } from "@moon-x/evm-adapter";
303
303
  import { MoonXSolanaSigner, SolanaSchemeMismatchError } from "@moon-x/solana-adapter";
304
- import { Transaction } from "@solana/web3.js";
304
+ import { Transaction, VersionedTransaction } from "@solana/web3.js";
305
305
  import { hashTypedData, keccak256, serializeTransaction } from "viem";
306
+ function parseWireU128(value, field) {
307
+ if (value === void 0 || value === null) {
308
+ throw new Error(`transaction is missing ${field}`);
309
+ }
310
+ if (typeof value === "bigint") {
311
+ if (value < 0n) {
312
+ throw new Error(`transaction field ${field} must be a non-negative integer`);
313
+ }
314
+ return value;
315
+ }
316
+ if (typeof value === "number") {
317
+ if (!Number.isSafeInteger(value) || value < 0) {
318
+ throw new Error(`transaction field ${field} must be a non-negative integer`);
319
+ }
320
+ return BigInt(value);
321
+ }
322
+ if (typeof value === "string") {
323
+ const trimmed = value.trim();
324
+ if (!trimmed) {
325
+ throw new Error(`transaction field ${field} is empty`);
326
+ }
327
+ if (/^0[xX][0-9a-fA-F]+$/.test(trimmed)) {
328
+ return BigInt(trimmed);
329
+ }
330
+ if (!/^\d+$/.test(trimmed)) {
331
+ throw new Error(`transaction field ${field} is not a valid integer`);
332
+ }
333
+ return BigInt(trimmed);
334
+ }
335
+ throw new Error(`transaction field ${field} has an invalid type`);
336
+ }
306
337
  function reviveTx(w) {
338
+ if (typeof w !== "object" || w === null || Array.isArray(w)) {
339
+ throw new Error("transaction must be an object, not a JSON-encoded string");
340
+ }
307
341
  return {
308
342
  type: "eip1559",
309
343
  to: w.to,
310
- value: BigInt(w.value),
344
+ value: parseWireU128(w.value ?? "0", "value"),
311
345
  data: w.data,
312
346
  chainId: w.chainId,
313
- gas: BigInt(w.gas),
314
- maxPriorityFeePerGas: BigInt(w.maxPriorityFeePerGas),
315
- maxFeePerGas: BigInt(w.maxFeePerGas),
347
+ gas: parseWireU128(w.gas, "gas"),
348
+ maxPriorityFeePerGas: parseWireU128(w.maxPriorityFeePerGas, "maxPriorityFeePerGas"),
349
+ maxFeePerGas: parseWireU128(w.maxFeePerGas, "maxFeePerGas"),
316
350
  nonce: w.nonce
317
351
  };
318
352
  }
@@ -356,6 +390,14 @@ function solanaSigningPayload(base64Tx) {
356
390
  }
357
391
  return bytesToHex(new Uint8Array(raw.subarray(i + sigCount * 64)));
358
392
  }
393
+ function deserializeSolanaTx(base64Tx) {
394
+ const raw = Buffer2.from(base64Tx, "base64");
395
+ try {
396
+ return Transaction.from(raw);
397
+ } catch {
398
+ return VersionedTransaction.deserialize(new Uint8Array(raw));
399
+ }
400
+ }
359
401
  function buildSwapEnvelopes(txs, binding, creds) {
360
402
  if (!binding.walletId) {
361
403
  throw new Error("PayBox did not supply a wallet id for this operation.");
@@ -484,7 +526,7 @@ async function signIntent(intent, creds, binding, transport) {
484
526
  return { ok: true, artifact: { signature: bytesToHex(sig) } };
485
527
  }
486
528
  case "solanaTransaction": {
487
- const tx = Transaction.from(Buffer2.from(intent.transactionBase64, "base64"));
529
+ const tx = deserializeSolanaTx(intent.transactionBase64);
488
530
  const signed = await new MoonXSolanaSigner(ed25519Sign, intent.address).signTransaction(
489
531
  tx
490
532
  );
@@ -607,6 +649,100 @@ async function signX402Request(post, requestId, plan, creds) {
607
649
  await post(`/agent/requests/${requestId}/envelopes`, { envelopes: [envelope] });
608
650
  }
609
651
 
652
+ // src/mcp.ts
653
+ var PROTOCOL_VERSION = "2025-06-18";
654
+ function responseBody(text) {
655
+ const events = text.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim());
656
+ return events.length === 0 ? text : events.join("");
657
+ }
658
+ function errorText(result) {
659
+ return result.content.filter((item) => item.type === "text" && typeof item.text === "string").map((item) => item.text).join("\n");
660
+ }
661
+ function toolJson(tool, result) {
662
+ if (result.isError) {
663
+ throw new Error(errorText(result) || `paybox ${tool} failed`);
664
+ }
665
+ const text = result.content.find(
666
+ (item) => item.type === "text" && typeof item.text === "string"
667
+ )?.text;
668
+ if (typeof text !== "string") {
669
+ throw new Error(`paybox ${tool} returned no JSON content`);
670
+ }
671
+ return JSON.parse(text);
672
+ }
673
+ var McpTransport = class {
674
+ endpoint;
675
+ bearer;
676
+ fetchImpl;
677
+ nextId = 0;
678
+ initialization;
679
+ constructor(options) {
680
+ this.endpoint = `${options.baseUrl}/mcp`;
681
+ this.bearer = options.bearer;
682
+ this.fetchImpl = options.fetchImpl;
683
+ }
684
+ async callTool(name, args) {
685
+ await this.initialize();
686
+ return this.rpc("tools/call", { name, arguments: args });
687
+ }
688
+ async initialize() {
689
+ this.initialization ??= this.rpc("initialize", {
690
+ protocolVersion: PROTOCOL_VERSION,
691
+ capabilities: {},
692
+ clientInfo: { name: "paybox-sdk", version: "1" }
693
+ }).then(() => this.notify("notifications/initialized", {}));
694
+ try {
695
+ await this.initialization;
696
+ } catch (error) {
697
+ this.initialization = void 0;
698
+ throw error;
699
+ }
700
+ }
701
+ async post(payload, method) {
702
+ const response = await this.fetchImpl(this.endpoint, {
703
+ method: "POST",
704
+ headers: {
705
+ accept: "application/json, text/event-stream",
706
+ authorization: `Bearer ${await this.bearer()}`,
707
+ "content-type": "application/json",
708
+ "mcp-protocol-version": PROTOCOL_VERSION
709
+ },
710
+ body: JSON.stringify(payload)
711
+ });
712
+ const text = await response.text();
713
+ if (!response.ok) {
714
+ throw new Error(
715
+ `paybox MCP ${method} failed (${response.status}): ${text}`
716
+ );
717
+ }
718
+ return text;
719
+ }
720
+ async notify(method, params) {
721
+ await this.post({ jsonrpc: "2.0", method, params }, method);
722
+ }
723
+ async rpc(method, params) {
724
+ const text = await this.post(
725
+ {
726
+ jsonrpc: "2.0",
727
+ id: ++this.nextId,
728
+ method,
729
+ params
730
+ },
731
+ method
732
+ );
733
+ const parsed = JSON.parse(responseBody(text));
734
+ if (parsed.error) {
735
+ throw new Error(
736
+ `paybox MCP ${method} failed (${parsed.error.code}): ${parsed.error.message}`
737
+ );
738
+ }
739
+ if (parsed.result === void 0) {
740
+ throw new Error(`paybox MCP ${method} returned no result`);
741
+ }
742
+ return parsed.result;
743
+ }
744
+ };
745
+
610
746
  // src/client.ts
611
747
  var DEFAULT_BASE_URL = "https://api.paybox.sh";
612
748
  var EXPIRY_SKEW_MS = 6e4;
@@ -631,10 +767,16 @@ var PayboxClient = class _PayboxClient {
631
767
  fetchImpl;
632
768
  oauth;
633
769
  configBacked = false;
770
+ mcp;
634
771
  constructor(options = {}) {
635
772
  this.opts = options;
636
773
  this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
637
774
  this.fetchImpl = options.fetchImpl ?? fetch;
775
+ this.mcp = new McpTransport({
776
+ baseUrl: this.baseUrl,
777
+ bearer: () => this.bearer(),
778
+ fetchImpl: this.fetchImpl
779
+ });
638
780
  }
639
781
  static fromConfig(overrides = {}) {
640
782
  const cfg = loadConfig();
@@ -852,6 +994,32 @@ var PayboxClient = class _PayboxClient {
852
994
  }
853
995
  });
854
996
  }
997
+ async discoverPlugins(args = {}) {
998
+ return toolJson(
999
+ "discover_plugins",
1000
+ await this.mcp.callTool("discover_plugins", {
1001
+ query: args.query,
1002
+ source: args.source,
1003
+ status: args.status,
1004
+ limit: args.limit,
1005
+ cursor: args.cursor
1006
+ })
1007
+ );
1008
+ }
1009
+ async getPluginContract(contractUri) {
1010
+ return toolJson(
1011
+ "get_contract",
1012
+ await this.mcp.callTool("get_contract", { contract_uri: contractUri })
1013
+ );
1014
+ }
1015
+ usePlugin(args) {
1016
+ return this.mcp.callTool("use_plugin", {
1017
+ plugin_id: args.pluginId,
1018
+ tool_id: args.toolId,
1019
+ input: args.input,
1020
+ invocation_id: args.invocationId
1021
+ });
1022
+ }
855
1023
  async payX402(args, opts = {}) {
856
1024
  return this.withExpiryRetry(
857
1025
  async () => {
@@ -922,58 +1090,6 @@ var PayboxClient = class _PayboxClient {
922
1090
  }
923
1091
  });
924
1092
  }
925
- worldMarkets(args = {}) {
926
- return this.request("GET", "/agent/world/markets", {
927
- query: {
928
- events: args.events ? "true" : void 0,
929
- limit: args.limit?.toString(),
930
- cursor: args.cursor?.toString(),
931
- event_ticker: args.eventTicker,
932
- series_ticker: args.seriesTicker,
933
- status: args.status
934
- }
935
- });
936
- }
937
- worldMarket(eventTicker, withNestedMarkets = true) {
938
- return this.request("GET", "/agent/world/market", {
939
- query: {
940
- event_ticker: eventTicker,
941
- with_nested_markets: withNestedMarkets ? void 0 : "false"
942
- }
943
- });
944
- }
945
- worldOrderbook(id, byMint = false) {
946
- return this.request("GET", "/agent/world/orderbook", {
947
- query: { id, by_mint: byMint ? "true" : void 0 }
948
- });
949
- }
950
- worldPrices(args) {
951
- return this.request("GET", "/agent/world/prices", {
952
- query: {
953
- ticker: args.ticker,
954
- start_ts: args.startTs.toString(),
955
- end_ts: args.endTs.toString(),
956
- resolution: args.resolution?.toString()
957
- }
958
- });
959
- }
960
- worldFilterOutcomeMints(addresses) {
961
- return this.request("POST", "/agent/world/filter-outcome-mints", {
962
- body: { addresses }
963
- });
964
- }
965
- worldPositions(address) {
966
- return this.request("GET", "/agent/world/positions", { query: { address } });
967
- }
968
- hyperliquidMarkets() {
969
- return this.request("GET", "/agent/hyperliquid/markets");
970
- }
971
- hyperliquidPrices() {
972
- return this.request("GET", "/agent/hyperliquid/prices");
973
- }
974
- hyperliquidToken(name) {
975
- return this.request("GET", "/agent/hyperliquid/token", { query: { name } });
976
- }
977
1093
  getRequest(requestId) {
978
1094
  return this.request("GET", `/agent/requests/${requestId}`);
979
1095
  }
@@ -1010,4 +1126,4 @@ export {
1010
1126
  PayboxError,
1011
1127
  PayboxClient
1012
1128
  };
1013
- //# sourceMappingURL=chunk-WRPYONXW.js.map
1129
+ //# sourceMappingURL=chunk-SMPW2GUM.js.map