Skip to main content
Glama

create_paywall

Generate paywall URLs that charge agents for accessing protected resources using on-chain payments, returning HTTP 402 until payment is verified.

Instructions

Create an x402 paywall that charges agents/clients for accessing a resource. Returns a public access URL that returns HTTP 402 until paid. Agents pay on-chain, then retry with proof to get the content.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
wallet_idYesWallet ID to receive payments
nameYesHuman-readable paywall name (e.g. "Premium API Access")
descriptionNoDescription shown in the 402 response
amountYesPrice in human-readable format (e.g. "0.01" for 0.01 USDC)
token_typeNo"erc20" for EVM stablecoins, "spl" for Solana SPL tokens, "native" for ETH/SOL/POL/etc.erc20
token_addressNoToken contract address (ERC-20 for EVM, SPL mint Base58 for Solana). Required if token_type is "erc20" or "spl". Use get_chains to find stablecoin addresses.
token_decimalsNoToken decimals (6 for USDC, 18 for ETH/most tokens)
token_nameNoToken display name (e.g. "USDC", "ETH")USDC
chain_idNoChain ID for payments (8453=Base, 1=Ethereum, etc.)
resource_urlYesURL of the protected resource to serve after payment verification
resource_mimeNoMIME type of the resource (e.g. "application/json", "text/plain")application/json

Implementation Reference

  • The 'create_paywall' tool handler. Creates an x402 paywall by converting the human-readable amount to raw token units using parseUnits(), then calls the API endpoint '/x402/paywalls' with all paywall configuration (wallet_id, name, description, amount, token details, chain_id, resource_url, resource_mime). Returns the created paywall data with formatted price string.
    server.tool(
      'create_paywall',
      'Create an x402 paywall that charges agents/clients for accessing a resource. ' +
        'Returns a public access URL that returns HTTP 402 until paid. ' +
        'Agents pay on-chain, then retry with proof to get the content.',
      {
        wallet_id: z.number().int().describe('Wallet ID to receive payments'),
        name: z.string().describe('Human-readable paywall name (e.g. "Premium API Access")'),
        description: z.string().default('').describe('Description shown in the 402 response'),
        amount: z.string().describe('Price in human-readable format (e.g. "0.01" for 0.01 USDC)'),
        token_type: z.enum(['erc20', 'spl', 'native']).default('erc20').describe('"erc20" for EVM stablecoins, "spl" for Solana SPL tokens, "native" for ETH/SOL/POL/etc.'),
        token_address: z.string().default('').describe('Token contract address (ERC-20 for EVM, SPL mint Base58 for Solana). Required if token_type is "erc20" or "spl". Use get_chains to find stablecoin addresses.'),
        token_decimals: z.number().int().default(6).describe('Token decimals (6 for USDC, 18 for ETH/most tokens)'),
        token_name: z.string().default('USDC').describe('Token display name (e.g. "USDC", "ETH")'),
        chain_id: z.number().int().default(8453).describe('Chain ID for payments (8453=Base, 1=Ethereum, etc.)'),
        resource_url: z.string().url().describe('URL of the protected resource to serve after payment verification'),
        resource_mime: z.string().default('application/json').describe('MIME type of the resource (e.g. "application/json", "text/plain")'),
      },
      async ({ wallet_id, name, description, amount, token_type, token_address, token_decimals, token_name, chain_id, resource_url, resource_mime }) => {
        // Convert human-readable amount to raw token units
        const rawAmount = parseUnits(amount, token_decimals);
    
        const data = await api('/x402/paywalls', 'POST', {
          wallet_id,
          name,
          description,
          amount: rawAmount,
          token_type,
          token_address,
          token_decimals,
          token_name,
          chain_id,
          resource_url,
          resource_mime,
        });
    
        return jsonResponse({
          ...(data as Record<string, unknown>),
          price: `${amount} ${token_name}`,
          chain_id,
        });
      },
    );
  • The Zod schema definition for 'create_paywall' tool inputs. Defines 11 parameters: wallet_id (required int), name (required string), description (default ''), amount (required string for human-readable price), token_type (enum: erc20/spl/native, default erc20), token_address (default ''), token_decimals (default 6), token_name (default 'USDC'), chain_id (default 8453 for Base), resource_url (required URL), resource_mime (default 'application/json').
    server.tool(
      'create_paywall',
      'Create an x402 paywall that charges agents/clients for accessing a resource. ' +
        'Returns a public access URL that returns HTTP 402 until paid. ' +
        'Agents pay on-chain, then retry with proof to get the content.',
      {
        wallet_id: z.number().int().describe('Wallet ID to receive payments'),
        name: z.string().describe('Human-readable paywall name (e.g. "Premium API Access")'),
        description: z.string().default('').describe('Description shown in the 402 response'),
        amount: z.string().describe('Price in human-readable format (e.g. "0.01" for 0.01 USDC)'),
        token_type: z.enum(['erc20', 'spl', 'native']).default('erc20').describe('"erc20" for EVM stablecoins, "spl" for Solana SPL tokens, "native" for ETH/SOL/POL/etc.'),
        token_address: z.string().default('').describe('Token contract address (ERC-20 for EVM, SPL mint Base58 for Solana). Required if token_type is "erc20" or "spl". Use get_chains to find stablecoin addresses.'),
        token_decimals: z.number().int().default(6).describe('Token decimals (6 for USDC, 18 for ETH/most tokens)'),
        token_name: z.string().default('USDC').describe('Token display name (e.g. "USDC", "ETH")'),
        chain_id: z.number().int().default(8453).describe('Chain ID for payments (8453=Base, 1=Ethereum, etc.)'),
        resource_url: z.string().url().describe('URL of the protected resource to serve after payment verification'),
        resource_mime: z.string().default('application/json').describe('MIME type of the resource (e.g. "application/json", "text/plain")'),
      },
  • src/index.ts:1218-1262 (registration)
    Full registration of 'create_paywall' tool with the MCP server using server.tool(). Includes the tool name, description explaining it creates an x402 paywall that charges agents/clients for accessing resources, the Zod input schema, and the async handler function.
    // ─── Tool: create_paywall ────────────────────────────────────────
    
    server.tool(
      'create_paywall',
      'Create an x402 paywall that charges agents/clients for accessing a resource. ' +
        'Returns a public access URL that returns HTTP 402 until paid. ' +
        'Agents pay on-chain, then retry with proof to get the content.',
      {
        wallet_id: z.number().int().describe('Wallet ID to receive payments'),
        name: z.string().describe('Human-readable paywall name (e.g. "Premium API Access")'),
        description: z.string().default('').describe('Description shown in the 402 response'),
        amount: z.string().describe('Price in human-readable format (e.g. "0.01" for 0.01 USDC)'),
        token_type: z.enum(['erc20', 'spl', 'native']).default('erc20').describe('"erc20" for EVM stablecoins, "spl" for Solana SPL tokens, "native" for ETH/SOL/POL/etc.'),
        token_address: z.string().default('').describe('Token contract address (ERC-20 for EVM, SPL mint Base58 for Solana). Required if token_type is "erc20" or "spl". Use get_chains to find stablecoin addresses.'),
        token_decimals: z.number().int().default(6).describe('Token decimals (6 for USDC, 18 for ETH/most tokens)'),
        token_name: z.string().default('USDC').describe('Token display name (e.g. "USDC", "ETH")'),
        chain_id: z.number().int().default(8453).describe('Chain ID for payments (8453=Base, 1=Ethereum, etc.)'),
        resource_url: z.string().url().describe('URL of the protected resource to serve after payment verification'),
        resource_mime: z.string().default('application/json').describe('MIME type of the resource (e.g. "application/json", "text/plain")'),
      },
      async ({ wallet_id, name, description, amount, token_type, token_address, token_decimals, token_name, chain_id, resource_url, resource_mime }) => {
        // Convert human-readable amount to raw token units
        const rawAmount = parseUnits(amount, token_decimals);
    
        const data = await api('/x402/paywalls', 'POST', {
          wallet_id,
          name,
          description,
          amount: rawAmount,
          token_type,
          token_address,
          token_decimals,
          token_name,
          chain_id,
          resource_url,
          resource_mime,
        });
    
        return jsonResponse({
          ...(data as Record<string, unknown>),
          price: `${amount} ${token_name}`,
          chain_id,
        });
      },
    );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hifriendbot/agentwallet-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server