Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions .agent/context/20260913T040725Z-mcp-access-and-scope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Session Context: MCP access and request scope

## Date/time

- UTC: 2026-09-13T04:07:25Z

## User goal

Remove the unused MCP-specific 1 USDC cap, make the downloadable agent skill installable with npx, connect the merged MCP path to Google Cloud, and verify that users see only their own requests.

## Original prompt/request

The user asked to remove the MCP 1 USDC boundary, provide the bearer required by agent configuration, add the missing npx skill installation instructions, audit per-user request isolation, and make the MCP usable through the existing Google Cloud deployment.

## Assumptions

- “Remove the 1 USDC boundary” means delete the second MCP-only cap. The worker settlement cap and Privy policy remain authoritative security controls.
- A shared production bearer must stay in Google Secret Manager and must not be embedded in the public docs page.
- Browser request isolation applies to job lists, job reads/results, and activity. Direct intent/recovery routes need a later storage association before full cross-workspace isolation can be claimed.

## Plan

1. Remove the MCP-specific amount cap and its configuration/tests/docs.
2. Scope browser job and activity routes by the verified Privy subject.
3. Add and verify the exact npx skill install command.
4. Validate, commit/push, then build and deploy the API with Google Secret Manager-backed MCP configuration.
5. Verify public MCP authentication and tool discovery without submitting a payment.

## Key decisions

- Derive an opaque stable workspace ID as SHA-256 of the verified Privy subject; do not accept a caller-selected workspace.
- Issue one random 256-bit bearer per Privy workspace, store only its SHA-256 digest, and allow explicit rotation. Keep the optional operator bearer only for compatibility.
- Never render or commit the bearer token.

## Files/components touched

- API authentication and route workspace selection.
- MCP cap configuration and tests.
- MCP docs page, operator docs, downloadable skill, and implementation plan.
- PostgreSQL migration 011 and personal MCP credential store.
- Authenticated Profile token generation and rotation UI.
- Google Cloud deployment configuration (pending).

## Commands/checks

- `npx --yes skills@latest add https://github.com/SWOFART/OneShot/tree/develop --list --full-depth` - found `oneshot-arc-payment`.
- `pnpm build` - passed on local Node 22 with the repository Node 24 engine warning.
- `pnpm --filter @oneshot/api test` - 75/75 passed after personal token work.
- Focused web profile/docs tests - 10/10 passed.
- `pnpm test` - 79 files and 1052 tests passed.
- `pnpm test:browser` - 8/8 Chromium checks passed.
- Full web test exposed two pre-existing failures in `privy-session.test.tsx`; the changed MCP docs assertion was updated and passes.

## External-doc findings

- None. The installed `skills` CLI help verified the command syntax directly.

## Unresolved questions

- Google Secret Manager list/get remains unavailable to the active account; personal MCP bearer generation does not depend on a shared MCP secret.
- Direct `/v1/intents/:id`, reconcile, and recovery-view routes are not yet workspace-bound in storage; job request views are isolated.
- The active account cannot list/get Secret Manager metadata, but personal MCP tokens no longer require a shared MCP secret.

## Git and PR state

- Branch: fix/mcp-access-and-scope
- Base: origin/develop at 246a38af36e291b0538eb0a8f87d1f3b3f1def60
- Commit: 9aafe21d27e27a99ddb0586a0cff747bd36a38f2
- PR: <https://github.com/SWOFART/OneShot/pull/122> (draft)
- CI: all required checks passed for 9aafe21d27e27a99ddb0586a0cff747bd36a38f2

## Review gates

- Gate A: SKIPPED by explicit user instruction to continue without FreePi.
- Gate B: SKIPPED by explicit user instruction to continue without FreePi.

## Handoff/next steps

1. Finish local checks and inspect the candidate diff.
2. Commit, push, and open the PR without FreePi per user instruction.
3. Build/deploy the API image and configure `/mcp` through Google Cloud.
21 changes: 9 additions & 12 deletions .agents/skills/oneshot-arc-payment/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: oneshot-arc-payment
description: >
Pay a USDC recipient on Arc Testnet through the OneShot `arc_payment` MCP
tool: connect an MCP client with the operator-issued bearer token, create or
tool: connect an MCP client with the user's profile bearer token, create or
replay one durable payment intent, read the authoritative settlement state,
and verify the ArcScan proof. Use when the user asks to pay via OneShot, send
USDC on Arc, run the arc_payment MCP tool, or delegate an agent payment task.
Expand All @@ -15,15 +15,13 @@ Pay once, safely, through OneShot. This skill is written for any agent
MCP endpoint. It never handles keys: the payer is OneShot's policy-bound
server wallet, and the bearer token lives only in the MCP client config.

## Prerequisites (operator-provided, never invented)
## Prerequisites (user-provided, never invented)

- MCP endpoint URL, e.g. `https://oneshot.kapustazh.dev/mcp` (Streamable HTTP).
- `ONESHOT_MCP_BEARER_TOKEN` — configured in the MCP client as
- A bearer generated from the user's OneShot Profile — configured in the MCP client as
`authorization: Bearer <token>`. It is a secret: never print, log, copy into
task prompts, or commit it.
- One allowed `request_key` — the operator binds it to exactly one payment.
- The per-payment cap (default 1000000 atomic = 1 USDC) is enforced
server-side; requests above it are rejected.
- One allowed `request_key` shown with the generated profile credential.

If any of these is missing, stop and ask the operator. Do not guess values.

Expand All @@ -46,7 +44,7 @@ UNKNOWN | REJECTED`), `replayed`, `payer.mode` (`SERVER_PRIVY`),

## How to execute a payment

1. Call `arc_payment` once with the operator's `request_key` and the exact
1. Call `arc_payment` once with the profile's `request_key` and the exact
recipient, amount, and purpose the user approved.
2. If `state` is `COMMITTED`, report `settlement.transaction_hash` and its
`explorer_url` (ArcScan). Done.
Expand All @@ -57,7 +55,7 @@ UNKNOWN | REJECTED`), `replayed`, `payer.mode` (`SERVER_PRIVY`),
not failure: it never justifies a replacement payment or a new key.
5. If the tool returns the conflict error ("already belongs to a different
payment"), the key was reused with changed fields. Stop, report the
conflict, and ask the operator for the original fields or a new key.
conflict, and ask the user for the original fields or a new credential.
6. If `state` is `FAILED_SAFE` or `REJECTED`, report it and stop. Do not retry
with a different key or amount.

Expand All @@ -67,7 +65,7 @@ UNKNOWN | REJECTED`), `replayed`, `payer.mode` (`SERVER_PRIVY`),
`recipient`, `amount_usdc`, `purpose`, and this skill.
- 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. To parallelize, ask the operator
- One request_key funds exactly one intent. To parallelize, ask the user
for one key per payment; never derive or mutate keys.
- The delegate reports back the authoritative `state` plus the ArcScan proof
for `COMMITTED`, or the exact tool error. "It probably went through" is not
Expand All @@ -77,6 +75,5 @@ UNKNOWN | REJECTED`), `replayed`, `payer.mode` (`SERVER_PRIVY`),

- Walkthrough: `docs/MCP_ARC_PAYMENT.md` in the OneShot repository.
- Human-readable page: `https://oneshot.kapustazh.dev/docs/mcp`.
- Install: copy this folder into the agent's skills directory, or add the
GitHub source `SWOFART/OneShot` with skill path
`.agents/skills/oneshot-arc-payment/SKILL.md`.
- Install (requires Node.js/npm; `npx` ships with npm):
`npx --yes skills@latest add https://github.com/SWOFART/OneShot/tree/develop --skill oneshot-arc-payment`.
8 changes: 3 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ ONESHOT_WORKSPACE_ID=team-testnet-workspace
ONESHOT_API_RATE_LIMIT_MAX_REQUESTS=60
ONESHOT_API_RATE_LIMIT_WINDOW_MS=60000

# One-tool MCP demo. The bearer is accepted only at /mcp. The configured
# request key makes this deployment a literal one-intent demo; identical calls
# replay the same durable payment and any other key is denied.
# ONESHOT_MCP_BEARER_TOKEN=<random-secret-at-least-32-characters>
# One-tool MCP. Each Privy user generates a workspace-bound bearer in Profile.
# The optional deployment bearer keeps one operator-controlled client working.
# ONESHOT_MCP_BEARER_TOKEN=<optional-random-secret-at-least-32-characters>
# ONESHOT_MCP_REQUEST_KEY=<one-stable-demo-request-key>
# ONESHOT_MCP_PAYER_ADDRESS=0x<40-hex-privy-server-wallet-address>
# ONESHOT_MCP_MAX_AMOUNT_ATOMIC=1000000
# ONESHOT_MCP_WAIT_MS=2500

# Production worker effect boundary. Public identifiers are placeholders;
Expand Down
Loading
Loading