Opensea Tool Sdk logo

Opensea Tool Sdk

Organization
ProjectOpenSea
opensea-tool-sdk

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, subscriptions, trait gating, or x402 pay-per-call (USDC), and call gated tools. For querying OpenSea marketplace data use opensea-api instead.

Overview

PublisherProjectOpenSea
Repositoryopensea-skill
Skill nameopensea-tool-sdk
Stars
53
Forks
16
Bundled files
3
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 3 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by ProjectOpenSea on GitHub. Read the source before you install it.

Installation

Install the Opensea Tool Sdk AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/ProjectOpenSea/opensea-skill/tree/main/opensea-tool-sdk
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/ProjectOpenSea/opensea-skill.git /tmp/opensea-skill
mkdir -p .claude/skills
cp -r /tmp/opensea-skill/opensea-tool-sdk .claude/skills/opensea-tool-sdk
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Opensea Tool Sdk in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Opensea Tool Sdk on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Opensea Tool Sdk is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

OpenSea Tool SDK

Build, register, and gate AI-callable tool endpoints using the OpenSea Tool Registry (ERC-8257) on Base.

When to use this skill (scope_in)

Use opensea-tool-sdk when you need to:

  • Scaffold an AI-callable tool endpoint (HTTPS, JSON Schema, .well-known manifest) for Vercel, Cloudflare, or Express
  • Register a tool onchain on the Base ToolRegistry so other agents can discover it
  • Gate access via x402 pay-per-call (USDC) or predicates (ERC-721/ERC-1155 ownership, subscriptions, trait gating, ERC-20 balance, composites)
  • Call a gated or paid tool: 402 payments (paidFetch), predicate-gated auth (eip3009AuthenticatedFetch), or both (paidAuthenticatedFetch)
  • Search and discover registered tools via the OpenSea REST API

When NOT to use this skill (scope_out, handoff)

NeedUse instead
Query NFT/token data, search, collection statsopensea-api
Buy/sell NFTsopensea-marketplace
Swap ERC20 tokensopensea-swaps
Set up wallet signing providersopensea-wallet

This SDK is for tool providers and consumers. To query OpenSea marketplace data (floor prices, listings, trades), use the opensea-api skill instead.

Concepts

TermMeaning
ToolA single REST API endpoint with a JSON Schema interface, discoverable via /.well-known/ai-tool/<slug>.json. Each tool should perform one focused operation.
ManifestJCS-canonicalized JSON describing the tool's name, endpoint, inputs, outputs, pricing, and access policy
ToolRegistryOnchain contract (Base) where tools are registered with a manifest hash and optional access predicate
Access PredicateAn IAccessPredicate contract that gates who can invoke a tool (NFT ownership, subscriptions, trait gating, ERC-20 balance, composites)
x402HTTP 402-based pay-per-call protocol (caller signs a USDC TransferWithAuthorization; server settles after execution)
EIP-3009 authZero-value USDC TransferWithAuthorization signature used to authenticate callers for predicate-gated tools
FacilitatorThird-party service that verifies and settles x402 payments (PayAI or Coinbase CDP)

Important Constraints

One tool = one endpoint. Each tool registration represents a single REST API endpoint with a singular focus and intention. The endpoint URL in your manifest should point to a specific API route that performs one well-defined operation (e.g., POST /api/price-check or POST /api/translate), not a generic HTML page, documentation site, or multi-purpose URL. Think of each registered tool the same way you think of an individual REST API endpoint. It should accept a specific input, perform a specific action, and return a specific output.

Origin binding: manifest and endpoint must share the exact same origin. Your .well-known/ai-tool/<slug>.json manifest and your tool's invocation endpoint must be served from the exact same origin (identical scheme, host, and port per RFC 6454). Subdomains do not count as the same origin. example.com and api.example.com are different origins. This is enforced at registration time. If the manifest origin and endpoint origin don't match exactly, the tool will be rejected and marked as deregistered.

  • Valid: manifest at https://my-tool.example.com/.well-known/ai-tool/my-tool.json, endpoint at https://my-tool.example.com/api/my-tool
  • Invalid: manifest at https://example.com/.well-known/ai-tool/my-tool.json, endpoint at https://api.example.com/api/my-tool

If you need your API on a subdomain, serve the manifest from that same subdomain (e.g., both on api.example.com).

Deployed Contracts (Ethereum mainnet, Base, Shape, Abstract, Monad, Robinhood Chain)

Canonical v0.2 deployments — identical CREATE2 address on every supported chain.

ContractAddress
ToolRegistry (v0.2)0x265BB2DBFC0A8165C9A1941Eb1372F349baD2cf1
ERC721OwnerPredicate (v0.2)0xc8721c9A776958FfFfEb602DA1b708bf1D318379
ERC1155OwnerPredicate (v0.2)0x77373Dc3c1AE9A1e937eF3e5E08F4807D47c7c11
SubscriptionPredicate (v0.2)0xCBe0cd9B1d99d95Baa9c58f2767246C52e461f25
TraitGatedPredicate (v0.2)0x10abF07CfA34Bf22372C57f27e8bd9C2DCF93fA1
ERC20BalancePredicate (v0.2)0x1a834FC48B5f6e119c62C12a98b32137bCFA77cD

Tool Discovery [Beta]

Search or look up registered tools via the OpenSea REST API. Requires OPENSEA_API_KEY.

bash
# Reuse OPENSEA_API_KEY if already set; otherwise fetch an instant free-tier key
# (no signup — 600/h read, 30/h write, 7-day expiry) and SAVE it for reuse.
if [ -z "${OPENSEA_API_KEY:-}" ]; then
  KEY_FILE="${OPENSEA_CONFIG_DIR:-$HOME/.opensea}/api_key"
  if [ -s "$KEY_FILE" ]; then
    export OPENSEA_API_KEY=$(cat "$KEY_FILE")          # reuse cached key
  else
    api_key=$(curl -s -X POST https://api.opensea.io/api/v2/auth/keys | jq -r '.api_key')
    mkdir -p "$(dirname "$KEY_FILE")"
    (umask 077; printf '%s\n' "$api_key" > "$KEY_FILE")  # save before using it
    export OPENSEA_API_KEY="${api_key}"
  fi
fi

Always save a fetched instant key and reuse it rather than re-fetching. The opensea-api skill ships an auth/opensea-resolve-key.sh helper that does this (env → cached file → fetch + save); see its "API key resolution" section. For higher rate limits, create a full key at Settings → Developer.

List tools: GET /api/v2/tools (docs)

ParameterRequiredDescription
sort_byNoSort by: newest (default), oldest
typeNoFilter by access type: open, nft_gated, token_gated, subscription, gated
limitNoResults per page (1–100)
cursorNoPagination cursor

Search tools: GET /api/v2/tools/search (docs)

ParameterRequiredDescription
queryNoSearch query text
registry_chainNoFilter by registry chain ID
tagsNoFilter by tags
access_typeNoFilter by access type: open, nft_gated, subscription
creatorNoFilter by creator address
sort_byNoSort by: relevance (default), newest, most_used
limitNoResults per page (1–200)
cursor.valueNoPagination cursor

Get a tool: GET /api/v2/tools/{registry_chain}/{registry_addr}/{tool_id} (docs)

ParameterRequiredDescription
registry_chainYesRegistry chain ID (e.g. 1, 8453)
registry_addrYesRegistry contract address
tool_idYesNumeric tool ID
bash
# List tools sorted by newest
curl -s "https://api.opensea.io/api/v2/tools?sort_by=newest&limit=10" \
  -H "x-api-key: $OPENSEA_API_KEY" | jq

# List tools filtered by type
curl -s "https://api.opensea.io/api/v2/tools?type=open&sort_by=oldest" \
  -H "x-api-key: $OPENSEA_API_KEY" | jq

# Search tools by keyword
curl -s "https://api.opensea.io/api/v2/tools/search?query=nft" \
  -H "x-api-key: $OPENSEA_API_KEY" | jq

# Get a specific tool on Base
curl -s "https://api.opensea.io/api/v2/tools/8453/0x265BB2DBFC0A8165C9A1941Eb1372F349baD2cf1/1" \
  -H "x-api-key: $OPENSEA_API_KEY" | jq

# Filter by access type
curl -s "https://api.opensea.io/api/v2/tools/search?access_type=open&limit=10" \
  -H "x-api-key: $OPENSEA_API_KEY" | jq

1. Create a Tool

1a. Scaffold a project

bash
npx @opensea/tool-sdk init --runtime vercel   # or: cloudflare, express

This generates:

  • src/manifest.ts — tool manifest definition
  • src/handler.ts — request handler with input/output schemas
  • api/index.ts — framework adapter entry point
  • public/llms.txt — agent-readable discovery page
  • api/well-known/[slug].ts — serves the manifest at /.well-known/ai-tool/<slug>.json

1b. Define the manifest

typescript
import { 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: [...] },
})

1c. Write the handler

typescript
import { 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}` }
  },
})

1d. Wire up the adapter

Vercel:

typescript
import { toVercelHandler } from "@opensea/tool-sdk"
import { toolHandler } from "../src/handler.js"
export default toVercelHandler(toolHandler)

Express:

typescript
import { toExpressHandler } from "@opensea/tool-sdk"
import { toolHandler } from "./handler.js"
app.post("/api", toExpressHandler(toolHandler))

Cloudflare Workers:

typescript
import { toolHandler } from "./handler.js"
export default { fetch: toolHandler }

2. Register a Tool Onchain

2a. Via CLI

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 an 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:

  1. Fetches the manifest from --metadata URL
  2. Validates the manifest schema
  3. Verifies manifest.creatorAddress matches your wallet
  4. Computes the JCS keccak256 manifest hash
  5. Calls ToolRegistry.registerTool(metadataURI, manifestHash, accessPredicate)
  6. Returns the toolId from the ToolRegistered event

2b. Via SDK (programmatic)

typescript
import { 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) = open access
})

console.log(`Registered tool ${toolId} in tx ${txHash}`)

3. Gating tool access

Tools can be gated three ways:

GateMechanismReference
x402 paywallPay-per-call (USDC, EIP-3009)references/x402.md
Predicate gateOnchain check (NFT, subscription, trait gating, ERC-20 balance, composite)references/predicate-gating.md
CombinedEIP-3009 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.

4. Wallet Setup

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.

ProviderEnv varsBest for
Private KeyPRIVATE_KEYLocal dev, scripts
PrivyPRIVY_APP_ID, PRIVY_APP_SECRET, PRIVY_WALLET_IDServer wallets
TurnkeyTURNKEY_API_PUBLIC_KEY, TURNKEY_API_PRIVATE_KEY, TURNKEY_ORGANIZATION_IDEnterprise signing
FireblocksFIREBLOCKS_API_KEY, FIREBLOCKS_API_SECRET, FIREBLOCKS_VAULT_ACCOUNT_IDInstitutional custody
BankrBANKR_API_KEYAgent wallets (via HTTP API)

For any provider, RPC_URL (or the --rpc-url flag) sets the RPC endpoint for onchain reads and writes. When neither is set, CLI commands fall back to the network's default public RPC, which can be slow or rate-limited.

typescript
import { createWalletFromEnv } from "@opensea/tool-sdk"

// Auto-detects: Privy > Fireblocks > Turnkey > Bankr > PrivateKey
const adapter = createWalletFromEnv()
const address = await adapter.getAddress()

For Bankr (external signer):

typescript
import { createBankrAccount } from "@opensea/tool-sdk"

const account = await createBankrAccount("your-bankr-api-key")
// Use with eip3009AuthenticatedFetch or paidAuthenticatedFetch

5. Response Codes

CodeMeaningAction
200SuccessParse the JSON body per the manifest's outputs schema
400Invalid inputFix request body to match the manifest's inputs schema
401Invalid or expired X-Payment signatureRe-sign a fresh zero-value EIP-3009 authorization and retry with the X-Payment header
402Payment / identity requiredThe challenge is in body.accepts[0] (x402 v1) or the PAYMENT-REQUIRED response header (v2). For predicate gates (amount "0"), sign a zero-value authorization; for x402 paywalls, sign the requested amount. Send it back in X-PAYMENT (v1) or PAYMENT-SIGNATURE (v2) — pay/paidFetch choose the right header automatically.
403Access deniedInspect body.predicate to discover what's needed; acquire the required token/subscription
405Method not allowedUse the verb the tool expects. pay auto-retries as GET when an unspecified-method POST probe returns 404/405; otherwise pass --method <verb>.
500Internal tool errorRetry or contact the tool creator
502Predicate/facilitator errorThe upstream predicate or payment facilitator misbehaved; retry later

6. Quick Reference: CLI Commands

CommandPurpose
initScaffold a new tool project
validateValidate a manifest file
hashCompute the JCS keccak256 hash of a manifest
exportExport the manifest as JSON
registerRegister a tool onchain. Supports --nft-gate, --erc20-gate + --erc20-min-balance, or --predicate-config to bundle predicate setup with registration
update-metadataUpdate a tool's metadata URI and manifest hash onchain
inspectLook up a tool's onchain config by ID
verifyVerify a manifest against its onchain hash
deployDeploy a tool to Vercel
authCall a predicate-gated tool (EIP-3009)
payCall an x402-paid or gated tool (probes for 402, signs, retries). Handles x402 v1/v2 and GET tools. Flags: --method <verb> (defaults POST; bodyless verbs put params in the query string; auto-falls back to GET on a 404/405 POST probe), --max-amount <baseUnits> spend cap (default 10 USDC, unlimited to disable), --body, --wallet-provider
smokeAuto-detect gate type and call
dry-run-gateSimulate an x402 gate check locally
dry-run-predicate-gateSimulate a predicate gate check locally
set-collectionsSet ERC-721 collection gate list for a tool
get-collectionsRead ERC-721 collection gate list for a tool
set-collection-tokensSet ERC-1155 collection + token ID gate for a tool
configure-subscriptionConfigure SubscriptionPredicate gate (collection + minTier) for a tool
configure-trait-gatingConfigure TraitGatedPredicate gate (collection, traits contract, trait key, allowed values) for a tool
get-trait-configRead trait gating configuration for a tool
configure-erc20-gateConfigure ERC20BalancePredicate gate (token, minBalance) for a tool
get-erc20-configRead ERC-20 balance gating configuration for a tool

All CLI commands accept --wallet-provider privy|turnkey|fireblocks|bankr|private-key or auto-detect from env vars.

The manifest is hashed as served (ERC-8257 §2). The registry hash is the JCS keccak256 of the full manifest document, including any namespaced extension fields. Nothing is stripped and no defaults are injected before hashing, so a hash computed by any RFC 8785 implementation agrees with the SDK and the backend. The schema is open: extension fields MUST be namespaced (reverse-DNS, e.g. io.opensea.paymentHint, or the legacy x- prefix); validate, hash, and register warn about bare un-namespaced extension fields, since those risk colliding with future normative fields.

7. Usage Tracking

Tool-sdk reports usage to OpenSea's analytics endpoint (POST /api/v2/tools/usage) for each successful call. It reports the verified caller: the on-chain payer for paid x402 calls, or the caller's own EIP-3009 authorization for predicateGate-authenticated calls. A tool server never signs on the caller's behalf.

usageReporting (recommended)

Pass usageReporting to createToolHandler and it runs the reporter at the very end of the lifecycle, awaited before the response returns (bounded by timeoutMs, default 5s) so it completes even on serverless runtimes that freeze on response flush. Failures are logged, never fatal. No walletClient is needed server-side:

  • Paid x402 calls → verification_type: "x402_settlement" with the payer address and settlement tx hash. The backend verifies the tx directly.
  • EIP-3009-authenticated calls (behind predicateGate) → verification_type: "eip3009_authorization", forwarding the caller's original signed authorization. The caller already signed it to authenticate, so the reported identity is the real caller.
typescript
import { createToolHandler } from "@opensea/tool-sdk"

export const toolHandler = createToolHandler({
  manifest,
  inputSchema: InputSchema,
  outputSchema: OutputSchema,
  gates: [/* x402 paywall and/or predicateGate */],
  usageReporting: {
    chainId: 8453,                // EIP-712 USDC domain / x402 chain_id fallback
    toolChainId: 8453,            // ERC-8257: chain where the tool is registered
    toolRegistryAddress: "0x...", // ERC-8257: registry contract
    toolOnchainId: 42,            // ERC-8257: tool ID in the registry
    apiKey: process.env.OPENSEA_API_KEY!,
    // optional: aggregatorUrl, tokenAddress, timeoutMs
  },
  handler: async (input) => {
    return { result: `Processed: ${input.query}` }
  },
})

Reporting is always the service's responsibility (authenticated by apiKey), never the caller's; there is no caller self-reporting path. To report from a custom pipeline instead of the handler, use the standalone createEip3009UsageReporter / createX402UsageReporter (see the tool-sdk README "Usage Reporting" section).

onInvocation callback

You can also provide a custom onInvocation callback for bespoke analytics. It fires after the handler succeeds and settles, before the response is returned, with an InvocationEvent containing caller identity, payment status, and timing:

typescript
import { createToolHandler } from "@opensea/tool-sdk"
import type { InvocationEvent } from "@opensea/tool-sdk"

export const toolHandler = createToolHandler({
  manifest,
  inputSchema: InputSchema,
  outputSchema: OutputSchema,
  onInvocation: (event: InvocationEvent) => {
    // event.callerAddress — verified caller wallet
    // event.paid          — whether x402 payment settled
    // event.toolName      — resolved tool name from manifest
    // event.latencyMs     — handler execution time
    // event.timestamp     — invocation timestamp
  },
  handler: async (input) => {
    return { result: `Processed: ${input.query}` }
  },
})

8. End-to-End Examples

Example A: Free open-access tool

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"}'

Example B: x402 paid tool (pay-per-call only, no identity check)

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"}'

Example C: NFT-gated tool (identity check, no payment)

bash
# Register with ERC721OwnerPredicate
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 0xYOUR_COLLECTION_ADDRESS

# Configure which collection(s) gate the tool (if not using --nft-gate):
npx @opensea/tool-sdk set-collections <TOOL_ID> 0xYOUR_COLLECTION_ADDRESS \
  --network base

# 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"}'

Example D: Subscription-gated tool

bash
# Register with SubscriptionPredicate and configure in one shot:
PRIVATE_KEY=0x... npx @opensea/tool-sdk register \
  --metadata https://my-tool.vercel.app/.well-known/ai-tool/my-tool.json \
  --access-predicate 0xCBe0cd9B1d99d95Baa9c58f2767246C52e461f25 \
  --predicate-config '{"collection":"0xYOUR_SUBSCRIPTION_NFT","minTier":0}' \
  --network base

# Or configure after registration:
npx @opensea/tool-sdk configure-subscription <TOOL_ID> 0xYOUR_SUBSCRIPTION_NFT \
  --min-tier 0 --network base

# 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"}'

Example E: ERC-20 balance-gated tool

bash
# Register with ERC20BalancePredicate and configure in one shot:
PRIVATE_KEY=0x... npx @opensea/tool-sdk register \
  --metadata https://my-tool.vercel.app/.well-known/ai-tool/my-tool.json \
  --network base \
  --erc20-gate 0xTOKEN_ADDRESS --erc20-min-balance 1000000000000000000

# Or configure after registration:
npx @opensea/tool-sdk configure-erc20-gate <TOOL_ID> 0xTOKEN_ADDRESS 1000000000000000000 \
  --network base

# 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"}'

Example F: NFT-gated + paid tool (combined gate, single round trip)

bash
# Server: use paidPredicateGate (see references/predicate-gating.md)
# Single 402: identity proof + payment in one X-Payment signature
PRIVATE_KEY=0x... RPC_URL=https://mainnet.base.org \
  npx @opensea/tool-sdk pay \
  https://my-tool.vercel.app/api \
  --body '{"query": "hello"}'

References

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Opensea Tool Sdk AI skill do?

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, subscriptions, trait gating, or x402 pay-per-call (USDC), and call gated tools. For querying OpenSea marketplace data use opensea-api instead.

Why use Opensea Tool Sdk on TypingMind?

Because you install it once and use it with any model. Opensea Tool Sdk is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Opensea Tool Sdk in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/ProjectOpenSea/opensea-skill/tree/main/opensea-tool-sdk. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Opensea Tool Sdk?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Opensea Tool Sdk?

As many as you like. As long as a model supports skills, you can use Opensea Tool Sdk with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Opensea Tool Sdk AI skill free?

Yes. It is published on GitHub by ProjectOpenSea under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇