{"id":30193289,"url":"https://github.com/radiustechsystems/mcp-sdk","last_synced_at":"2026-01-20T16:54:51.738Z","repository":{"id":308421459,"uuid":"1031481694","full_name":"radiustechsystems/mcp-sdk","owner":"radiustechsystems","description":"Official Radius MCP SDK for token-gating Model Context Protocol tools, resources, and prompts.","archived":false,"fork":false,"pushed_at":"2025-08-05T20:57:49.000Z","size":74,"stargazers_count":3,"open_issues_count":2,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-13T01:56:26.323Z","etag":null,"topics":["ai-tools","authentication","authorization","developer-tools","eip712","erc1155","evm","mcp","model-context-protocol","sdk","token-gating","web3"],"latest_commit_sha":null,"homepage":"https://www.radiustech.xyz/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/radiustechsystems.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-03T20:41:21.000Z","updated_at":"2025-08-12T09:33:56.000Z","dependencies_parsed_at":"2025-08-05T21:46:25.083Z","dependency_job_id":"ac3377c9-71b5-498a-8d92-67ce714b59ad","html_url":"https://github.com/radiustechsystems/mcp-sdk","commit_stats":null,"previous_names":["radiustechsystems/mcp-sdk"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/radiustechsystems/mcp-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radiustechsystems%2Fmcp-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radiustechsystems%2Fmcp-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radiustechsystems%2Fmcp-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radiustechsystems%2Fmcp-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/radiustechsystems","download_url":"https://codeload.github.com/radiustechsystems/mcp-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radiustechsystems%2Fmcp-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273213920,"owners_count":25065058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-01T02:00:09.058Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-tools","authentication","authorization","developer-tools","eip712","erc1155","evm","mcp","model-context-protocol","sdk","token-gating","web3"],"created_at":"2025-08-13T01:56:22.818Z","updated_at":"2026-01-20T16:54:51.711Z","avatar_url":"https://github.com/radiustechsystems.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Radius MCP SDK\n\n[![npm version](https://img.shields.io/npm/v/@radiustechsystems/mcp-sdk.svg)](https://www.npmjs.com/package/@radiustechsystems/mcp-sdk)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nToken-gate your MCP tools, resources, and prompts with just 3 lines of code. Works seamlessly with the **Radius MCP Server** to enable decentralized, token-based access control across the MCP ecosystem.\n\n\u003e **TESTNET RELEASE**  \n\u003e This SDK is currently configured for use with Radius Testnet.\n\n## Overview\n\nThe Radius MCP SDK is the authorization component of the Radius ecosystem. It allows MCP server developers to protect their tools, resources, and prompts with ERC-1155 token requirements. The SDK verifies cryptographic proofs generated by the Radius MCP Server and checks on-chain token ownership, enabling a decentralized marketplace of token-gated AI tools.\n\n### How It Works\n\n1. **Simple Integration**: Add SDK to your MCP server with 3 lines of code\n2. **Proof Verification**: SDK validates EIP-712 signatures from the Radius MCP Server\n3. **Token Checking**: Direct on-chain verification of token ownership\n4. **Intelligent Errors**: Guides Claude through authentication and purchase flow\n5. **Performance**: Built-in caching and request deduplication\n\n## Installation\n\n```bash\npnpm add @radiustechsystems/mcp-sdk\n# or\nnpm install @radiustechsystems/mcp-sdk\n# or\nyarn add @radiustechsystems/mcp-sdk\n```\n\n## Features\n\n- **🔐 Cryptographic Security**: EIP-712 signature verification\n- **🧠 AI-Friendly**: Structured error responses that guide Claude through the flow\n- **📝 TypeScript First**: Full type safety with comprehensive interfaces\n- **🛡️ Security Enhanced**: Chain ID validation and replay protection\n- **⚡ High Performance**: Built-in caching and request deduplication\n- **🎯 Simple Integration**: Just 3 lines of code to protect any MCP tool\n\n## Quick Start\n\n```typescript\nimport { RadiusMcpSdk } from '@radiustechsystems/mcp-sdk';\n\n// Simple usage - just provide the contract address!\n// Defaults to Radius Testnet (chainId: 1223953)\nconst radius = new RadiusMcpSdk({\n  contractAddress: '0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96'\n});\n\n// Protect any MCP tool, resource, or prompt\nhandler: radius.protect(TOKEN_ID, yourHandler)\n```\n\n## Working Example\n\nCheck out the [`/examples/fastmcp`](./examples/fastmcp) directory for a complete working example that you can run in under 60 seconds!\n\n## Dependencies\n\nThe SDK has minimal dependencies:\n\n- `viem` - For Ethereum interactions and EIP-712 signature verification\n- `@evmauth/eip712-authn` - For EIP-712 authentication handling\n\n## Complete Usage Example\n\n### How It Works: The 3-Call Flow\n\n```typescript\n// 1. Claude tries to use your protected tool\nawait yourTool({ query: \"analyze market data\" });\n// Response: EVMAUTH_PROOF_MISSING error with required tokens\n\n// 2. Claude calls Radius MCP Server (handles everything in one call!)\nconst response = await authenticate_and_purchase({ \n  tokenIds: [101]  // From error's requiredTokens field\n});\n// Returns: { proof, purchases } - proof for auth + purchase info (if tokens were bought)\n\n// 3. Claude retries with authentication proof\nconst result = await yourTool({ \n  query: \"analyze market data\",\n  __evmauth: response.proof  // Proof from authenticate_and_purchase\n});\n// Success! Tool executes and returns results\n```\n\n### The __evmauth Namespace\n\nThe SDK uses a reserved `__evmauth` namespace to:\n\n1. **Keep auth separate**: Authentication data never mixes with business logic\n2. **Maintain full security**: EIP-712 signature verification with cryptographic guarantees\n3. **Simplify handlers**: Your tool handlers receive clean requests without auth data\n4. **Guide Claude**: Clear error messages show exactly how to use the namespace\n\n### From Developer's Perspective\n\n```typescript\n// Your entire integration:\nconst radius = new RadiusMcpSdk({ ...config });\n\nserver.addTool({\n  name: 'market_analyzer',\n  handler: radius.protect(101, async (args) =\u003e {\n    // Your tool logic here - only runs if user owns token 101\n    return analyzeMarket(args.query);\n  })\n});\n```\n\n## Testnet Configuration\n\n```text\nChain ID: 1223953\nRPC URL: https://rpc.testnet.radiustech.xyz\n```\n\n## Configuration\n\n### Basic Configuration\n\n```typescript\nconst radius = new RadiusMcpSdk({\n  contractAddress: '0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96'\n});\n```\n\n### Advanced Configuration\n\n```typescript\nconst radius = new RadiusMcpSdk({\n  contractAddress: '0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96',\n  chainId: 1223953,\n  rpcUrl: 'https://rpc.testnet.radiustech.xyz',\n  cache: {\n    ttl: 300,           // Cache TTL in seconds\n    maxSize: 1000,      // Max cache entries\n    disabled: false     // Set true to disable caching\n  },\n  debug: false          // Enable debug logging\n});\n```\n\n### Configuration Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `contractAddress` | `string` | Required | ERC-1155 contract address |\n| `chainId` | `number` | `1223953` | Blockchain network ID (Radius Testnet) |\n| `rpcUrl` | `string` | Radius Testnet RPC | RPC endpoint for ownership checks |\n| `cache.ttl` | `number` | `60` | Cache TTL in seconds |\n| `cache.maxSize` | `number` | `1000` | Maximum cache entries |\n| `cache.disabled` | `boolean` | `false` | Disable caching |\n| `debug` | `boolean` | `false` | Enable debug logging |\n\n## Framework Examples\n\n### FastMCP Integration\n\n```typescript\nimport { FastMCP } from 'fastmcp';\nimport { RadiusMcpSdk } from '@radiustechsystems/mcp-sdk';\nimport { z } from 'zod';\n\n// Simple initialization - defaults to Radius Testnet\nconst radius = new RadiusMcpSdk({\n  contractAddress: '0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96'\n});\n\n// Or explicitly set chain/RPC for other networks\nconst radiusCustom = new RadiusMcpSdk({\n  contractAddress: '0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96',\n  chainId: 1223953,\n  rpcUrl: 'https://rpc.testnet.radiustech.xyz'\n});\n\nconst server = new FastMCP({\n  name: 'Premium Analytics',\n  version: '1.0.0'\n});\n\n// Protected tool\nserver.addTool({\n  name: 'premium_analytics',\n  description: 'Advanced market analytics (requires token)',\n  inputSchema: z.object({\n    market: z.string(),\n    timeframe: z.string()\n  }),\n  handler: radius.protect(101, async (args) =\u003e {\n    const data = await fetchPremiumData(args.market, args.timeframe);\n    return { content: [{ type: 'text', text: JSON.stringify(data) }] };\n  })\n});\n\n// Protected resource\nserver.addResource({\n  name: 'premium_dataset',\n  description: 'Premium market dataset (requires token)',\n  handler: radius.protect(102, async () =\u003e {\n    return {\n      contents: [\n        { uri: 'dataset://premium/2024', text: loadPremiumData() }\n      ]\n    };\n  })\n});\n\n// Protected prompt\nserver.addPrompt({\n  name: 'expert_trading_prompt',\n  description: 'Expert trading strategies (requires token)',\n  handler: radius.protect(103, async () =\u003e {\n    return {\n      messages: [\n        { role: 'system', content: 'You are an expert trader...' },\n        { role: 'user', content: 'Analyze this market...' }\n      ]\n    };\n  })\n});\n```\n\n## Multi-Token Protection\n\n### ANY Token Logic\n\n```typescript\n// User needs ANY of these tokens\nhandler: radius.protect([201, 202, 203], async (args) =\u003e {\n  // User has at least one of the required tokens\n  return performEnterpriseAnalytics(args.query);\n})\n```\n\n### Specific Token Requirements\n\n```typescript\n// Different tools require different tokens\nconst TOKENS = {\n  BASIC_ANALYTICS: 101,\n  PREMIUM_ANALYTICS: 102,\n  ENTERPRISE_ANALYTICS: [201, 202, 203] // ANY of these\n};\n\n// Basic tier\nserver.addTool({\n  name: 'basic_analytics',\n  handler: radius.protect(TOKENS.BASIC_ANALYTICS, basicHandler)\n});\n\n// Premium tier\nserver.addTool({\n  name: 'premium_analytics',\n  handler: radius.protect(TOKENS.PREMIUM_ANALYTICS, premiumHandler)\n});\n\n// Enterprise tier\nserver.addTool({\n  name: 'enterprise_analytics',\n  handler: radius.protect(TOKENS.ENTERPRISE_ANALYTICS, enterpriseHandler)\n});\n```\n\n## Integration with the Radius MCP Server\n\nThis SDK works in tandem with the **Radius MCP Server** to create a complete token-gating ecosystem:\n\n1. **Radius MCP Server**\n   - Handles OAuth authentication with AI clients\n   - Manages user wallets via Privy\n   - Generates cryptographic proofs\n   - Processes token purchases\n   - One instance per AI client\n\n2. **Radius MCP SDK** (this repo)\n   - Verifies proofs from the Radius MCP Server\n   - Checks on-chain token ownership\n   - Protects your MCP tools/resources/prompts\n   - Guides AI through the flow\n\n## Error Handling\n\n### Error Codes\n\nThe SDK uses specific error codes for different failure scenarios:\n\n- `EVMAUTH_PROOF_MISSING` - No proof provided in the request\n- `PROOF_EXPIRED` - Proof has expired (proofs expire after 30 seconds by default)\n- `PROOF_INVALID` - Proof format is invalid\n- `CHAIN_MISMATCH` - Chain ID in proof doesn't match SDK configuration\n- `CONTRACT_MISMATCH` - Contract address in proof doesn't match SDK configuration\n- `SIGNATURE_INVALID` - EIP-712 signature verification failed\n- `SIGNER_MISMATCH` - Signature doesn't match the claimed wallet address\n- `NONCE_INVALID` - Nonce is malformed or outside acceptable time window\n- `PAYMENT_REQUIRED` - User doesn't own required tokens\n\n### Structured Error Responses\n\nThe SDK provides comprehensive error responses that guide MCP clients such as Claude through the authentication flow:\n\n```typescript\n// When proof is missing\n{\n  \"error\": {\n    \"code\": \"EVMAUTH_PROOF_MISSING\",\n    \"message\": \"You need to authenticate with Radius MCP Server first\",\n    \"details\": {\n      \"contractAddress\": \"0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96\",\n      \"chainId\": 1223953,\n      \"requiredTokens\": [101]\n    },\n    \"claude_action\": {\n      \"description\": \"You need to authenticate and potentially purchase tokens\",\n      \"steps\": [\n        \"Call the authenticate_and_purchase tool on Radius MCP Server with the required tokenIds\",\n        \"The tool will check if you own the tokens and purchase them if needed\",\n        \"Copy the entire proof object from the response\",\n        \"Include it as \\\"__evmauth\\\": \u003cproof\u003e in this tool's arguments\",\n        \"Retry this tool call with the proof included\"\n      ],\n      \"tool\": {\n        \"server\": \"radius-mcp-server\",\n        \"name\": \"authenticate_and_purchase\",\n        \"arguments\": {\n          \"tokenIds\": [101]\n        }\n      }\n    }\n  }\n}\n\n// When token ownership is required (after authentication)\n{\n  \"error\": {\n    \"code\": \"PAYMENT_REQUIRED\",\n    \"message\": \"Token ownership required\",\n    \"details\": {\n      \"requiredTokens\": [101],\n      \"contractAddress\": \"0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96\",\n      \"chainId\": 1223953,\n      \"checkedWallet\": \"0x742d35Cc6634C0532925a3b844Bc9e7Ed1A0aC0E\"\n    },\n    \"claude_action\": {\n      \"description\": \"You don't own the required tokens. You need to purchase them.\",\n      \"steps\": [\n        \"Call the authenticate_and_purchase tool again on Radius MCP Server\",\n        \"It will automatically purchase the missing tokens\",\n        \"Use the new proof from the response\",\n        \"Retry this tool call with the new proof\"\n      ],\n      \"tool\": {\n        \"server\": \"radius-mcp-server\",\n        \"name\": \"authenticate_and_purchase\",\n        \"arguments\": {\n          \"tokenIds\": [101]\n        }\n      }\n    }\n  }\n}\n```\n\n## Architecture\n\n### Namespace Design\n\nThe SDK uses a reserved `__evmauth` namespace for authentication data. This design ensures:\n\n- Tool handlers receive clean requests without authentication parameters\n- Authentication logic is completely separated from business logic\n- Full cryptographic security with EIP-712 signatures\n- Claude receives clear guidance on how to provide authentication\n\n### Security Model\n\nThe SDK implements a multi-layered security approach:\n\n1. **EIP-712 Signature Verification**: Validates cryptographic proofs using standard Ethereum signing\n2. **Chain ID Validation**: Prevents cross-chain replay attacks\n3. **Domain Validation**: Ensures proof was created for the correct contract\n4. **Timestamp Validation**: Prevents replay of expired proofs\n5. **Nonce Validation**: Ensures proof freshness and prevents replay attacks\n6. **Fail-Closed Design**: Denies access on any validation failure\n\n### Performance Optimizations\n\n1. **Intelligent Caching**: LRU cache with TTL for token ownership results\n2. **Request Deduplication**: Prevents duplicate RPC calls for same token/wallet\n3. **Connection Pooling**: Efficient RPC client with retry logic\n\n### Proof Flow\n\n```mermaid\nsequenceDiagram\n    participant C as Claude\n    participant T as Tool (Your MCP)\n    participant S as Radius MCP SDK\n    participant R as RPC Node\n    participant E as Radius MCP Server\n\n    C-\u003e\u003eT: Call protected tool\n    T-\u003e\u003eS: protect() wrapper\n    S-\u003e\u003eS: Extract proof from request\n    \n    alt No proof\n        S-\u003e\u003eC: EVMAUTH_PROOF_MISSING\n        C-\u003e\u003eE: authenticate_and_purchase\n        E-\u003e\u003eC: Return proof and purchase info\n        C-\u003e\u003eT: Retry with proof\n    end\n    \n    S-\u003e\u003eS: Verify EIP-712 signature\n    S-\u003e\u003eS: Validate timestamp and nonce\n    S-\u003e\u003eS: Check cache for token\n    \n    alt Cache miss\n        S-\u003e\u003eR: balanceOf(wallet, tokenId)\n        R-\u003e\u003eS: Return balance\n        S-\u003e\u003eS: Cache result\n    end\n    \n    alt Has tokens\n        S-\u003e\u003eT: Execute handler\n        T-\u003e\u003eC: Return result\n    else No tokens\n        S-\u003e\u003eC: PAYMENT_REQUIRED\n        C-\u003e\u003eE: authenticate_and_purchase\n        E-\u003e\u003eC: Purchase complete with new proof\n        C-\u003e\u003eT: Retry with new proof\n    end\n```\n\n## TypeScript Support\n\n### Exported Types and Utilities\n\nThe SDK exports the following types and utilities:\n\n```typescript\n// Main SDK class\nexport { RadiusMcpSdk }\n\n// Types\nexport type { \n  RadiusConfig,\n  CacheConfig,\n  MCPHandler,\n  MCPRequest,\n  MCPResponse,\n  EVMAuthProof,\n  EVMAuthErrorResponse,\n  ProofErrorCode,\n  RadiusError,\n  RadiusErrorCode\n}\n\n// Utilities from viem\nexport { isAddress }\nexport type { Address }\n\n// Version constant\nexport const VERSION\n```\n\n### Full Type Safety\n\n```typescript\nimport { RadiusMcpSdk, type RadiusConfig, type EVMAuthProof, VERSION } from '@radiustechsystems/mcp-sdk';\n\n// Version constant is exported\nconsole.log('SDK Version:', VERSION); // '1.0.0'\n\n// Configuration is fully typed\nconst config: RadiusConfig = {\n  contractAddress: '0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96',\n  chainId: 1223953,\n  rpcUrl: 'https://rpc.testnet.radiustech.xyz',\n  cache: {\n    ttl: 300,\n    maxSize: 1000,\n    disabled: false\n  }\n};\n\n// Proof structure is typed\nconst proof: EVMAuthProof = {\n  challenge: {\n    domain: {\n      name: 'EVMAuth',\n      version: '1',\n      chainId: 1223953,\n      verifyingContract: '0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96'\n    },\n    types: {\n      EIP712Domain: [/* ... */],\n      EVMAuthRequest: [/* ... */]\n    },\n    primaryType: 'EVMAuthRequest',\n    message: {\n      serverName: 'radius-mcp-server',\n      resourceName: 'mcp_tool',\n      requiredTokens: '[]',\n      walletAddress: '0x...',\n      nonce: '123456-randomhex',\n      issuedAt: '1234567890',\n      expiresAt: '1234567890',\n      purpose: 'mcp_tool_access'\n    }\n  },\n  signature: '0x...' as `0x${string}`\n};\n```\n\n### Handler Types\n\n```typescript\nimport type { MCPHandler, MCPRequest, MCPResponse } from '@radiustechsystems/mcp-sdk';\n\n// Your handlers are properly typed\nconst myHandler: MCPHandler = async (\n  request: MCPRequest,\n  extra?: any\n): Promise\u003cMCPResponse\u003e =\u003e {\n  // TypeScript knows the structure\n  return {\n    content: [{ type: 'text', text: 'Hello!' }]\n  };\n};\n```\n\n## Advanced Usage\n\n### Public API\n\nThe `RadiusMcpSdk` class exposes only one public method:\n\n- `protect(tokenId: number | number[], handler: MCPHandler): MCPHandler` - Wraps a handler with token protection\n\nAll other functionality (proof verification, token checking, caching) is handled internally and not exposed in the public API.\n\n### Dynamic Token Requirements\n\n```typescript\n// Token requirements based on user tier\nconst getTokenRequirement = (userTier: string): number | number[] =\u003e {\n  switch (userTier) {\n    case 'basic': return 101;\n    case 'premium': return 102;\n    case 'enterprise': return [201, 202, 203];\n    default: throw new Error('Invalid tier');\n  }\n};\n\nserver.addTool({\n  name: 'tiered_analytics',\n  handler: async (request) =\u003e {\n    const userTier = request.params.tier;\n    const tokenRequirement = getTokenRequirement(userTier);\n    \n    return radius.protect(tokenRequirement, async (args) =\u003e {\n      return performTieredAnalysis(args, userTier);\n    })(request);\n  }\n});\n```\n\n## Testing\n\n### Unit Testing\n\n```typescript\nimport { RadiusMcpSdk } from '@radiustechsystems/mcp-sdk';\nimport { vi, describe, it, expect } from 'vitest';\n\ndescribe('Radius MCP SDK', () =\u003e {\n  it('should require proof for protected handlers', async () =\u003e {\n    const radius = new RadiusMcpSdk({\n      contractAddress: '0x5448Dc20ad9e0cDb5Dd0db25e814545d1aa08D96',\n      chainId: 1223953,\n      rpcUrl: 'https://rpc.testnet.radiustech.xyz'\n    });\n\n    const handler = vi.fn();\n    const protectedHandler = radius.protect(101, handler);\n\n    const request = { params: { arguments: {} } };\n    const response = await protectedHandler(request);\n\n    expect(response.content[0].text).toContain('EVMAUTH_PROOF_MISSING');\n    expect(handler).not.toHaveBeenCalled();\n  });\n});\n```\n\n## Performance Monitoring\n\n### Debug Mode\n\n```typescript\nconst radius = new RadiusMcpSdk({\n  contractAddress: '0x...',\n  chainId: 1223953,\n  rpcUrl: 'https://...',\n  debug: true  // Enable debug logging\n});\n\n// Debug mode logs:\n// - Token balance check results\n// - Cache hit/miss information\n// - RPC call details\n// - Proof validation steps\n```\n\n## Troubleshooting\n\n### Common Issues\n\n1. **\"EVMAUTH_PROOF_MISSING\" Errors**\n   - Ensure Radius MCP Server is connected\n   - Check that proof is included in `__evmauth` parameter\n   - Verify proof hasn't expired (default 30 seconds)\n\n2. **\"Chain ID mismatch\" Errors**\n   - Verify SDK chainId matches the network\n   - Ensure proof was created for the same chain\n\n3. **RPC Connection Issues**\n   - Verify RPC URL is correct and accessible\n   - Check network connectivity\n   - Ensure RPC endpoint supports eth_call\n\n## For AI Agents (Claude, GPT, etc.)\n\n### Important: The __evmauth Parameter\n\nWhen using tools protected by Radius MCP SDK:\n\n1. **The `__evmauth` parameter is ALWAYS accepted** - Even if a tool's schema doesn't list `__evmauth` as a parameter, ALL Radius MCP SDK-protected tools accept it.\n\n2. **It's automatically stripped** - The SDK removes the `__evmauth` parameter before calling the actual tool logic, so tool developers never see it.\n\n3. **Example usage**:\n\n   ```javascript\n   // First, authenticate and get a proof\n   const { proof } = await authenticate_and_purchase({\n     tokenIds: [101]  // Required tokens from the error\n   });\n   \n   // Then use it with ANY protected tool\n   const result = await any_protected_tool({\n     // ... normal parameters ...,\n     __evmauth: proof  // This ALWAYS works!\n   });\n   ```\n\n4. **Common mistake**: Don't worry if you don't see `__evmauth` in a tool's parameter list. It's a special parameter that's always accepted by the Radius MCP SDK.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradiustechsystems%2Fmcp-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fradiustechsystems%2Fmcp-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradiustechsystems%2Fmcp-sdk/lists"}