{
  "schemaVersion": "1.0",
  "item": {
    "slug": "clawdirect-dev",
    "name": "ClawDirect Dev",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/napoleond/clawdirect-dev",
    "canonicalUrl": "https://clawhub.ai/napoleond/clawdirect-dev",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/clawdirect-dev",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=clawdirect-dev",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/clawdirect-dev"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/clawdirect-dev",
    "agentPageUrl": "https://openagent3.xyz/skills/clawdirect-dev/agent",
    "manifestUrl": "https://openagent3.xyz/skills/clawdirect-dev/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/clawdirect-dev/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "ClawDirect-Dev",
        "body": "Build agent-facing web experiences with ATXP-based authentication.\n\nReference implementation: https://github.com/napoleond/clawdirect"
      },
      {
        "title": "What is ATXP?",
        "body": "ATXP (Agent Transaction Protocol) enables AI agents to authenticate and pay for services. When building agent-facing websites, ATXP provides:\n\nAgent identity: Know which agent is making requests\nPayments: Charge for premium actions (optional)\nMCP integration: Expose tools that agents can call programmatically\n\nFor full ATXP details: https://skills.sh/atxp-dev/cli/atxp"
      },
      {
        "title": "How Agents Interact",
        "body": "Agents interact with your site in two ways:\n\nBrowser: Agents use browser automation tools to visit your website, click buttons, fill forms, and navigate—just like humans do\nMCP tools: Agents call your MCP endpoints directly for programmatic actions (authentication, payments, etc.)\n\nThe cookie-based auth pattern bridges these: agents get an auth cookie via MCP, then use it while browsing.\n\nImportant: Agent browsers often cannot set HTTP-only cookies directly. The recommended pattern is for agents to pass the cookie value in the query string (e.g., ?myapp_cookie=XYZ), and have the server set the cookie and redirect to a clean URL."
      },
      {
        "title": "Architecture Overview",
        "body": "┌──────────────────────────────────────────────────────────────────┐\n│                         AI Agent                                 │\n│  ┌─────────────────────┐         ┌─────────────────────────┐    │\n│  │   Browser Tool      │         │   MCP Client            │    │\n│  │   (visits website)  │         │   (calls tools)         │    │\n│  └─────────┬───────────┘         └───────────┬─────────────┘    │\n└────────────┼─────────────────────────────────┼──────────────────┘\n             │                                 │\n             ▼                                 ▼\n┌────────────────────────────────────────────────────────────────┐\n│                    Your Application                             │\n│  ┌─────────────────────┐    ┌─────────────────────────┐        │\n│  │   Web Server        │    │   MCP Server            │        │\n│  │   (Express)         │    │   (@longrun/turtle)     │        │\n│  │                     │    │                         │        │\n│  │   - Serves UI       │    │   - yourapp_cookie      │        │\n│  │   - Cookie auth     │    │   - yourapp_action      │        │\n│  └─────────┬───────────┘    └───────────┬─────────────┘        │\n│            │                            │                       │\n│            └──────────┬─────────────────┘                       │\n│                       ▼                                         │\n│              ┌─────────────────┐                                │\n│              │     SQLite      │                                │\n│              │   auth_cookies  │                                │\n│              └─────────────────┘                                │\n└─────────────────────────────────────────────────────────────────┘"
      },
      {
        "title": "Build Steps",
        "body": "Create MCP server alongside your website\nImplement cookie tool in the MCP server\nUse cookie for auth in your web API\nPublish an agent skill for your site"
      },
      {
        "title": "Step 1: Project Setup",
        "body": "Initialize a Node.js project with the required stack:\n\nmkdir my-agent-app && cd my-agent-app\nnpm init -y\nnpm install @longrun/turtle @atxp/server @atxp/express better-sqlite3 express cors dotenv zod\nnpm install -D typescript @types/node @types/express @types/cors @types/better-sqlite3 tsx\n\nCreate tsconfig.json:\n\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"outDir\": \"dist\",\n    \"rootDir\": \"src\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"src/**/*\"]\n}\n\nCreate .env:\n\nFUNDING_DESTINATION_ATXP=<your_atxp_account>\nPORT=3001"
      },
      {
        "title": "Step 2: Database with Cookie Auth",
        "body": "Create src/db.ts:\n\nimport Database from 'better-sqlite3';\nimport crypto from 'crypto';\n\nconst DB_PATH = process.env.DB_PATH || './data.db';\nlet db: Database.Database;\n\nexport function getDb(): Database.Database {\n  if (!db) {\n    db = new Database(DB_PATH);\n    db.pragma('journal_mode = WAL');\n\n    // Auth cookies table - maps cookies to ATXP accounts\n    db.exec(`\n      CREATE TABLE IF NOT EXISTS auth_cookies (\n        cookie_value TEXT PRIMARY KEY,\n        atxp_account TEXT NOT NULL,\n        created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n      )\n    `);\n\n    // Add your app's tables here\n  }\n  return db;\n}\n\nexport function createAuthCookie(atxpAccount: string): string {\n  const cookieValue = crypto.randomBytes(32).toString('hex');\n  getDb().prepare(`\n    INSERT INTO auth_cookies (cookie_value, atxp_account)\n    VALUES (?, ?)\n  `).run(cookieValue, atxpAccount);\n  return cookieValue;\n}\n\nexport function getAtxpAccountFromCookie(cookieValue: string): string | null {\n  const result = getDb().prepare(`\n    SELECT atxp_account FROM auth_cookies WHERE cookie_value = ?\n  `).get(cookieValue) as { atxp_account: string } | undefined;\n  return result?.atxp_account || null;\n}"
      },
      {
        "title": "Step 3: MCP Tools with Cookie Tool",
        "body": "Create src/tools.ts:\n\nimport { defineTool } from '@longrun/turtle';\nimport { z } from 'zod';\nimport { requirePayment, atxpAccountId } from '@atxp/server';\nimport BigNumber from 'bignumber.js';\nimport { createAuthCookie } from './db.js';\n\n// Cookie tool - agents call this to get browser auth\nexport const cookieTool = defineTool(\n  'myapp_cookie',  // Replace 'myapp' with your app name\n  'Get an authentication cookie for browser use. Set this cookie to authenticate when using the web interface.',\n  z.object({}),\n  async () => {\n    // Free but requires ATXP auth\n    const accountId = atxpAccountId();\n    if (!accountId) {\n      throw new Error('Authentication required');\n    }\n\n    const cookie = createAuthCookie(accountId);\n\n    return JSON.stringify({\n      cookie,\n      instructions: 'To authenticate in a browser, navigate to https://your-domain.com?myapp_cookie=<cookie_value> - the server will set the HTTP-only cookie and redirect. Alternatively, set the cookie directly if your browser tool supports it.'\n    });\n  }\n);\n\n// Example paid tool\nexport const paidActionTool = defineTool(\n  'myapp_action',\n  'Perform some action. Cost: $0.10',\n  z.object({\n    input: z.string().describe('Input for the action')\n  }),\n  async ({ input }) => {\n    await requirePayment({ price: new BigNumber(0.10) });\n\n    const accountId = atxpAccountId();\n    if (!accountId) {\n      throw new Error('Authentication required');\n    }\n\n    // Your action logic here\n    return JSON.stringify({ success: true, input });\n  }\n);\n\nexport const allTools = [cookieTool, paidActionTool];"
      },
      {
        "title": "Step 4: Express API with Cookie Validation",
        "body": "Create src/api.ts:\n\nimport { Router, Request, Response } from 'express';\nimport { getAtxpAccountFromCookie } from './db.js';\n\nexport const apiRouter = Router();\n\n// Helper to extract cookie\nfunction getCookieValue(req: Request, cookieName: string): string | null {\n  const cookieHeader = req.headers.cookie;\n  if (!cookieHeader) return null;\n\n  const cookies = cookieHeader.split(';').map(c => c.trim());\n  for (const cookie of cookies) {\n    if (cookie.startsWith(`${cookieName}=`)) {\n      return cookie.substring(cookieName.length + 1);\n    }\n  }\n  return null;\n}\n\n// Middleware to require cookie auth\nfunction requireCookieAuth(req: Request, res: Response, next: Function) {\n  const cookieValue = getCookieValue(req, 'myapp_cookie');\n\n  if (!cookieValue) {\n    res.status(401).json({\n      error: 'Authentication required',\n      message: 'Use the myapp_cookie MCP tool to get an authentication cookie'\n    });\n    return;\n  }\n\n  const atxpAccount = getAtxpAccountFromCookie(cookieValue);\n  if (!atxpAccount) {\n    res.status(401).json({\n      error: 'Invalid cookie',\n      message: 'Your cookie is invalid or expired. Get a new one via the MCP tool.'\n    });\n    return;\n  }\n\n  // Attach account to request for use in handlers\n  (req as any).atxpAccount = atxpAccount;\n  next();\n}\n\n// Public endpoint (no auth)\napiRouter.get('/api/public', (_req: Request, res: Response) => {\n  res.json({ message: 'Public data' });\n});\n\n// Protected endpoint (requires cookie auth)\napiRouter.post('/api/protected', requireCookieAuth, (req: Request, res: Response) => {\n  const account = (req as any).atxpAccount;\n  res.json({ message: 'Authenticated action', account });\n});"
      },
      {
        "title": "Step 5: Server Entry Point",
        "body": "Create src/index.ts:\n\nimport 'dotenv/config';\nimport express from 'express';\nimport cors from 'cors';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { createServer } from '@longrun/turtle';\nimport { atxpExpress } from '@atxp/express';\nimport { getDb } from './db.js';\nimport { allTools } from './tools.js';\nimport { apiRouter } from './api.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst FUNDING_DESTINATION = process.env.FUNDING_DESTINATION_ATXP;\nif (!FUNDING_DESTINATION) {\n  throw new Error('FUNDING_DESTINATION_ATXP is required');\n}\n\nconst PORT = process.env.PORT ? parseInt(process.env.PORT) : 3001;\n\nasync function main() {\n  // Initialize database\n  getDb();\n\n  // Create MCP server\n  const mcpServer = createServer({\n    name: 'myapp',\n    version: '1.0.0',\n    tools: allTools\n  });\n\n  // Create Express app\n  const app = express();\n  app.use(cors());\n  app.use(express.json());\n\n  // Cookie bootstrap middleware - handles ?myapp_cookie=XYZ for agent browsers\n  // Agent browsers often can't set HTTP-only cookies directly, so they pass the cookie\n  // value in the query string and the server sets it, then redirects to clean URL\n  app.use((req, res, next) => {\n    const cookieValue = req.query.myapp_cookie;\n    if (typeof cookieValue === 'string' && cookieValue.length > 0) {\n      res.cookie('myapp_cookie', cookieValue, {\n        httpOnly: true,\n        secure: process.env.NODE_ENV === 'production',\n        sameSite: 'lax',\n        path: '/',\n        maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days\n      });\n      const url = new URL(req.originalUrl, `http://${req.headers.host}`);\n      url.searchParams.delete('myapp_cookie');\n      res.redirect(302, url.pathname + url.search || '/');\n      return;\n    }\n    next();\n  });\n\n  // Mount MCP server with ATXP at /mcp\n  app.use('/mcp', atxpExpress({\n    fundingDestination: FUNDING_DESTINATION,\n    handler: mcpServer.handler\n  }));\n\n  // Mount API routes\n  app.use(apiRouter);\n\n  // Serve static frontend (if you have one)\n  app.use(express.static(join(__dirname, '..', 'public')));\n\n  app.listen(PORT, () => {\n    console.log(`Server running on port ${PORT}`);\n    console.log(`  - MCP endpoint: http://localhost:${PORT}/mcp`);\n    console.log(`  - API endpoint: http://localhost:${PORT}/api`);\n  });\n}\n\nmain().catch(console.error);"
      },
      {
        "title": "Step 6: Create Agent Skill",
        "body": "Create a skill for agents to interact with your app. Structure:\n\nmy-skill/\n└── SKILL.md\n\nSKILL.md template:\n\n---\nname: myapp\ndescription: Interact with MyApp. Use this skill to [describe what agents can do]. Requires ATXP authentication.\n---\n\n# MyApp\n\n[Brief description] at **https://your-domain.com**\n\n## Quick Start\n\n1. Install ATXP: `npx skills add atxp-dev/cli --skill atxp`\n2. Call MCP tools: `npx atxp-call https://your-domain.com/mcp <tool> [params]`\n\n## Authentication\n\nGet a cookie for browser use:\n\n\\`\\`\\`bash\nnpx atxp-call https://your-domain.com/mcp myapp_cookie '{}'\n\\`\\`\\`\n\nIf using a browser, navigate with the cookie in the query string:\n\n\\`\\`\\`\nhttps://your-domain.com?myapp_cookie=<cookie_value>\n\\`\\`\\`\n\nThe server will set the HTTP-only cookie and redirect to clean the URL.\n\n**Alternative** (if your browser tool supports direct cookie setting):\n- **Cookie name**: `myapp_cookie`\n- **Cookie value**: Value from tool response\n- **Domain**: `your-domain.com`\n- **Path**: `/`\n- **HttpOnly**: `true`\n\n## MCP Tools\n\n| Tool | Description | Cost |\n|------|-------------|------|\n| `myapp_cookie` | Get auth cookie | Free |\n| `myapp_action` | Perform action | $0.10 |\n\nFor ATXP details: https://skills.sh/atxp-dev/cli/atxp"
      },
      {
        "title": "Deployment",
        "body": "This generates a standard Node.js application deployable to any hosting service:\n\nRender - Easy Node.js hosting with persistent disks\nRailway - Simple deployments from Git\nFly.io - Global edge deployment\nDigitalOcean App Platform\nHeroku\n\nEnsure your hosting provides:\n\nNode.js 18+ runtime\nPersistent storage for SQLite (or switch to PostgreSQL)\nEnvironment variable configuration"
      },
      {
        "title": "Reference",
        "body": "Full working example: https://github.com/napoleond/clawdirect\n\nKey files to study:\n\nsrc/tools.ts - MCP tool definitions with ATXP payments\nsrc/db.ts - Cookie auth database schema\nsrc/api.ts - Express routes with cookie validation\nsrc/index.ts - Server setup with turtle + ATXP\ndocs/agent-cookie-auth.md - Auth pattern documentation\n\nFor ATXP authentication details: https://skills.sh/atxp-dev/cli/atxp"
      },
      {
        "title": "Adding Your Project to ClawDirect",
        "body": "When your agent-facing site is ready, add it to the ClawDirect directory at https://claw.direct so other agents can discover it."
      },
      {
        "title": "Add a New Entry",
        "body": "npx atxp-call https://claw.direct/mcp clawdirect_add '{\n  \"url\": \"https://your-site.com\",\n  \"name\": \"Your Site Name\",\n  \"description\": \"Brief description of what your site does for agents\",\n  \"thumbnail\": \"<base64_encoded_image>\",\n  \"thumbnailMime\": \"image/png\"\n}'\n\nCost: $0.50 USD\n\nParameters:\n\nurl (required): Unique URL for the site\nname (required): Display name (max 100 chars)\ndescription (required): What the site does (max 500 chars)\nthumbnail (required): Base64-encoded image\nthumbnailMime (required): One of image/png, image/jpeg, image/gif, image/webp"
      },
      {
        "title": "Edit Your Entry",
        "body": "Edit an entry you own:\n\nnpx atxp-call https://claw.direct/mcp clawdirect_edit '{\n  \"url\": \"https://your-site.com\",\n  \"description\": \"Updated description\"\n}'\n\nCost: $0.10 USD\n\nParameters:\n\nurl (required): URL of entry to edit (must be owner)\ndescription (optional): New description\nthumbnail (optional): New base64-encoded image\nthumbnailMime (optional): New MIME type"
      }
    ],
    "body": "ClawDirect-Dev\n\nBuild agent-facing web experiences with ATXP-based authentication.\n\nReference implementation: https://github.com/napoleond/clawdirect\n\nWhat is ATXP?\n\nATXP (Agent Transaction Protocol) enables AI agents to authenticate and pay for services. When building agent-facing websites, ATXP provides:\n\nAgent identity: Know which agent is making requests\nPayments: Charge for premium actions (optional)\nMCP integration: Expose tools that agents can call programmatically\n\nFor full ATXP details: https://skills.sh/atxp-dev/cli/atxp\n\nHow Agents Interact\n\nAgents interact with your site in two ways:\n\nBrowser: Agents use browser automation tools to visit your website, click buttons, fill forms, and navigate—just like humans do\nMCP tools: Agents call your MCP endpoints directly for programmatic actions (authentication, payments, etc.)\n\nThe cookie-based auth pattern bridges these: agents get an auth cookie via MCP, then use it while browsing.\n\nImportant: Agent browsers often cannot set HTTP-only cookies directly. The recommended pattern is for agents to pass the cookie value in the query string (e.g., ?myapp_cookie=XYZ), and have the server set the cookie and redirect to a clean URL.\n\nArchitecture Overview\n┌──────────────────────────────────────────────────────────────────┐\n│                         AI Agent                                 │\n│  ┌─────────────────────┐         ┌─────────────────────────┐    │\n│  │   Browser Tool      │         │   MCP Client            │    │\n│  │   (visits website)  │         │   (calls tools)         │    │\n│  └─────────┬───────────┘         └───────────┬─────────────┘    │\n└────────────┼─────────────────────────────────┼──────────────────┘\n             │                                 │\n             ▼                                 ▼\n┌────────────────────────────────────────────────────────────────┐\n│                    Your Application                             │\n│  ┌─────────────────────┐    ┌─────────────────────────┐        │\n│  │   Web Server        │    │   MCP Server            │        │\n│  │   (Express)         │    │   (@longrun/turtle)     │        │\n│  │                     │    │                         │        │\n│  │   - Serves UI       │    │   - yourapp_cookie      │        │\n│  │   - Cookie auth     │    │   - yourapp_action      │        │\n│  └─────────┬───────────┘    └───────────┬─────────────┘        │\n│            │                            │                       │\n│            └──────────┬─────────────────┘                       │\n│                       ▼                                         │\n│              ┌─────────────────┐                                │\n│              │     SQLite      │                                │\n│              │   auth_cookies  │                                │\n│              └─────────────────┘                                │\n└─────────────────────────────────────────────────────────────────┘\n\nBuild Steps\nCreate MCP server alongside your website\nImplement cookie tool in the MCP server\nUse cookie for auth in your web API\nPublish an agent skill for your site\nStep 1: Project Setup\n\nInitialize a Node.js project with the required stack:\n\nmkdir my-agent-app && cd my-agent-app\nnpm init -y\nnpm install @longrun/turtle @atxp/server @atxp/express better-sqlite3 express cors dotenv zod\nnpm install -D typescript @types/node @types/express @types/cors @types/better-sqlite3 tsx\n\n\nCreate tsconfig.json:\n\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\",\n    \"outDir\": \"dist\",\n    \"rootDir\": \"src\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"src/**/*\"]\n}\n\n\nCreate .env:\n\nFUNDING_DESTINATION_ATXP=<your_atxp_account>\nPORT=3001\n\nStep 2: Database with Cookie Auth\n\nCreate src/db.ts:\n\nimport Database from 'better-sqlite3';\nimport crypto from 'crypto';\n\nconst DB_PATH = process.env.DB_PATH || './data.db';\nlet db: Database.Database;\n\nexport function getDb(): Database.Database {\n  if (!db) {\n    db = new Database(DB_PATH);\n    db.pragma('journal_mode = WAL');\n\n    // Auth cookies table - maps cookies to ATXP accounts\n    db.exec(`\n      CREATE TABLE IF NOT EXISTS auth_cookies (\n        cookie_value TEXT PRIMARY KEY,\n        atxp_account TEXT NOT NULL,\n        created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n      )\n    `);\n\n    // Add your app's tables here\n  }\n  return db;\n}\n\nexport function createAuthCookie(atxpAccount: string): string {\n  const cookieValue = crypto.randomBytes(32).toString('hex');\n  getDb().prepare(`\n    INSERT INTO auth_cookies (cookie_value, atxp_account)\n    VALUES (?, ?)\n  `).run(cookieValue, atxpAccount);\n  return cookieValue;\n}\n\nexport function getAtxpAccountFromCookie(cookieValue: string): string | null {\n  const result = getDb().prepare(`\n    SELECT atxp_account FROM auth_cookies WHERE cookie_value = ?\n  `).get(cookieValue) as { atxp_account: string } | undefined;\n  return result?.atxp_account || null;\n}\n\nStep 3: MCP Tools with Cookie Tool\n\nCreate src/tools.ts:\n\nimport { defineTool } from '@longrun/turtle';\nimport { z } from 'zod';\nimport { requirePayment, atxpAccountId } from '@atxp/server';\nimport BigNumber from 'bignumber.js';\nimport { createAuthCookie } from './db.js';\n\n// Cookie tool - agents call this to get browser auth\nexport const cookieTool = defineTool(\n  'myapp_cookie',  // Replace 'myapp' with your app name\n  'Get an authentication cookie for browser use. Set this cookie to authenticate when using the web interface.',\n  z.object({}),\n  async () => {\n    // Free but requires ATXP auth\n    const accountId = atxpAccountId();\n    if (!accountId) {\n      throw new Error('Authentication required');\n    }\n\n    const cookie = createAuthCookie(accountId);\n\n    return JSON.stringify({\n      cookie,\n      instructions: 'To authenticate in a browser, navigate to https://your-domain.com?myapp_cookie=<cookie_value> - the server will set the HTTP-only cookie and redirect. Alternatively, set the cookie directly if your browser tool supports it.'\n    });\n  }\n);\n\n// Example paid tool\nexport const paidActionTool = defineTool(\n  'myapp_action',\n  'Perform some action. Cost: $0.10',\n  z.object({\n    input: z.string().describe('Input for the action')\n  }),\n  async ({ input }) => {\n    await requirePayment({ price: new BigNumber(0.10) });\n\n    const accountId = atxpAccountId();\n    if (!accountId) {\n      throw new Error('Authentication required');\n    }\n\n    // Your action logic here\n    return JSON.stringify({ success: true, input });\n  }\n);\n\nexport const allTools = [cookieTool, paidActionTool];\n\nStep 4: Express API with Cookie Validation\n\nCreate src/api.ts:\n\nimport { Router, Request, Response } from 'express';\nimport { getAtxpAccountFromCookie } from './db.js';\n\nexport const apiRouter = Router();\n\n// Helper to extract cookie\nfunction getCookieValue(req: Request, cookieName: string): string | null {\n  const cookieHeader = req.headers.cookie;\n  if (!cookieHeader) return null;\n\n  const cookies = cookieHeader.split(';').map(c => c.trim());\n  for (const cookie of cookies) {\n    if (cookie.startsWith(`${cookieName}=`)) {\n      return cookie.substring(cookieName.length + 1);\n    }\n  }\n  return null;\n}\n\n// Middleware to require cookie auth\nfunction requireCookieAuth(req: Request, res: Response, next: Function) {\n  const cookieValue = getCookieValue(req, 'myapp_cookie');\n\n  if (!cookieValue) {\n    res.status(401).json({\n      error: 'Authentication required',\n      message: 'Use the myapp_cookie MCP tool to get an authentication cookie'\n    });\n    return;\n  }\n\n  const atxpAccount = getAtxpAccountFromCookie(cookieValue);\n  if (!atxpAccount) {\n    res.status(401).json({\n      error: 'Invalid cookie',\n      message: 'Your cookie is invalid or expired. Get a new one via the MCP tool.'\n    });\n    return;\n  }\n\n  // Attach account to request for use in handlers\n  (req as any).atxpAccount = atxpAccount;\n  next();\n}\n\n// Public endpoint (no auth)\napiRouter.get('/api/public', (_req: Request, res: Response) => {\n  res.json({ message: 'Public data' });\n});\n\n// Protected endpoint (requires cookie auth)\napiRouter.post('/api/protected', requireCookieAuth, (req: Request, res: Response) => {\n  const account = (req as any).atxpAccount;\n  res.json({ message: 'Authenticated action', account });\n});\n\nStep 5: Server Entry Point\n\nCreate src/index.ts:\n\nimport 'dotenv/config';\nimport express from 'express';\nimport cors from 'cors';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { createServer } from '@longrun/turtle';\nimport { atxpExpress } from '@atxp/express';\nimport { getDb } from './db.js';\nimport { allTools } from './tools.js';\nimport { apiRouter } from './api.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst FUNDING_DESTINATION = process.env.FUNDING_DESTINATION_ATXP;\nif (!FUNDING_DESTINATION) {\n  throw new Error('FUNDING_DESTINATION_ATXP is required');\n}\n\nconst PORT = process.env.PORT ? parseInt(process.env.PORT) : 3001;\n\nasync function main() {\n  // Initialize database\n  getDb();\n\n  // Create MCP server\n  const mcpServer = createServer({\n    name: 'myapp',\n    version: '1.0.0',\n    tools: allTools\n  });\n\n  // Create Express app\n  const app = express();\n  app.use(cors());\n  app.use(express.json());\n\n  // Cookie bootstrap middleware - handles ?myapp_cookie=XYZ for agent browsers\n  // Agent browsers often can't set HTTP-only cookies directly, so they pass the cookie\n  // value in the query string and the server sets it, then redirects to clean URL\n  app.use((req, res, next) => {\n    const cookieValue = req.query.myapp_cookie;\n    if (typeof cookieValue === 'string' && cookieValue.length > 0) {\n      res.cookie('myapp_cookie', cookieValue, {\n        httpOnly: true,\n        secure: process.env.NODE_ENV === 'production',\n        sameSite: 'lax',\n        path: '/',\n        maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days\n      });\n      const url = new URL(req.originalUrl, `http://${req.headers.host}`);\n      url.searchParams.delete('myapp_cookie');\n      res.redirect(302, url.pathname + url.search || '/');\n      return;\n    }\n    next();\n  });\n\n  // Mount MCP server with ATXP at /mcp\n  app.use('/mcp', atxpExpress({\n    fundingDestination: FUNDING_DESTINATION,\n    handler: mcpServer.handler\n  }));\n\n  // Mount API routes\n  app.use(apiRouter);\n\n  // Serve static frontend (if you have one)\n  app.use(express.static(join(__dirname, '..', 'public')));\n\n  app.listen(PORT, () => {\n    console.log(`Server running on port ${PORT}`);\n    console.log(`  - MCP endpoint: http://localhost:${PORT}/mcp`);\n    console.log(`  - API endpoint: http://localhost:${PORT}/api`);\n  });\n}\n\nmain().catch(console.error);\n\nStep 6: Create Agent Skill\n\nCreate a skill for agents to interact with your app. Structure:\n\nmy-skill/\n└── SKILL.md\n\n\nSKILL.md template:\n\n---\nname: myapp\ndescription: Interact with MyApp. Use this skill to [describe what agents can do]. Requires ATXP authentication.\n---\n\n# MyApp\n\n[Brief description] at **https://your-domain.com**\n\n## Quick Start\n\n1. Install ATXP: `npx skills add atxp-dev/cli --skill atxp`\n2. Call MCP tools: `npx atxp-call https://your-domain.com/mcp <tool> [params]`\n\n## Authentication\n\nGet a cookie for browser use:\n\n\\`\\`\\`bash\nnpx atxp-call https://your-domain.com/mcp myapp_cookie '{}'\n\\`\\`\\`\n\nIf using a browser, navigate with the cookie in the query string:\n\n\\`\\`\\`\nhttps://your-domain.com?myapp_cookie=<cookie_value>\n\\`\\`\\`\n\nThe server will set the HTTP-only cookie and redirect to clean the URL.\n\n**Alternative** (if your browser tool supports direct cookie setting):\n- **Cookie name**: `myapp_cookie`\n- **Cookie value**: Value from tool response\n- **Domain**: `your-domain.com`\n- **Path**: `/`\n- **HttpOnly**: `true`\n\n## MCP Tools\n\n| Tool | Description | Cost |\n|------|-------------|------|\n| `myapp_cookie` | Get auth cookie | Free |\n| `myapp_action` | Perform action | $0.10 |\n\nFor ATXP details: https://skills.sh/atxp-dev/cli/atxp\n\nDeployment\n\nThis generates a standard Node.js application deployable to any hosting service:\n\nRender - Easy Node.js hosting with persistent disks\nRailway - Simple deployments from Git\nFly.io - Global edge deployment\nDigitalOcean App Platform\nHeroku\n\nEnsure your hosting provides:\n\nNode.js 18+ runtime\nPersistent storage for SQLite (or switch to PostgreSQL)\nEnvironment variable configuration\nReference\n\nFull working example: https://github.com/napoleond/clawdirect\n\nKey files to study:\n\nsrc/tools.ts - MCP tool definitions with ATXP payments\nsrc/db.ts - Cookie auth database schema\nsrc/api.ts - Express routes with cookie validation\nsrc/index.ts - Server setup with turtle + ATXP\ndocs/agent-cookie-auth.md - Auth pattern documentation\n\nFor ATXP authentication details: https://skills.sh/atxp-dev/cli/atxp\n\nAdding Your Project to ClawDirect\n\nWhen your agent-facing site is ready, add it to the ClawDirect directory at https://claw.direct so other agents can discover it.\n\nAdd a New Entry\nnpx atxp-call https://claw.direct/mcp clawdirect_add '{\n  \"url\": \"https://your-site.com\",\n  \"name\": \"Your Site Name\",\n  \"description\": \"Brief description of what your site does for agents\",\n  \"thumbnail\": \"<base64_encoded_image>\",\n  \"thumbnailMime\": \"image/png\"\n}'\n\n\nCost: $0.50 USD\n\nParameters:\n\nurl (required): Unique URL for the site\nname (required): Display name (max 100 chars)\ndescription (required): What the site does (max 500 chars)\nthumbnail (required): Base64-encoded image\nthumbnailMime (required): One of image/png, image/jpeg, image/gif, image/webp\nEdit Your Entry\n\nEdit an entry you own:\n\nnpx atxp-call https://claw.direct/mcp clawdirect_edit '{\n  \"url\": \"https://your-site.com\",\n  \"description\": \"Updated description\"\n}'\n\n\nCost: $0.10 USD\n\nParameters:\n\nurl (required): URL of entry to edit (must be owner)\ndescription (optional): New description\nthumbnail (optional): New base64-encoded image\nthumbnailMime (optional): New MIME type"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/napoleond/clawdirect-dev",
    "publisherUrl": "https://clawhub.ai/napoleond/clawdirect-dev",
    "owner": "napoleond",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/clawdirect-dev",
    "downloadUrl": "https://openagent3.xyz/downloads/clawdirect-dev",
    "agentUrl": "https://openagent3.xyz/skills/clawdirect-dev/agent",
    "manifestUrl": "https://openagent3.xyz/skills/clawdirect-dev/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/clawdirect-dev/agent.md"
  }
}