mcpField
T
tyrekick

tyrekick

本地服务
github.com/richardofortune开发工具32 周前更新

关于 tyrekick

Tyrekick 为原型页面提供访客反馈组件,让审阅者直接在页面元素上留言,供编码 Agent 获取并处理。反馈带有元素文本、标题和页面错误等上下文,处理后可标记为已解决。

主要功能

  1. 01在页面元素上固定评论
  2. 02收集带上下文的反馈
  3. 03通过 MCP 获取并处理评论
  4. 04解决评论并更新标记
  5. 05评论抽屉与草稿恢复
  6. 06支持自有存储端点

适用场景

  1. 01收集原型页面的审阅意见
  2. 02让编码 Agent 根据反馈修复问题
  3. 03查看页面错误及对应反馈
  4. 04将评论发送到自有存储端点

MCP 相关

Tyrekick 的 MCP 服务提供列出、获取、分类、解决反馈及统计工具。编码 Agent 可从配置的 Worker 获取评论并将其标记为已解决。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"richardofortune-tyrekick": {
"command": "npx",
"args": [
"-y",
"tyrekick-mcp"
],
"env": {
"TYREKICK_URL": "<TYREKICK_URL>",
"TYREKICK_TOKEN": "<TYREKICK_TOKEN>"
}
}
}
}
启动命令npx -y tyrekick-mcp
需要配置的环境变量
TYREKICK_URLBase URL of your deployed Tyrekick feedback worker (e.g. https://tyrekick-feedback.you.workers.dev)
TYREKICK_TOKEN密钥Bearer token for the worker's management routes (set via `wrangler secret put TYREKICK_TOKEN`)

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmtyrekick-mcp0.3.1

工具

6

收录的工具列表 · 更新于 3 周前

参数类型必填说明
limitinteger否返回条目数上限(worker 默认值为 50,最大值为 200)
routestring否仅返回此 route 上留下的反馈
sincestring否仅返回在此 ISO-8601 时间戳当日或之后创建的反馈
statusenum否仅返回具有此 status 的反馈(open = 尚未分类)open | approved | declined | resolved
projectstring否仅返回此 project_name 的反馈(一个 worker 可服务多个项目)

详细介绍

Tyrekick

发布前先试试。 邀请你信任的人评审由 AI 构建的原型,再让你的编码 Agent 根据他们的反馈采取行动。

npm 版本 gzip 大小 许可证:MIT MCP 服务

评审者可直接在实时页面上固定评论,无需账户,也无需培训。你的编码 Agent 通过 MCP 获取这些评论,并附上对应的确切元素、可见文本、所在部分的标题以及任何页面错误;它会修复标记的问题,并将其标记为已解决。评审者的标记会变绿,并附上备注。你再也不必把反馈重新输入提示词了。

评审者在实时演示页面上固定评论;Agent 通过 MCP 读取评论、提交修复、附上备注并标记为已解决——评审者的标记随即变绿。

▶ 试用在线演示  ·  快速入门  ·  文档  ·  “外层循环”——为何要打造它

真实演示:这条评论固定在实时演示页面上,由 Agent 修复后,标记变绿——无需重新输入反馈、无需跟踪工具、无需账户。

工作原理

 reviewer's browser              destination YOU own              your coding agent
┌──────────────────┐   POST    ┌────────────────────┐    MCP    ┌─────────────────┐
│ pin a comment on │ ────────► │ Discord webhook or │ ◄───────► │ "fix the open   │
│ the live page    │           │ your CF Worker     │           │  feedback"      │
└──────────────────┘           └────────────────────┘           └─────────────────┘

这个小组件是一个仅约 14 KB(gzip 压缩后)的脚本,零依赖,并在 Shadow DOM 中渲染,不会与你的页面产生冲突。Tyrekick 没有后端,也没有账户,更不会向任何地方发送数据——反馈会直接从评审者的浏览器 POST 到你拥有的目的地。它旨在满足这样的需求:由 Agent 构建的原型需要更多人来审视。你不必把截图贴进群聊后眼看回复淹没其中,每条评论都会以结构化、带版本信息的形式送达,并固定在确切位置。

发表评论后,标记会留在页面上(在你与之交互前会变暗)。悬停在标记上可查看评论,点击即可就地打开讨论串,并在标记处显示回复、重试和丢弃操作。评审者还可以使用评论抽屉(右侧的概览列表,列出每个标记及其评论文本——点击即可跳回对应位置,也可以完全隐藏标记)、恢复草稿,以及完整的键盘和触摸操作支持(按 Cmd/Ctrl+Enter 发送)。启用 persist: true(默认值)时,localStorage 仅用于在重新加载后恢复尚未发送的内容——未能送达的评论会在重新加载后恢复,并带有“重试”和“丢弃”按钮;即使窗口大小发生变化,评论也会重新固定到对应元素上。

Agent: 要将 Tyrekick 安装到项目中?使用 make-reviewable 技能——只需一句话,它就会在需要时托管页面、选择目的地、部署 worker、安装小组件、连接 MCP,并起草要发送给评审者的邀请;也可以按照 AGENTS.md 逐步操作。

完整文档位于 docs/ 中:快速入门 · 开始使用 · 配置 · 评审者体验 · 目的地 · Agent 工作流 · 载荷参考 · 故障排查与常见问题

要公开分享原型? 请先阅读公开原型,然后查看各项功能指南:速率限制 · 共享评审 · AI 自动回复。

60 秒快速入门(Discord)

最快的方式是使用一个由你管理的 Discord 频道——先体验一下反馈流向你掌控的位置。完整产品(持久化、状态,以及你的 Agent 通过 MCP 完成反馈闭环)见下文的工作器目标端。

一条命令(在项目文件夹中运行):

npx tyrekick init

命令会提示你输入 webhook URL,注入脚本标签,并发送一条测试评论。也可以手动操作:

  1. 在 Discord 中,打开服务器设置 → 集成 → Webhook → 新建 Webhook,选择一个频道,然后点击复制 Webhook URL。
  2. 将该 URL 粘贴到下面的代码片段中,并将其放在原型中 </body> 之前:
<script
  src="https://cdn.jsdelivr.net/npm/tyrekick@latest/dist/tyrekick.js"
  data-webhook="https://discord.com/api/webhooks/XXXX/YYYY"
  data-app-version="v0.1"
  data-transport="discord"
  data-project-name="My Prototype"
  data-accent="#4f46e5"
  data-position="bottom-right"
  data-branding="true"
></script>

IIFE 构建会在 DOMContentLoaded 时,根据自身 <script> 标签的 data-* 属性自动初始化。评审者会在角落看到“提供反馈”按钮;每条评论都会以易读的消息形式发送到你的 Discord 频道。

只有 data-webhook 和 data-app-version 是必填项。其他配置均为可选,并使用配置表中的默认值。

自托管 / 自有存储

Discord 是最省事的默认选项,但如果你希望将数据存储在自己掌控的存储空间中,请使用指向持久化该载荷的端点的 JSON 传输方式(transport: "json",默认值)。

  • Cloudflare 模板(TypeScript): 请参阅 destinations/cloudflare,其中提供了可部署的 Worker,用于接收 v2 载荷、验证载荷,并将其写入你掌控的存储空间。由于代码由你掌控,这里也很适合添加垃圾信息验证。
  • 同源 Pages Function: 如果你的原型托管在 Cloudflare Pages 上,可在同一来源部署 Pages Function(例如 /api/feedback),并将 webhook 设为该相对 URL 或同源 URL。同源意味着完全无需配置 CORS。

任何启用了 CORS 的端点或表单后端也都可以使用——采用 transport: "json" 时,成功条件为 HTTP 2xx;如果返回了响应正文,则不能是 {"ok":false}。

Agent 工作流(MCP)

这就是 Tyrekick 存在的意义。使用 Cloudflare Worker 目标端后,反馈不只是被收集起来——你的编码 Agent 还可以拉取反馈、采取行动并解决问题:

  1. 部署 Worker 并设置令牌(参见 destinations/cloudflare):
    wrangler deploy && wrangler secret put TYREKICK_TOKEN
    
  2. 将工作流交给你的 Agent(只需一次——此后每次会话都适用):
    claude mcp add tyrekick \
      --env TYREKICK_URL=https://tyrekick-feedback.YOUR.workers.dev \
      --env TYREKICK_TOKEN=your-token \
      -- npx tyrekick-mcp
    
  3. 用一句话完成闭环:

    “列出未处理的反馈,修复大家指出的问题,然后将其标记为已解决。”

Agent 可以使用五种工具——list_feedback、get_feedback、triage_feedback、resolve_feedback、feedback_stats——每条反馈都包含元素的可见文本(可在源码中用 grep 查找)、最近的标题、路由、视口,以及任何未捕获的页面错误。像 “这个按钮点了没反应” 这样的评论会以如下形式收到:

element: <button> "Search trips"
under: "Plan your escape" · landmark: main > section#planner
page_errors: 1
> This button does nothing when I click it

这比大多数人写的 Bug 报告都更好。完整详情见 mcp/README.md。

共享审阅(审阅者可以看到彼此的评论)

默认情况下,审阅由多个私密对话组成:每位审阅者只能看到自己的标记,评论会发送到你的目标位置。设置审阅密钥后,页面本身就会成为共享空间——所有人都能看到彼此的标记,且只能查看,并附有署名。这样审阅者就不用把同一件事重复报告四遍了。

npx wrangler secret put TYREKICK_REVIEW_KEY   # on your worker; any long random string
<script
  src="https://cdn.jsdelivr.net/npm/tyrekick@latest/dist/tyrekick.js"
  data-webhook="https://your-worker.workers.dev/feedback"
  data-app-version="v0.1"
  data-project-name="my-prototype"
  data-review-key="the-same-long-random-string"
></script>

启用前请先阅读。 密钥会随页面一起发布,因此持有审阅链接的任何人都能看到它:任何能打开原型的人都能阅读其上的所有评论,包括审阅者姓名。 对于发送给五位可信人士的私密链接,这是合适的取舍;对于公开 URL,则不合适。没有按审阅者身份进一步限定访问范围的方式——审阅者永远无需登录,这正是设计初衷。轮换密钥即可撤销访问权限。

它的功能与限制:

  • 只读。 你可以查看并回复其他审阅者的评论;回复会像其他评论一样发送到你的目标位置,而非审阅者之间直接互通。没有实时在线状态,也没有审阅者之间的页面内评论串。
  • 拒绝即隐藏。 你拒绝的评论(通过 MCP 或 API)会从所有人的页面消失——这就是清除垃圾和无关内容的方式。评论作者仍可在自己的标记上看到处理结果。
  • 按项目隔离。 一个 worker 可以服务多个原型;审阅密钥只会读取指定的 projectName。请设置明确且稳定的 projectName——如果依赖 document.title 回退值,第一次修改标题时,你的反馈流就会被拆分。
  • 仅限 Worker。 Discord 按设计仅支持写入,没有共享视图。
  • **其他审阅者永远看不到的内容:**你的 User-Agent、屏幕或设备指纹、原型的页面错误、完整 URL(共享链接可能包含查询字符串密钥),或你的会话 ID。

AI 自动回复(可选)

在 worker 上设置 Anthropic API 密钥后,每条接收的评论都会收到一条简短、友好的确认回复——标记为 🤖,且只显示在审阅者自己的评论串中——同时标记保持打开状态(它只会确认收到;绝不会声称已修复任何问题,也不会解决标记)。模型没有工具,因此评论中的任何内容都无法让它执行操作。默认关闭。

npx wrangler secret put ANTHROPIC_API_KEY

编程式 / ESM 用法

从你的注册表安装并显式初始化(ESM 构建不会自动初始化):

npm install tyrekick
import { init, destroy } from "tyrekick";

init({
  webhook: "https://discord.com/api/webhooks/XXXX/YYYY",
  appVersion: "v0.1",
  projectName: "My Prototype",
  transport: "discord",
});

// later, to tear down all DOM, listeners, and in-memory state:
destroy();

全局(IIFE)等效调用为 window.Tyrekick.init(config) / window.Tyrekick.destroy()。未先调用 destroy() 而连续调用两次 init() 不会执行任何操作,并会发出警告;缺少 webhook 或 appVersion 会抛出错误。

框架 / 异步加载(Next.js、React、打包工具)

IIFE 构建会通过 document.currentScript 读取自身的 <script> 标签并自动初始化。只要标签是异步注入的(Next.js next/script、由 React 渲染的 <script>,或任何动态加载器),该值就会是 null,因此普通 CDN 标签可能会悄然无法启动。支持以下两种方式:

  1. 设置全局变量(适用于任何加载器)。在 widget 脚本运行前定义:

    <script>window.tyrekickConfig = { webhook: "…", appVersion: "1.0" }</script>
    

    IIFE 构建会依次读取 window.tyrekickConfig、自身的 data-*,然后回退到 DOM 中任意已有的 <script data-webhook>。

  2. 从客户端组件调用 init()(推荐用于 Next.js App Router / React):

    "use client";
    import { useEffect } from "react";
    
    export function TyrekickWidget() {
      useEffect(() => {
        let cleanup: (() => void) | undefined;
        import("tyrekick").then(({ init, destroy }) => {
          init({ webhook: "…", projectName: "…", appVersion: "…" });
          cleanup = destroy;
        });
        return () => cleanup?.();
      }, []);
      return null;
    }
    

配置

TyrekickConfig 的所有字段(参见 src/types.ts):

字段类型必填默认值描述
webhookstring是—接收 POST 请求的目标 URL。
appVersionstring是—正在审核的原型版本字符串。
projectNamestring否document.title项目的易读名称。
position"bottom-right" | "bottom-left"否"bottom-right"触发按钮所在角落。
accentstring否"#FFC53D"触发器、标记和发送按钮的强调色。强调色上的文本会自动调整对比度(浅色强调色使用深色文字,深色强调色使用白色)。
theme"auto" | "light" | "dark"否"auto"小组件的配色方案。"auto" 会在初始化时遵循访客的 prefers-color-scheme,并在其变化时实时更新。对于自动初始化构建,请在 script 标签上使用 data-theme。
brandingboolean否true显示“由 Frontier Operations 打造”页脚。
fields{ name?: boolean }否{ name: true }切换可选的审核者姓名输入框。
transport"json" | "discord"否"json"负载的传递方式(原始 JSON 或 Discord 消息)。
persistboolean否true仅使用 localStorage 进行未发送内容的恢复:草稿文本和发送失败、重载后仍需重试的评论。已提交的评论不会保存在 localStorage 中。设为 false 时,不会读取或写入任何存储键。
reviewKeystring否—共享审核(可选启用):每位审核者都能看到其他所有审核者的标记,但只能查看。必须与 Worker 上的 TYREKICK_REVIEW_KEY 匹配。该密钥会随页面一起发布,因此任何拥有审核链接的人都能读取所有评论——适用于私密链接,不适用于公开 URL。参见共享审核(审核者可相互查看)。
captureErrorsboolean否true记录页面未捕获的错误 / 未处理的拒绝(通过 window 的 "error" 和 "unhandledrejection" 监听器——不会修改控制台),并将最近的 ≤5 条附加到每个负载中,作为 page_errors。对于自动初始化构建,请在 script 标签上设置 data-capture-errors="false"。无论此标志为何值,任何地方都不会捕获输入的值。

负载架构(v2)

使用 transport: "json" 时,POST 到你的 webhook 的原始请求体格式恰好如下(FeedbackPayload):

{
  "schema": 2,
  "id": "b1c2...",
  "created_at": "2026-07-02T10:15:30.000+12:00",
  "project_name": "My Prototype",
  "app_version": "v0.1",
  "route": "/pricing?ref=x#plans",
  "url": "https://example.com/pricing?ref=x#plans",
  "body": "This button is hard to find.",
  "reviewer_name": "Sam",
  "session_id": "9f8e...",
  "anchor": {
    "x_pct": 42.3,
    "y_pct": 71.8,
    "selector": "main > section.pricing > button.cta",
    "viewport": { "w": 1440, "h": 900 },
    "element": {
      "tag": "button",
      "id": "buy-now",
      "testid": "pricing-cta",
      "role": null,
      "text": "Start free trial",
      "label": "Start your free trial",
      "rect": { "x": 612, "y": 484, "w": 216, "h": 44 }
    },
    "context": {
      "heading": "Pricing plans",
      "landmark": "main > section#pricing"
    }
  },
  "env": {
    "user_agent": "Mozilla/5.0 ...",
    "language": "en-US",
    "screen": { "w": 1512, "h": 982 },
    "dpr": 2,
    "dark": false,
    "touch": false
  },
  "page_errors": ["TypeError: prices is undefined"]
}

字段说明:

  • schema 始终为 2。id 和 session_id 均为 UUID(id 对应每条评论,session_id 在每次页面加载时生成一次)。
  • created_at 为带时区的 ISO-8601 格式。route 为 location.pathname + search + hash;url 为 location.href。
  • body 是去除首尾空白的评论文本;reviewer_name 为 string | null。
  • anchor.x_pct / anchor.y_pct 是点击时相对于文档尺寸的百分比,保留 1 位小数。anchor.selector 是点击位置所在宿主页面最深层元素的尽力匹配 CSS 选择器(最多 5 段),也可能为 null——绝不会指向工具自身的节点。
  • anchor.element 用于标识被点击的元素,方便编码 Agent 将反馈映射回源代码:小写的 tag、id / data-testid(testid)/ role 属性(或 null)、可见的 text(去除首尾空白、合并空白,≤80 个字符;为空时为 null)、label(aria-label → alt → placeholder → title,≤80 个字符),以及点击时相对于视口的边界 rect(整数 px)。无法解析元素时为 null。**隐私:**对于 input/textarea/select,text 始终为 null——绝不会捕获表单值。
  • anchor.context 以结构化方式标明点击位置:heading 是最近标题的文本(h1–h6,沿祖先节点及其前置兄弟节点向上查找,≤80 个字符);landmark 是最多包含 3 个地标祖先的粗略路径(main、nav、header、footer、aside、section、article、form),最内层在最后,例如 "main > section#pricing"。未找到时两者均为 null;采集过程绝不会抛出异常。
  • env 会添加物理 screen 尺寸(CSS px)、dpr(devicePixelRatio,保留 2 位小数)、dark(prefers-color-scheme: dark)和 touch(pointer: coarse)。
  • page_errors 是本次页面加载中最近发生的 ≤5 个未捕获错误 / 未处理的 Promise 拒绝(每条 ≤200 个字符,按时间从旧到新排列),通过 window 监听器收集——不会修改 console。若没有错误或 captureErrors: false,则为 []。

使用 transport: "discord" 时,此负载会改为格式化为易读的 Discord 消息({ content }),并将其 POST。

限制

这是一个有意设计为零后端的工具,因此也存在一些取舍:

  • 回执只会在 worker 路径上形成闭环。 使用 Cloudflare 目标时,解决评论会将审阅者的标记变为绿色,并附上解决说明;Discord 为只写入,不支持回读。
  • 默认情况下,评审内容按浏览器隔离。 两位审阅者各自只能看到自己的标记,看不到对方的;评论会汇总到目标位置,而不是显示在页面上。共享评审 可在 worker 路径上启用另一种行为,但代价是任何拥有链接的人都能读取所有评论。
  • 没有截图或会话回放。 只会发送上述 JSON 负载——不含图片、不采集 DOM、不录制内容。结构化的元素 / 上下文采集是有意采用的替代方案。
  • 垃圾信息。 公开的 webhook 可能收到垃圾内容——这是无需后端和把关机制所要付出的代价。可以将 transport: "json" 指向 Cloudflare 模板,并在那里添加验证 / 速率限制;也可以发送到只有审阅者能够访问的私有 Discord 频道。请参阅 docs/destinations 中基于托管方式的决策表。

贡献

npm run build   # build dist/tyrekick.js (IIFE) + dist/tyrekick.esm.js (ESM)
npm test        # unit tests (vitest)
npm run e2e     # end-to-end tests (playwright)

请将 src/types.ts 保留为唯一事实来源——未经架构版本升级,不要重命名负载键或配置字段。

**重新渲染本 README 顶部的演示 GIF:**运行 node scripts/record-demo.mjs,即可在一次性本地 worker 上录制完整流程并重新编码。请参阅 scripts/README.md——录制过程由 scripts/record-demo.mjs 中的脚本控制(可调整)。

由 Frontier Operations 打造

Tyrekick 是 Frontier Operations 的品牌载体:这是一款真正实用的开源工具,让收集原型反馈变得毫无阻碍,同时践行我们看重的一项原则——评审者的评论绝不会经由我们传递。整个流程中没有 Frontier 后端,也不会有任何数据回传;反馈会从评审者的浏览器直接发送到你掌控的目的地。这是一款免费提供的实用软件,也在不经意间展现了我们的构建理念。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。