mcpField
X
x-mcp

x-mcp

github.com/starchild-ai-agent营销与增长3067 次安装6 天前更新
代码仓库

关于 x-mcp

x-mcp 是面向需要操作本人 X 账户的 Agent 技能,通过官方 X MCP 读取数据,并用用户自己的应用和 OAuth 凭据经 REST API 写入。读取与写入分属不同接口,凭据保存在本机。

主要功能

  1. 01通过 X MCP 搜索帖子、用户和趋势
  2. 02读取时间线、提及和书签
  3. 03通过 REST API 发布、回复和删除内容
  4. 04点赞、转发、关注及发送私信
  5. 05使用个人应用与 OAuth 凭据

适用场景

  1. 01搜索并查看本人 X 时间线与提及
  2. 02用本人账户发布帖子或回复
  3. 03点赞、转发或收藏帖子
  4. 04通过 X 发送私信

MCP 相关

使用官方托管 X MCP 提供 24 项读取工具;写入操作不通过 MCP,而是调用 X v2 REST API。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/starchild-ai-agent/official-skills --skill x-mcp

安装后在 Claude Code 中输入/x-mcp确认已加载。

附带文件scripts/oauth_driver.py

详细介绍

X API — MCP(读取)+ REST(写入),BYOK

连接用户自己的 X 开发者应用,让此 Agent 能够:

  • 通过官方托管的 X MCP(https://api.x.com/mcp)进行读取 — 24 个工具
  • 通过 X v2 REST API(https://api.x.com/2/...)进行写入 — 发帖 / 删除 / 点赞 / 转推 / 回复 / 私信

为什么采用 BYOK(而不是共享的 Starchild 应用): X 的写入访问按应用限流 (约整个应用级别的上限),按使用量计费并由应用所有者承担,且 TOS 责任归属于 应用所有者。共享应用 = 单点故障 + 邻居相互抢用 + 计费集中 + 内容审核责任。因此每个用户 自带应用 + OAuth 令牌。令牌只存在于本机(~/.xurl, 符号链接到持久化工作区 — 见步骤 3), 绝不经过代理。

何时使用此技能

当用户希望用自己的账号/应用在 X 上操作时使用:

  • “连接我的 X / Twitter 账号,好让你替我发帖”
  • “用我的开发者应用设置 X API”、“使用我的 X 开发者密钥”
  • “搜索最近的推文 / 读取我的时间线 / 读取提及”(用他们自己的应用)
  • “以我的身份在 X 上发帖 / 回复 / 点赞 / 转推 / 私信”
  • “收藏这条推文”

不要使用 — 改用正确的替代方案:

  • “总结这条推文” / “@user 在发什么” / cashtag 扫描,无需账号 → 使用 twitter 技能(通过 twitterapi.io 的只读抓取,无需 OAuth)
  • “添加 X / Grok 模型” → 那是 xai-grok-onboarding(聊天模型),无关
  • 用户没有 X 开发者应用且不想要 → twitter 技能,或说明 写入需要他们自己的应用

消歧:twitter = 只读、无需设置、任何人的公开推文。x-mcp = 用户自己已认证的账号,可以写入,需要一次性 OAuth 设置。

另见

  • twitter 技能 — 只读 X 抓取(无需账号、无需 OAuth),可获取任何公开推文
  • config/context/references/model-onboarding.md — 如果用户实际指的是聊天 模型(Grok),而非 X 数据 API

预检 — 构建兼容性(开始前检查)

此技能依赖两项平台能力。设置前请确认二者:

  1. 原生 MCP 客户端(读取所必需)。 starchild-clawd 必须包含 core/mcp/* 并从 agent.yaml 读取 defaults.mcp_servers。快速检查:运行 /mcp — 如果返回状态块,则客户端存在。如果 /mcp 未知或 报错,则运行的构建早于 MCP 支持 → 通过 MCP 的读取将不可用。REST 写入路径(xurl)仍然可用;或更新平台镜像。
  2. 逐轮热重载(自动刷新令牌所必需)。 需要它以便 ~2h 的令牌轮换自动重连(步骤 7)。没有它的构建仍可工作, 但每次刷新后需要手动 /mcp reload — 已在 步骤 7 中记录为回退方案。没有干净的运行时探测手段;假设当前构建 具备它,将“MCP 在刷新后约 2h 静默失效,只有 /mcp reload 能救活它”视为 该构建缺少逐轮钩子的信号。

如果两项 MCP 能力都不存在,而用户只需要读取公开推文, 请在此停止并改用 twitter 技能 — 它不需要任何构建支持。

读取 vs 写入 — 两个独立的系统

能力通道已验证
搜索帖子/用户/新闻、时间线、提及、趋势、书签MCP(24 个工具)已连接
发帖 / 删除 / 回复 / 点赞 / 转推 / 关注 / 私信REST /2/...(不在 MCP 中)发帖+删除已测试

MCP 的 tools/list 只返回 24 个读取/书签工具。写入端点是一个 独立的 REST API,文档在 docs.x.com — 它们无法通过 MCP 发现。它们列在本技能下文。


STEP 1 — 用户在 X 门户中创建 OAuth 2.0 凭据(手动;X 没有用于此操作的 API)

X 没有提供用于创建/配置应用的 API。这些步骤在 Web 门户中无法避免地需要手动完成。务必做到可精确复制粘贴。

  1. 前往 developer.x.com → 创建/打开一个应用。
  2. 默认显示的密钥(API Key / API Secret / Bearer Token)是 OAuth 1.0a —— 不是我们要用的。
  3. 应用 Settings 标签页 → User authentication settings → Set up。严格按如下填写:
    • App permissions: Read and write(如果用户需要私信,则加上 DM)
    • Type of App: Web App, Automated App or Bot → Confidential client(只有这个才会生成 Client Secret;Native/Public 不会生成)
    • Callback URI / Redirect URL: http://localhost:8080/callback(必须与 xurl 的监听器逐字节一致)
    • Website URL: https://iamstarchild.com(纯粹用于展示的元数据;不参与认证;不要求唯一 —— 每个用户都可以使用相同的值,没有任何技术影响)
  4. Save → X 会仅显示一次 Client ID + Client Secret。Secret 只显示一次;请立即复制。
这两个 URL 实际控制什么(以便你能回答用户)
  • Callback URI = X 返回 OAuth 授权码的位置。xurl 会在 localhost:8080 上启动一个本地监听器;授权码在用户自己的机器上从浏览器流向 xurl,绝不会经过任何外部服务器。两边必须完全一致,否则 X 会返回 redirect_uri_mismatch。
  • Website URL = 仅用于展示的元数据。不属于认证的一部分,也不校验唯一性。所有用户都可以安全地将其设置为 https://iamstarchild.com。

STEP 2 — 安全地收集凭据

request_env_input(绝不要在聊天中索要密钥):

  • X_OAUTH_CLIENT_ID — X App Client ID(OAuth 2.0)
  • X_OAUTH_CLIENT_SECRET — X App Client Secret(OAuth 2.0)

提醒用户:这是 OAuth 2.0 密钥对(在启用 User authentication settings + Confidential 之后),不是 API Key/Secret(1.0a),也不是 Bearer Token。

STEP 3 — 安装 xurl + 持久化凭据存储 + 注册应用

⚠️ 持久化是必需的,而不是可选的。 xurl 将应用注册和 OAuth token 两者都保存在 ~/.xurl(即 /root/.xurl)中。/root 是临时的 —— 每次容器重启都会被清空,因此如果不做这一步,用户会在下次重启时丢失连接(甚至连应用注册也会丢失),并且必须从头重新进行 OAuth。请将真实文件保存在持久化工作区中,并在每次启动时将其符号链接回来。xurl 会通过符号链接写入(已验证),因此每次 xurl 调用都会透明地使用持久化文件 —— 无需为每条命令添加 HOME 前缀。

npm install -g @xdevplatform/xurl          # validated v1.2.2

# Persist install + credential store across container restarts (idempotent).
# Append ONCE to workspace/setup.sh (which re-runs at every boot):
cat >> setup.sh <<'SH'
npm install -g @xdevplatform/xurl
# X (xurl) credential store: /root is ephemeral, keep ~/.xurl in the workspace
XURL_STORE=/data/workspace/.config/x-mcp/xurl_store
mkdir -p "$(dirname "$XURL_STORE")"; chmod 700 "$(dirname "$XURL_STORE")" 2>/dev/null || true
if [ -f /root/.xurl ] && [ ! -L /root/.xurl ]; then mv /root/.xurl "$XURL_STORE"; fi
ln -sf "$XURL_STORE" /root/.xurl
SH

# Run it now so the store is live for this session BEFORE registering the app:
XURL_STORE=/data/workspace/.config/x-mcp/xurl_store
mkdir -p "$(dirname "$XURL_STORE")"; chmod 700 "$(dirname "$XURL_STORE")" 2>/dev/null || true
if [ -f /root/.xurl ] && [ ! -L /root/.xurl ]; then mv /root/.xurl "$XURL_STORE"; fi
ln -sf "$XURL_STORE" /root/.xurl

xurl auth apps add starchild-x \
  --client-id "$X_OAUTH_CLIENT_ID" \
  --client-secret "$X_OAUTH_CLIENT_SECRET" \
  --redirect-uri "http://localhost:8080/callback"

xurl auth status      # confirm app registered, redirect_uri shows [app config]
ls -la /data/workspace/.config/x-mcp/xurl_store   # confirm store lives in workspace

STEP 4 中获得的 OAuth token 会落到同一个持久化文件中,因此一旦连接成功,该连接就能在重启后继续存活。(agent.yaml 的 MCP bearer 是独立的,并且已经位于工作区中;STEP 7 中的刷新任务会让两者保持同步。)

STEP 4 — 无头 OAuth(此机器没有浏览器 → 用户将 URL 粘贴回来)

xurl auth oauth2 --headless 会打印一个授权 URL,然后阻塞在 stdin 上,等待粘贴回来的授权码。该授权码绑定到一个只存在于该进程内存中的 PKCE code_verifier —— 如果进程在用户粘贴回来之前就终止了,该授权码就永远无法被交换。因此整个流程必须从“打印 URL”一直到“交换授权码”全程保持同一个 xurl 进程存活。

持久驱动模式

运行单个 Python 驱动,通过 subprocess.PIPE 保持 xurl 的 stdin 打开, 将授权 URL 写入文件,等待最多约 10 分钟以获取代码文件,然后输入 代码并捕获结果。关键结构:

proc = subprocess.Popen(["xurl","auth","oauth2","--app","starchild-x","--headless"],  # no USERNAME (see token-key note)
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0)
# 1) read stdout until the oauth2/authorize line → write it to /tmp/xurl_auth_url.txt
# 2) poll /tmp/xurl_code_input.txt (up to 600s) for the pasted callback URL/code
# 3) proc.stdin.write(code+"\n"); flush  → 4) read result → write /tmp/xurl_oauth_done.json

使用本技能附带的驱动,位于 skills/x-mcp/scripts/oauth_driver.py, 而不是内联重写它——这样可以保持无 USERNAME 启动和 600s 超时的一致性。启动它时要使其能存活超过 180s 的前台限制——将 stdout 重定向到文件,分离运行,不要让前台 bash 阻塞在它上面:

# clean any stale driver/xurl FIRST (see driver rule 1), then:
python3 skills/x-mcp/scripts/oauth_driver.py >/tmp/oauth_driver_console.log 2>&1 &
sleep 8
cat /tmp/xurl_auth_url.txt        # the URL THIS live driver just wrote — give the user THIS one
pgrep -f oauth_driver.py >/dev/null && echo "driver alive, waiting for code"

该驱动运行 xurl auth oauth2 --app starchild-x --headless(无 USERNAME 参数), 将授权 URL 捕获到 /tmp/xurl_auth_url.txt,等待最多 600s(约 10 分钟)以获取 /tmp/xurl_code_input.txt,输入代码,并将结果写入 /tmp/xurl_oauth_done.json。

令牌键 = 解析后的 X 账号句柄。 无论是否传入 USERNAME, xurl 都会通过 /2/users/me 解析账号,并将令牌存储在解析后的 X 账号句柄下(例如 oauth2_tokens['ud_noel']),而不是存储在空字符串键下。请 动态读取该键,而不是硬编码它。在所有读取令牌的地方都使用此辅助函数—— 它期望恰好一个令牌,如果发现多个,它会停止并列出 各账号句柄,以便你确认使用哪个账号或清除过期的令牌:

import yaml, os

def _xurl_token(app="starchild-x"):
    d = yaml.safe_load(open(os.path.expanduser("~/.xurl")))
    toks = d["apps"][app]["oauth2_tokens"]          # {'<handle>': {...}}
    keys = list(toks)
    if not keys:
        raise SystemExit(f"No OAuth token for app '{app}' — run STEP 4 first.")
    if len(keys) > 1:
        raise SystemExit(
            f"Multiple X accounts authorized under '{app}': {keys}. "
            "Confirm which handle to use (or remove stale tokens) before continuing.")
    return keys[0], toks[keys[0]]["oauth2"]          # (handle, {access_token, refresh_token, expiration_time})
OAuth 驱动规则
  1. 一次只运行一个驱动。 启动前,按精确 PID 终止任何过期的 xurl auth oauth2 / oauth_driver PID,并排除当前 shell。 此处避免使用 pkill -f oauth_driver.py——该模式也会匹配清理 命令自身的 shell。使用:
    SELF=$$
    for pat in "xurl auth oauth2" "oauth_driver.py"; do
      for pid in $(pgrep -f "$pat"); do [ "$pid" != "$SELF" ] && kill "$pid" 2>/dev/null; done
    done
    rm -f /tmp/xurl_auth_url.txt /tmp/xurl_code_input.txt /tmp/xurl_oauth_done.json /tmp/xurl_oauth.pid
    
  2. 只给用户正在运行的驱动刚刚写入的 URL——在此驱动启动后, 从 /tmp/xurl_auth_url.txt 读取它。绝不要粘贴来自 更早尝试或聊天历史的 URL。
  3. 如果你重启了,之前的授权 URL 就失效了。 告诉用户 丢弃它,只使用最新的那个。
  4. 如果交换失败,验证 state 是否匹配:用户粘贴的回调中的 state= 必须等于正在运行的驱动生成的 URL 中的 state=。不 匹配意味着该回调来自更早的授权 URL。

在可见回复中清楚地告诉用户:

  1. 在任意设备上的浏览器中打开 https://x.com/i/oauth2/authorize?... URL(正在运行的驱动写入的那个)。
  2. 点击 Authorize app。
  3. 浏览器会重定向到 http://localhost:8080/callback?state=...&code=...——该 页面将加载失败(它是这个远程机器的 localhost,用户的浏览器无法 访问它)。这是预期情况。代码就在地址栏中。
  4. 从地址栏复制完整的重定向 URL,并将其粘贴回聊天中。

将其提供给正在等待的驱动:

echo '<full redirected URL with code=>' > /tmp/xurl_code_input.txt

驱动将其交换为 ~/.xurl 中的令牌,并写入 /tmp/xurl_oauth_done.json。 警告 "could not resolve username via /2/users/me" 不是失败——那是下面的 注册陷阱。

第 5 步 — client-not-enrolled 注册门槛

xurl --app starchild-x /2/users/me 返回:

{"reason":"client-not-enrolled","title":"Client Forbidden",
 "detail":"...App that is attached to a Project..."}

OAuth 成功了,但该应用缺少 v2 API 访问权限。在门户中修复(手动):

  • 免费层级:在 Dashboard 中,你可以直接在免费应用上切换到按用量付费——这就会授予 v2 访问权限。所需的门槛是按用量付费 / 生产注册。按用量付费可能需要绑定一张卡。
  • 注册后,无需重新授权——token 会保留。只需重新运行测试即可。传播可能需要一两分钟。

验证:xurl --app starchild-x /2/users/me 必须返回用户对象(id、name、username),而不是 client-forbidden。

第 6 步 — 将 MCP 接入 agent.yaml(原生 MCP 客户端;无需改动 Agent 代码)

starchild-clawd 有一个原生 MCP 客户端(core/mcp/*:stdio / streamable-http / sse + 静态 headers)。在 defaults.mcp_servers: 下添加(或用户的 agent.yaml 中):

defaults:
  mcp_servers:        # MAPPING keyed by server name (NOT a YAML list)
    xmcp:
      transport: streamable-http
      url: https://api.x.com/mcp
      headers:
        Authorization: "Bearer <ACCESS_TOKEN_FROM_~/.xurl>"
      timeout: 30

mcp_servers 是一个映射(服务名 → 定义),而不是列表。列表形式(- name: xmcp)会被静默忽略(记录日志 must be a mapping, got list)。

然后运行 /mcp 以确认 24 个工具注册为 mcp__xmcp__<tool>。

第 7 步 — Token 过期与自动刷新

OAuth2 访问 token 约 2 小时后过期(offline.access scope 会授予 refresh_token,因此可以续期)。agent.yaml headers 中的 bearer 是静态的——没有任何东西会自动刷新 TOKEN 值。**如果你只是把当前 token 粘贴进 agent.yaml 而从不刷新,MCP 会在约 2 小时后失效。**你必须运行一个刷新循环来重写 bearer。(在当前 clawd 上,用新 bearer 重新连接是自动的——参见下文“当前 clawd 上的自动重载”——但 token 本身仍然必须被刷新并写入。)

用 xurl 刷新,然后在 agent.yaml 中重写 bearer(重新连接是自动的):

# read current access token after xurl refreshes it
xurl --app starchild-x /2/users/me >/dev/null 2>&1   # xurl auto-refreshes when near expiry on use
# read the token via the _xurl_token() helper from STEP 4 (single-token check + handle-keyed lookup)
ACCESS=$(python3 -c "
import yaml, os
d = yaml.safe_load(open(os.path.expanduser('~/.xurl')))
t = d['apps']['starchild-x']['oauth2_tokens']
keys = list(t)
assert len(keys) == 1, f'expected one X account, found {keys} — confirm/clean before refresh'
print(t[keys[0]]['oauth2']['access_token'])
")
# patch agent.yaml header to the fresh token (a small python/yaml rewrite).
# On current clawd that's all — the next chat turn auto-reconnects (see below).
刷新机制
  • 机密客户端刷新:POST https://api.x.com/2/oauth2/token,使用 HTTP Basic auth(base64(client_id:client_secret))和请求体 grant_type=refresh_token&refresh_token=<rt>。返回一个新的 access_token(expires_in 7200)以及一个新的轮换后的 refresh_token。
  • refresh_token 每次刷新都会轮换——旧的会被失效。你必须持久化新的 refresh_token(写回 ~/.xurl),否则下一次刷新会失败。
  • ✅ 优先使用 xurl 自身的按需刷新(xurl --app starchild-x /2/users/me):xurl 会在临近过期时刷新,并把轮换后的 token 写回 ~/.xurl 本身,通过符号链接(已验证)——持久化保持完好,你无需触碰该文件。
  • 🚫 如果你确实要自己写入 ~/.xurl,绝不要使用原子重命名写入(tempfile + os.replace/os.rename)。由于 ~/.xurl 是指向持久化工作区存储的符号链接(第 3 步),重命名会用一个位于临时 /root 中的普通文件替换该符号链接——持久化会悄无声息地失效,token 会在下次重启时消失。(这是 ChatGPT/Grok store.py 使用的标准“安全”模式——对真实文件是正确的,对符号链接则是致命的。)已验证:os.replace 会破坏符号链接;原地 open(path,"w") 和 xurl 都会通过它写入。因此只能原地写入:
    # safe: follows the symlink, lands in the persistent workspace store
    with open(os.path.expanduser("~/.xurl"), "w") as f:
        yaml.safe_dump(data, f)
    
在当前 clawd 上自动重新加载

当前 starchild-clawd 在每一轮 /chat 和 /chat/stream 的开始时调用 maybe_hot_reload()(受 mtime 门控,只需一次廉价的 stat)。因此,在刷新任务重写 agent.yaml 中的 bearer 之后,下一轮对话就会自动使用新 token 重新连接——用户永远不需要运行 /mcp reload。 MCP 服务配置签名包含排序后的 headers,因此 bearer 变更会被正确归类为重新连接。

因此,刷新任务只需做两件事:

  1. 刷新 token(Basic auth)并将轮换后的 refresh_token 持久化写入 ~/.xurl(就地写入或仅通过 xurl 写入——不要用原子重命名,参见上文符号链接警告),
  2. 将新的 access_token 写入 agent.yaml 的 headers.Authorization bearer(agent.yaml 已在工作区中,因此在那里用原子写入没问题)。

无需 /mcp reload,无需手动步骤。(计划任务本身无法重新加载连接——任务 run.py 是独立进程,无法访问进程内的 MCP 管理器单例——但也无需如此:每轮钩子会处理重新连接。)

没有每轮热重载的旧版 clawd 构建:如果运行的构建早于每轮 maybe_hot_reload() 调用,则实时连接不会采用新的 bearer,直到有人运行 /mcp reload——在这种情况下,让刷新任务额外触发一次重新加载,或者指示用户在每次约 2 小时的刷新后运行 /mcp reload。

将刷新设置为每约 60–90 分钟执行一次的 scheduled_task(token 有效期约 2 小时): 刷新 token(Basic auth)→ 将轮换后的 refresh_token 持久化到 ~/.xurl → 将新的 access_token 写入 agent.yaml 的 bearer。在当前 clawd 上,这完全自动。

Token 存储路径:~/.xurl → apps.starchild-x.oauth2_tokens['<resolved-handle>'].oauth2.{access_token,refresh_token,expiration_time}。 对应的键是 xurl 从 /2/users/me 解析出的 X handle(例如 'ud_noel'),不是空字符串——通过 STEP 4 中的 _xurl_token() 辅助函数动态读取(通常每个应用一个 token;该辅助函数会标记出现多个 token 的情况,以便你挑选/清理)。 ~/.xurl 是指向持久化路径 /data/workspace/.config/x-mcp/xurl_store 的符号链接(在 STEP 3 中设置)——照常读写 ~/.xurl;持久化是透明的。


REST 写入端点(不在 MCP 中——通过 xurl 使用同一 token 调用)

全部使用 OAuth2 bearer 认证。xurl 会自动处理认证和刷新:

操作方法 + 端点请求体 / 说明状态
发推文POST /2/tweets{"text":"..."}已测试
回复POST /2/tweets{"text":"...","reply":{"in_reply_to_tweet_id":"<id>"}}有文档
引用POST /2/tweets{"text":"...","quote_tweet_id":"<id>"}有文档
删除推文DELETE /2/tweets/{id}—已测试
点赞POST /2/users/{user_id}/likes{"tweet_id":"<id>"}有文档
取消点赞DELETE /2/users/{user_id}/likes/{tweet_id}—有文档
转推POST /2/users/{user_id}/retweets{"tweet_id":"<id>"}有文档
关注POST /2/users/{user_id}/following{"target_user_id":"<id>"}有文档
私信POST /2/dm_conversations/with/{participant_id}/messages{"text":"..."}有文档

示例(通过 xurl 发帖):

xurl --app starchild-x -X POST /2/tweets -d '{"text":"hello from my agent"}'

点赞/转推的 user_id = 已认证用户从 /2/users/me 获取的 id。 标记为“有文档”的端点来自 docs.x.com,尚未在此处进行完整的往返测试——首次实际使用时请验证并标记为已测试。

24 个 MCP READ 工具(注册为 mcp__xmcp__<tool>)

搜索/新闻:search_posts_all、search_news、get_news、search_users、 get_trends_by_woeid、get_posts_counts_recent。 帖子:get_posts_by_id、get_posts_by_ids、get_posts_liking_users、 get_posts_quoted_posts、get_posts_reposted_by。 用户:get_users_me、get_users_by_id、get_users_by_username、 get_users_by_usernames、get_users_timeline、get_users_posts、 get_users_mentions。 书签(偏写入):get_users_bookmarks、get_users_bookmarks_by_folder_id、 get_users_bookmark_folders、create_users_bookmark、create_users_bookmark_folder、 delete_users_bookmark。

常用参数:max_results、*.fields(逗号分隔列表)、expansions。search_posts_all 接受一个 query(支持 from:、min_faves:、$CASHTAG 等运算符)。


FAQ

  • "我只看到一个 OAuth 1.0a 应用 / 没有 Client ID。" 你还没有启用 User authentication settings。在你启用之前,Keys & tokens 只会显示 1.0a。见 STEP 1。
  • redirect_uri_mismatch。 Portal Callback URI ≠ http://localhost:8080/callback。 必须完全一致。
  • 没有提供 Client Secret。 应用的 Type 是 Native/Public。切换到 Confidential(Web App / Bot)。
  • OAuth 成功后出现 client-not-enrolled。 应用缺少 v2 访问权限 → 迁移到 Pay-per-use(STEP 5)。
  • 回调页面无法加载。 这是预期行为——它是远程机器的 localhost。授权 码在地址栏中;把完整 URL 粘贴回来。
  • MCP 可用,但约 2 小时后停止工作。 访问令牌已过期,agent.yaml 中的 bearer 已 失效。设置重写 bearer 的刷新任务(STEP 7)—— 在当前的 clawd 上,下一轮对话会自动重新连接,无需 /mcp reload。
  • 我可以通过 MCP 发帖吗? 不可以。写入通过 REST /2/... 进行(见表格)。MCP 仅 支持读取 + 书签。

关键规则

  • 绝不要将 access_token 或 refresh_token 回显到聊天中。 它们是 ~/.xurl 中的 持久凭证。展示配置时,请遮盖 bearer (Bearer S0tHdk…)。令牌绝不会经过代理或进入聊天记录。
  • 绝不要在聊天中索要 Client ID / Secret。 始终通过 request_env_input 收集(STEP 2)。
  • 不要自动轮询 / 催促 OAuth 步骤。 打印授权 URL 后,等待 用户表示已批准并将重定向 URL 粘贴回来。在用户粘贴之前就写入 授权码文件(/tmp/xurl_code_input.txt)只会让驱动程序 等待空输入。
  • 遇到 client-not-enrolled 时,不要盲目重试。 这是门户注册门槛 (STEP 5),不是临时错误——重试同样的调用会持续失败。引导 用户迁移到 Pay-per-use,然后重新测试一次。
  • 写入是 REST,不是 MCP。 不要寻找 create_post MCP 工具——它不 存在。请使用 REST 表格。
  • 令牌每次刷新都会轮换。 始终持久化新的 refresh_token,否则 下次刷新就会失败(STEP 7)。

更新策略(X 发生变化 → 升级此 skill)

当以下任何一项发生变化时,更新 + 升级版本(然后提 PR,绝不要直接推送 main):

  • MCP 工具集(新增/重命名/移除工具、schema 变更)→ MINOR
  • REST 写入端点(路径/请求体变更)→ MINOR,如果签名破坏则为 MAJOR
  • X 门户注册流程(Pay-per-use 的 UI/步骤、认证设置)→ PATCH/MINOR
  • xurl CLI 标志/行为 → PATCH/MINOR

独立性(仅 skill,无需更改 agent 代码)

此 skill 需要对 agent 代码不做任何更改。它依赖已是原生功能的 MCP 客户端(core/mcp/*)加上纯配置(agent.yaml 的 mcp_servers)和一个计划 刷新任务——全部由 agent 按照此 skill 编排。唯一的前提是 运行的构建版本包含 MCP 客户端。不使用用户自己的应用进行只读抓取 → 请改用 twitter skill。

已验证:xurl 1.2.2 · MCP 服务 xmcp 1.0.0(协议 2025-06-18)· 24 个工具 · access-level read-write-directmessages · 默认重定向 http://localhost:8080/callback。

评论

支持 Markdown