diff --git a/.agent/context/20260913T-oneshot-payment-skill-autodiscovery.md b/.agent/context/20260913T-oneshot-payment-skill-autodiscovery.md new file mode 100644 index 0000000..f5eece8 --- /dev/null +++ b/.agent/context/20260913T-oneshot-payment-skill-autodiscovery.md @@ -0,0 +1,37 @@ +# OneShot payment skill: endpoint and payer discovery + +## Goal + +Make the downloadable `oneshot-arc-payment` skill use the canonical OneShot +MCP endpoint by default and explain how to resolve the active user wallet +without confusing a workspace bearer with a payer address. + +## Acceptance criteria + +- The skill identifies `https://oneshot.kapustazh.dev/mcp` as the canonical + default endpoint. +- The skill never asks for or exposes the bearer in a task prompt. +- The skill reads an active wallet/account connector when the host provides one. +- Without wallet context, the skill requests only the public payer address and + never guesses from a recipient, server wallet, or historical payment. +- Public docs and the in-app MCP guide match the skill behavior. + +## Assumptions and non-goals + +- The current `arc_payment` MCP schema intentionally keeps `payer_wallet` + required because OneShot must bind the intent before the user signs. +- Skill instructions cannot create a wallet connector or register an MCP server + in an arbitrary agent host; host configuration remains required once. +- This change does not enable the retained corporate server-wallet mode and does + not alter payment or settlement code. + +## Branch + +`fix/oneshot-payment-skill-autodiscovery`, based on `origin/develop` at the +current checkout. + +## Validation + +- `pnpm exec prettier --check apps/web/src/components/McpDocsPage.tsx` +- `git diff --check` +- `pnpm --filter @oneshot/web build` diff --git a/.agents/skills/oneshot-arc-payment/SKILL.md b/.agents/skills/oneshot-arc-payment/SKILL.md index 435356c..2ec3b2b 100644 --- a/.agents/skills/oneshot-arc-payment/SKILL.md +++ b/.agents/skills/oneshot-arc-payment/SKILL.md @@ -10,20 +10,37 @@ description: > # OneShot arc_payment MCP skill -Pay once, safely, through OneShot. This skill is written for any agent -(primary or delegated) whose MCP client is already connected to the OneShot -MCP endpoint. It never handles keys: the payer is the user's connected Privy -embedded/external wallet or MetaMask wallet, and the bearer token lives only in -the MCP client config. - -## Prerequisites (user-provided, never invented) - -- MCP endpoint URL, e.g. `https://oneshot.kapustazh.dev/mcp` (Streamable HTTP). -- A bearer generated from the user's OneShot Profile — configured in the MCP client as - `authorization: Bearer `. It is a secret: never print, log, copy into - task prompts, or commit it. - -If either is missing, stop and ask the operator. Do not guess values. +Pay once, safely, through OneShot. The canonical Streamable HTTP MCP endpoint +is `https://oneshot.kapustazh.dev/mcp`; use it by default unless the user +explicitly supplies an authorized alternative. The bearer is configured in the +MCP client's secret headers and is never handled by this skill. + +The payment is non-custodial: the payer is the user's connected Privy +embedded/external wallet or MetaMask wallet. OneShot prepares the exact +transaction and verifies the returned hash; it never signs or broadcasts a +user-wallet payment. + +## Connection and wallet prerequisites + +- Configure the MCP client with the canonical endpoint above and the bearer + generated from the user's OneShot Profile: + `authorization: Bearer `. The bearer is a secret: never print, log, + copy into task prompts, or commit it. +- Installing this skill does not register an MCP server or create a bearer. + If the current agent host has no OneShot MCP connection, tell the operator to + add the canonical endpoint using the configuration in `docs/MCP_ARC_PAYMENT.md` + or `/docs/mcp`. Never ask the operator to paste the bearer into the task + prompt. +- Before calling `arc_payment`, resolve the active payer address. If the agent + host exposes a connected wallet/account tool, query it and use the active + Ethereum wallet selected by the user. If the host has no wallet context, ask + the user to connect/select the wallet or provide its public EVM address once. + A payer address cannot be derived safely from the bearer, recipient, server + wallet, or an unrelated historical payment; never guess one. + +The current OneShot `arc_payment` schema requires `payer_wallet` because the +intent and exact transaction are bound to the user's selected wallet before +signing. The address is public, but the bearer is not. ## Tool contract: `arc_payment` then `arc_payment_submit` @@ -52,8 +69,9 @@ checks the receipt and exact USDC `Transfer` log, and returns the durable state. ## How to execute a payment -1. Generate the `request_key`, then call `arc_payment` once with that key, the - exact payer wallet, recipient, amount, and purpose the user approved. +1. Resolve the active wallet address as described above. Generate the + `request_key`, then call `arc_payment` once with that key, the exact payer + wallet, recipient, amount, and purpose the user approved. 2. Give the user the returned `signing_url`. The user must be signed into the matching OneShot workspace, review the recipient and amount, and click the wallet confirmation. Do not create a replacement transaction. @@ -73,9 +91,10 @@ checks the receipt and exact USDC `Transfer` log, and returns the durable state. ## Delegating (outsourcing) the payment to another agent -- Hand the delegate only the task arguments: endpoint URL, `payer_wallet`, - `recipient`, `amount_usdc`, `purpose`, and this skill. The delegate generates - and retains the request key. +- Hand the delegate only the task arguments: the canonical endpoint (unless it + is already configured), the resolved `payer_wallet` when the delegate has no + wallet connector, `recipient`, `amount_usdc`, `purpose`, and this skill. The + delegate generates and retains the request key. - The delegate must use its own MCP client configuration; the bearer token must not travel through prompts, task payloads, logs, or screenshots. - One request key funds exactly one intent. Each delegate generates one key per diff --git a/apps/web/src/components/McpDocsPage.tsx b/apps/web/src/components/McpDocsPage.tsx index 550de84..8c6521d 100644 --- a/apps/web/src/components/McpDocsPage.tsx +++ b/apps/web/src/components/McpDocsPage.tsx @@ -100,7 +100,10 @@ export function McpDocsPage(props: { readonly theme: Theme; readonly onToggleThe Connect, then confirm that the tool list contains arc_payment and arc_payment_submit.
  • Review the recipient, purpose, and amount before giving them to the agent.
  • -
  • Pass the connected Privy or MetaMask wallet address as payer_wallet.
  • +
  • + The agent reads the active Privy or MetaMask address from its wallet connector when one + is available; otherwise provide the public address as payer_wallet once. +
  • The agent generates a request key from the purpose plus eight random hex characters; you do not need to provide or copy it. diff --git a/docs/MCP_ARC_PAYMENT.md b/docs/MCP_ARC_PAYMENT.md index 233a90a..f13a0d2 100644 --- a/docs/MCP_ARC_PAYMENT.md +++ b/docs/MCP_ARC_PAYMENT.md @@ -53,6 +53,10 @@ Point a Streamable HTTP MCP client at: https://oneshot.kapustazh.dev/mcp ``` +This is the canonical OneShot MCP endpoint and is the default for the payment +skill; installing the skill alone does not register this server in an agent +host. Use the ready-made configuration from Profile or the JSON below. + Send the bearer as `Authorization: Bearer `: ```json @@ -73,7 +77,11 @@ Send the bearer as `Authorization: Bearer `: ## Prepare and submit -Prepare a payment with the wallet address selected by the user: +Prepare a payment with the wallet address selected by the user. If the agent +host has a wallet/account connector, it should read the active Ethereum wallet +from that connector. Otherwise the user provides only the public wallet address +once; the bearer token does not identify a wallet and must not be pasted into a +prompt. ```json {