名称: clawdirect-dev
描述: 基于 ATXP 认证构建面向 AI 代理的 Web 体验,遵循 ClawDirect 模式。适用于通过 MCP 工具与 AI 代理交互的网站、实现基于 Cookie 的代理认证,或为 Web 应用创建代理技能。提供使用 @longrun/turtle、Express、SQLite 和 ATXP 的模板。
基于 ATXP 认证构建面向 AI 代理的 Web 体验。
参考实现: https://github.com/napoleond/clawdirect
ATXP(代理交易协议)使 AI 代理能够进行身份验证并为服务付费。在构建面向代理的网站时,ATXP 提供:
ATXP 完整详情:https://skills.sh/atxp-dev/cli/atxp
代理通过两种方式与您的网站交互:
基于 Cookie 的认证模式连接了这两种方式:代理通过 MCP 获取认证 Cookie,然后在浏览时使用它。
重要提示:代理浏览器通常无法直接设置 HTTP-only Cookie。推荐模式是让代理在查询字符串中传递 Cookie 值(例如 ?myapp_cookie=XYZ),然后由服务器设置 Cookie 并重定向到干净的 URL。
┌──────────────────────────────────────────────────────────────────┐
│ AI 代理 │
│ ┌─────────────────────┐ ┌─────────────────────────┐ │
│ │ 浏览器工具 │ │ MCP 客户端 │ │
│ │ (访问网站) │ │ (调用工具) │ │
│ └─────────┬───────────┘ └───────────┬─────────────┘ │
└────────────┼─────────────────────────────────┼──────────────────┘
│ │
▼ ▼
┌────────────────────────────────────────────────────────────────┐
│ 您的应用程序 │
│ ┌─────────────────────┐ ┌─────────────────────────┐ │
│ │ Web 服务器 │ │ MCP 服务器 │ │
│ │ (Express) │ │ (@longrun/turtle) │ │
│ │ │ │ │ │
│ │ - 提供 UI │ │ - yourapp_cookie │ │
│ │ - Cookie 认证 │ │ - yourapp_action │ │
│ └─────────┬───────────┘ └───────────┬─────────────┘ │
│ │ │ │
│ └──────────┬─────────────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ SQLite │ │
│ │ auth_cookies │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
使用所需技术栈初始化 Node.js 项目:
mkdir my-agent-app && cd my-agent-app
npm init -y
npm install @longrun/turtle @atxp/server @atxp/express better-sqlite3 express cors dotenv zod
npm install -D typescript @types/node @types/express @types/cors @types/better-sqlite3 tsx
创建 tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
创建 .env:
FUNDING_DESTINATION_ATXP=<your_atxp_account>
PORT=3001
创建 src/db.ts:
import Database from 'better-sqlite3';
import crypto from 'crypto';
const DB_PATH = process.env.DB_PATH || './data.db';
let db: Database.Database;
export function getDb(): Database.Database {
if (!db) {
db = new Database(DB_PATH);
db.pragma('journal_mode = WAL');
// 认证 Cookie 表 - 将 Cookie 映射到 ATXP 账户
db.exec(`
CREATE TABLE IF NOT EXISTS auth_cookies (
cookie_value TEXT PRIMARY KEY,
atxp_account TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// 在此处添加您应用程序的其他表
}
return db;
}
export function createAuthCookie(atxpAccount: string): string {
const cookieValue = crypto.randomBytes(32).toString('hex');
getDb().prepare(`
INSERT INTO auth_cookies (cookie_value, atxp_account)
VALUES (?, ?)
`).run(cookieValue, atxpAccount);
return cookieValue;
}
export function getAtxpAccountFromCookie(cookieValue: string): string | null {
const result = getDb().prepare(`
SELECT atxp_account FROM auth_cookies WHERE cookie_value = ?
`).get(cookieValue) as { atxp_account: string } | undefined;
return result?.atxp_account || null;
}
创建 src/tools.ts:
import { defineTool } from '@longrun/turtle';
import { z } from 'zod';
import { requirePayment, atxpAccountId } from '@atxp/server';
import BigNumber from 'bignumber.js';
import { createAuthCookie } from './db.js';
// Cookie 工具 - 代理调用此工具以获取浏览器认证
export const cookieTool = defineTool(
'myapp_cookie', // 将 'myapp' 替换为您的应用名称
'获取用于浏览器的认证 Cookie。设置此 Cookie 以在使用 Web 界面时进行身份验证。',
z.object({}),
async () => {
// 免费但需要 ATXP 认证
const accountId = atxpAccountId();
if (!accountId) {
throw new Error('需要身份验证');
}
const cookie = createAuthCookie(accountId);
return JSON.stringify({
cookie,
instructions: '要在浏览器中进行身份验证,请导航至 https://your-domain.com?myapp_cookie=<cookie_value> - 服务器将设置 HTTP-only Cookie 并重定向。或者,如果您的浏览器工具支持,也可以直接设置 Cookie。'
});
}
);
// 示例付费工具
export const paidActionTool = defineTool(
'myapp_action',
'执行某些操作。费用:$0.10',
z.object({
input: z.string().describe('操作的输入')
}),
async ({ input }) => {
await requirePayment({ price: new BigNumber(0.10) });
const accountId = atxpAccountId();
if (!accountId) {
throw new Error('需要身份验证');
}
// 在此处添加您的操作逻辑
return JSON.stringify({ success: true, input });
}
);
export const allTools = [cookieTool, paidActionTool];
创建 src/api.ts:
import { Router, Request, Response } from 'express';
import { getAtxpAccountFromCookie } from './db.js';
export const apiRouter = Router();
// 提取 Cookie 的辅助函数
function getCookieValue(req: Request, cookieName: string): string | null {
const cookieHeader = req.headers.cookie;
if (!cookieHeader) return null;
const cookies = cookieHeader.split(';').map(c => c.trim());
for (const cookie of cookies) {
if (cookie.startsWith(`${cookieName}=`)) {
return cookie.substring(cookieName.length + 1);
}
}
return null;
}
// 要求 Cookie 认证的中间件
function requireCookieAuth(req: Request, res: Response, next: Function) {
const cookieValue = getCookieValue(req, 'myapp_cookie');
if (!cookieValue) {
res.status(401).json({
error: '需要身份验证',
message: '使用 myapp_cookie MCP 工具获取认证 Cookie'
});
return;
}
const atxpAccount = getAtxpAccountFromCookie(cookieValue);
if (!atxpAccount) {
res.status(401).json({
error: '无效的 Cookie',
message: '您的 Cookie 无效或已过期。请通过 MCP 工具获取新的 Cookie。'
});
return;
}
// 将账户附加到请求对象,供处理器使用
(req as any).atxpAccount = atxpAccount;
next();
}
// 公共端点(无需认证)
apiRouter.get('/api/public', (_req: Request, res: Response) => {
res.json({ message: '公共数据' });
});
// 受保护端点(需要 Cookie 认证)
apiRouter.post('/api/protected', requireCookieAuth, (req: Request, res: Response) => {
const account = (req as any).atxpAccount;
res.json({ message: '已认证的操作', account });
});
创建 src/index.ts:
import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { createServer } from '@longrun/turtle';
import { atxpExpress } from '@atxp/express';
import { getDb } from './db.js';
import { allTools } from './tools.js';
import { apiRouter } from './api.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const FUNDING_DESTINATION = process.env.FUNDING_DESTINATION_ATXP;
if (!FUNDING_DESTINATION) {
throw new Error('FUNDING_DESTINATION_ATXP 是必需的');
}
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3001;
async function main() {
// 初始化数据库
getDb();
// 创建 MCP 服务器
const mcpServer = createServer({
name: 'myapp',
version: '1.0.0',
tools: allTools
});
// 创建 Express 应用
const app = express();
app.use(cors());
app.use(express.json());
// Cookie 引导中间件 - 处理代理浏览器的 ?myapp_cookie=XYZ 请求
// 代理浏览器通常无法直接设置 HTTP-only Cookie,因此它们在查询字符串中传递 Cookie 值,
// 服务器设置 Cookie,然后重定向到干净的 URL
app.use((req, res, next) => {
const cookieValue = req.query.myapp_cookie;
if (typeof cookieValue === 'string' && cookieValue.length > 0) {
res.cookie('myapp_cookie', cookieValue, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 30 * 24 * 60 * 60 * 1000 // 30 天
});
const url = new URL(req.originalUrl, `http://${req.headers.host}`);
url.searchParams.delete('myapp_cookie');
res.redirect(302, url.pathname + url.search || '/');
return;
}
next();
});
// 在 /mcp 路径下挂载带有 ATXP 的 MCP 服务器
app.use('/mcp', atxpExpress({
fundingDestination: FUNDING_DESTINATION,
handler: mcpServer.handler
}));
// 挂载 API 路由
app.use(apiRouter);
// 提供静态前端文件(如果有)
app.use(express.static(join(__dirname, '..', 'public')));
app.listen(PORT, () => {
console.log(`服务器运行在端口 ${PORT}`);
console.log(` - MCP 端点: http://localhost:${PORT}/mcp`);
console.log(` - API 端点: http://localhost:${PORT}/api`);
});
}
main().catch(console.error);
为代理创建与您的应用交互的技能。结构如下:
my-skill/
└── SKILL.md
SKILL.md 模板:
---
名称: myapp
**描述:** 与 MyApp 交互。使用此技能来 [描述代理可以做什么]。需要 ATXP 认证。
---
# MyApp
[简要描述],网址:**https://your-domain.com**
## 快速开始
1. 安装 ATXP:`npx skills add atxp-dev/cli --skill atxp`
2. 调用 MCP 工具:`npx atxp-call https://your-domain.com/mcp <tool> [params]`
## 身份验证
获取用于浏览器的 Cookie:
\`\`\`bash
npx atxp-call https://your-domain.com/mcp myapp_cookie '{}'
\`\`\`
如果使用浏览器,请在查询字符串中包含 Cookie 进行导航:
\`\`\`
https://your-domain.com?myapp_cookie=<cookie_value>
\`\`\`
服务器将设置 HTTP-only Cookie 并重定向以清理 URL。
**替代方案**(如果您的浏览器工具支持直接设置 Cookie):
- **Cookie 名称**:`myapp_cookie`
- **Cookie 值**:工具响应中的值
- **域名**:`your-domain.com`
- **路径**:`/`
- **HttpOnly**:`true`
## MCP 工具
| 工具 | 描述 | 费用 |
|------|-------------|------|
| `myapp_cookie` | 获取认证 Cookie | 免费 |
| `myapp_action` | 执行操作 | $0.10 |
ATXP 详情:https://skills.sh/atxp-dev/cli/atxp
这将生成一个标准的 Node.js 应用程序,可部署到任何托管服务:
确保您的托管服务提供:
- Node.js 18+ 运行时
- SQLite 的持久化存储(或切换到 PostgreSQL)
- 环境变量配置
完整工作示例:https://github.com/napoleond/clawdirect
需要研究的关键文件:
- src/tools.ts - 包含 ATXP 支付的 MCP 工具定义
- src/db.ts - Cookie 认证数据库模式
- src/api.ts - 包含 Cookie 验证的 Express 路由
- src/index.ts - 使用 turtle + ATXP 的服务器设置
- docs/agent-cookie-auth.md - 认证模式文档
ATXP 认证详情:https://skills.sh/atxp-dev/cli/atxp
当您的面向代理的网站准备就绪后,将其添加到 https://claw.direct 的 ClawDirect 目录中,以便其他代理可以发现它。
npx atxp-call https://claw.direct/mcp clawdirect_add '{
"url": "https://your-site.com",
"name": "您的网站名称",
"description": "关于您的网站为代理提供功能的简要描述",
"thumbnail": "<base64_encoded_image>",
"thumbnailMime": "image/png"
}'
费用:$0.50 USD
参数:
- url(必需):网站的唯一 URL
- name(必需):显示名称(最多 100 个字符)
- description(必需):网站功能的描述(最多 500 个字符)
- thumbnail(必需):Base64 编码的图像
- thumbnailMime(必需):image/png、image/jpeg、image/gif、image/webp 之一
编辑您拥有的条目:
npx atxp-call https://claw.direct/mcp clawdirect_edit '{
"url": "https://your-site.com",
"description": "更新后的描述"
}'
费用:$0.10 USD
参数:
- url(必需):要编辑的条目的 URL(必须是所有者)
- description(可选):新描述
- thumbnail(可选):新的 Base64 编码图像
- thumbnailMime(可选):新的 MIME 类型