Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Build, register, and gate AI-callable tool endpoints using the OpenSea Tool Registry (ERC-8257) on Base. Scaffold HTTPS tools with JSON Schema interfaces, register them onchain, gate access via NFT ownership or x402 pay-per-call (USDC), and call gated tools. For querying OpenSea marketplace data use opensea-api instead.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 128% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 131% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 270% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 79% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 101% | 0% |
Build, register, and gate AI-callable tool endpoints using the OpenSea Tool Registry (ERC-8257) on Base.
scope_in)Use opensea-tool-sdk when you need to:
.well-known manifest) for Vercel, Cloudflare, or ExpressauthenticatedFetch), 402 payments (paidFetch), or both (paidAuthenticatedFetch)scope_out, handoff)| Need | Use instead | |---|---| | Query NFT/token data, search, collection stats | opensea-api | | Buy/sell NFTs | opensea-marketplace | | Swap ERC20 tokens | opensea-swaps | | Set up wallet signing providers | opensea-wallet |
This SDK is for tool providers and consumers. To query OpenSea marketplace data (floor prices, listings, trades), use the opensea-api skill instead.
| Term | Meaning | |------|---------| | Tool | An HTTPS endpoint with a JSON Schema interface, discoverable via /.well-known/ai-tool/<slug>.json | | Manifest | JCS-canonicalized JSON describing the tool's name, endpoint, inputs, outputs, pricing, and access policy | | ToolRegistry | Onchain contract (Base) where tools are registered with a manifest hash and optional access predicate | | Access Predicate | An IAccessPredicate contract that gates who can invoke a tool (NFT ownership, subscriptions, composites) | | x402 | HTTP 402-based pay-per-call protocol (caller signs a USDC TransferWithAuthorization; server settles after execution) | | SIWE | Sign-In with Ethereum (EIP-4361), used to authenticate callers for predicate-gated tools | | Facilitator | Third-party service that verifies and settles x402 payments (PayAI or Coinbase CDP) |
| Contract | Address | |----------|---------| | ToolRegistry (v0.1) | 0x7291BbFbC368C2D478eCe1eA30de31F612a34856 | | ERC721OwnerPredicate (v0.2) | 0xd1F703D0B90BB7106fAebBfbcAdD2B07BDc4c769 | | ERC1155OwnerPredicate (v0.2) | 0xc179b9d4D9B7ffe0CdA608134729f72003380A7e |
bashnpx @opensea/tool-sdk init --runtime vercel # or: cloudflare, express
This generates:
src/manifest.ts: tool manifest definitionsrc/handler.ts: request handler with input/output schemasapi/index.ts: framework adapter entry pointpublic/llms.txt: agent-readable discovery pageapi/well-known/[slug].ts: serves the manifest at /.well-known/ai-tool/<slug>.jsontypescriptimport { defineManifest } from "@opensea/tool-sdk" export const manifest = defineManifest({ name: "My Tool", description: "What this tool does", endpoint: "https://my-tool.example.com/api", creatorAddress: "0xYOUR_WALLET_ADDRESS", inputs: { type: "object", properties: { query: { type: "string", description: "Search query" }, }, required: ["query"], }, outputs: { type: "object", properties: { result: { type: "string" }, }, }, // Optional: add pricing for x402 paywall (see references/x402.md) // pricing: paywall.pricing, // Optional: add access requirements (see references/predicate-gating.md) // access: { logic: "OR", requirements: [...] }, })
typescriptimport { createToolHandler } from "@opensea/tool-sdk" import { z } from "zod/v4" import { manifest } from "./manifest.js" const InputSchema = z.object({ query: z.string() }) const OutputSchema = z.object({ result: z.string() }) export const toolHandler = createToolHandler({ manifest, inputSchema: InputSchema, outputSchema: OutputSchema, // gates: [], // Add gates here (see references/x402.md and references/predicate-gating.md) handler: async (input) => { return { result: `Processed: ${input.query}` } }, })
Vercel:
typescriptimport { toVercelHandler } from "@opensea/tool-sdk" import { toolHandler } from "../src/handler.js" export default toVercelHandler(toolHandler)
Express:
typescriptimport { toExpressHandler } from "@opensea/tool-sdk" import { toolHandler } from "./handler.js" app.post("/api", toExpressHandler(toolHandler))
Cloudflare Workers:
typescriptimport { toolHandler } from "./handler.js" export default { fetch: toolHandler }
bash# Set up wallet export PRIVATE_KEY=0x... export RPC_URL=https://mainnet.base.org # Register (open access, no predicate) npx @opensea/tool-sdk register \ --metadata https://my-tool.example.com/.well-known/ai-tool/my-tool.json \ --network base # Register with NFT gate (ERC-721 collection) npx @opensea/tool-sdk register \ --metadata https://my-tool.example.com/.well-known/ai-tool/my-tool.json \ --network base \ --nft-gate 0xCOLLECTION_ADDRESS # Register with a custom access predicate npx @opensea/tool-sdk register \ --metadata https://my-tool.example.com/.well-known/ai-tool/my-tool.json \ --network base \ --access-predicate 0xPREDICATE_ADDRESS # Dry run (no transaction) npx @opensea/tool-sdk register --metadata ... --network base --dry-run
The CLI:
--metadata URLmanifest.creatorAddress matches your walletToolRegistry.registerTool(metadataURI, manifestHash, accessPredicate)toolId from the ToolRegistered eventtypescriptimport { ToolRegistryClient, computeManifestHash } from "@opensea/tool-sdk" import { createWalletFromEnv, walletAdapterToClient } from "@opensea/tool-sdk" import { base } from "viem/chains" const adapter = createWalletFromEnv() const walletClient = await walletAdapterToClient(adapter, base) const registry = new ToolRegistryClient({ chain: base, rpcUrl: "https://mainnet.base.org", walletClient, }) const { toolId, txHash } = await registry.registerTool({ metadataURI: "https://my-tool.example.com/.well-known/ai-tool/my-tool.json", manifest, // your ToolManifest object accessPredicate: "0x0000...0000", // address(0) for open access }) console.log(`Registered tool ${toolId} in tx ${txHash}`)
Tools can be gated three ways:
| Gate | Mechanism | Reference | |------|-----------|-----------| | x402 paywall | Pay-per-call (USDC, EIP-3009) | references/x402.md | | Predicate gate | Onchain check (NFT, subscription, composite) | references/predicate-gating.md | | Combined | SIWE auth and payment (predicate first, then x402) | references/predicate-gating.md |
For deployed predicate addresses, requirement encodings, and SDK helpers like describeToolAccess / decodeRequirement, see references/known-predicates.md.
The SDK supports multiple wallet providers via @opensea/wallet-adapters. Set environment variables and the SDK auto-detects the provider. See the opensea-wallet skill for the full provider table, env vars, setup walkthroughs, and signing-policy configuration.
typescriptimport { createWalletFromEnv } from "@opensea/tool-sdk" const adapter = createWalletFromEnv() const address = await adapter.getAddress()
For Bankr (external signer):
typescriptimport { createBankrAccount } from "@opensea/tool-sdk" const account = await createBankrAccount("your-bankr-api-key") // Use with authenticatedFetch or paidAuthenticatedFetch
| Code | Meaning | Action | |------|---------|--------| | 200 | Success | Parse the JSON body per the manifest's outputs schema | | 400 | Invalid input | Fix request body to match the manifest's inputs schema | | 401 | Missing/invalid SIWE auth | Sign a SIWE message and include Authorization: SIWE <token> | | 402 | Payment required | Read body.accepts[0] for payment requirements, sign and retry with X-Payment | | 403 | Access denied | Inspect body.predicate to discover what's needed; acquire the required token/subscription | | 405 | Method not allowed | Use POST | | 500 | Internal tool error | Retry or contact the tool creator | | 502 | Predicate/facilitator error | The upstream predicate or payment facilitator misbehaved; retry later |
| Command | Purpose | |---------|---------| | init | Scaffold a new tool project | | validate | Validate a manifest file | | hash | Compute the JCS keccak256 hash of a manifest | | export | Export the manifest as JSON | | register | Register a tool onchain | | update-metadata | Update a tool's metadata URI and manifest hash onchain | | inspect | Look up a tool's onchain config by ID | | verify | Verify a manifest against its onchain hash | | deploy | Deploy a tool to Vercel | | auth | Call a predicate-gated tool (SIWE) | | pay | Call an x402-paid tool (USDC) | | smoke | Auto-detect gate type and call | | dry-run-gate | Simulate an x402 gate check locally | | dry-run-predicate-gate | Simulate a predicate gate check locally |
All CLI commands accept --wallet-provider privy|turnkey|fireblocks|bankr|private-key or auto-detect from env vars.
bash# 1. Scaffold npx @opensea/tool-sdk init --runtime vercel # 2. Edit src/manifest.ts and src/handler.ts with your logic # 3. Deploy npx @opensea/tool-sdk deploy # 4. Register (open access) PRIVATE_KEY=0x... npx @opensea/tool-sdk register \ --metadata https://my-tool.vercel.app/.well-known/ai-tool/my-tool.json \ --network base # 5. Call curl -X POST https://my-tool.vercel.app/api \ -H "Content-Type: application/json" \ -d '{"query": "hello"}'
bash# Server: add paywall gate (see references/x402.md) # Call via CLI: PRIVATE_KEY=0x... npx @opensea/tool-sdk pay \ https://my-tool.vercel.app/api \ --body '{"query": "hello"}'
bash# Register with NFT gate PRIVATE_KEY=0x... npx @opensea/tool-sdk register \ --metadata https://my-tool.vercel.app/.well-known/ai-tool/my-tool.json \ --network base \ --nft-gate 0xCOLLECTION # Server: add predicateGate (see references/predicate-gating.md) # Call via CLI: PRIVATE_KEY=0x... RPC_URL=https://mainnet.base.org \ npx @opensea/tool-sdk auth \ https://my-tool.vercel.app/api \ --body '{"query": "hello"}'
bash# Server: add both predicateGate and paywall.gate (see references/predicate-gating.md) # Call via CLI: PRIVATE_KEY=0x... RPC_URL=https://mainnet.base.org \ npx @opensea/tool-sdk smoke \ --endpoint https://my-tool.vercel.app/api \ --expect 200
references/x402.md: pay-per-call protocol, server-side paywall, paidFetchreferences/predicate-gating.md: SIWE-based access control, combined gatesreferences/known-predicates.md: deployed predicate contracts and SDK helpersOther measured skills in the registry, with their headline benchmark lift.