ui票mcp
人工智能代码审查桥梁。 直接在浏览器中查看UI原型,然后让AI代理读取您的反馈并自动修复代码。
你点击元素,写评论,比如“这个按钮应该是蓝色的”或“这里的间距错了”,你的AI编码代理(Claude Code、Codex、Cursor等)通过MCP拾取它们并解析它们——并提供你指向的元素、CSS、位置和周围DOM的完整上下文。
运作原理
journey
title Using ui-ticket-mcp
section Review
Open your app in browser: 5: You
Click on a broken element: 4: You
Write what's wrong: 5: You
section AI resolves
Agent reads your feedback: 3: AI
Agent finds the source file: 4: AI
Agent fixes the code: 5: AI
Review disappears: 5: You, AI一个Python进程处理所有事务-代理的MCP协议(stdio)和浏览器UI的REST API(HTTP)。评论存储在项目中的SQLite数据库中。
______________________________________________________________________
快速开始
1.连接到您的AI代理
添加到您的项目 .mcp.json (克劳德代码、法典、光标等):
{
"mcpServers": {
"ui-ticket-mcp": {
"command": "uvx",
"args": ["ui-ticket-mcp"],
"env": {
"PROJECT_ROOT": "/path/to/your/project",
"REVIEW_PORT": "3200"
}
}
}
}重新启动代理。 uvx 自动下载并运行软件包,无需手动安装。
备选方案:pip install ui-ticket-mcp,然后使用"command": "ui-ticket-mcp"而不是uvx.
当MCP服务器启动时,它还启动上的REST API http://localhost:3200 (或你的习惯 REVIEW_PORT)对于浏览器UI。
重要提示: API始终运行 本地 (localhost).网站https://uiticket.0ics.ai/仅为登录页-它不是API端点。始终使用http://localhost:{PORT}/api随着api-url.
2.将浏览器UI添加到您的应用程序中
npm install ui-ticket-panel在应用程序的入口文件中(例如。 main.ts, index.tsx):
import { defineReviewPanel } from 'ui-ticket-panel';
defineReviewPanel();然后在根模板中:
就是这样。工作在 任何框架 -Angular、React、Vue、Svelte或纯HTML。这是一个标准的Web组件。对于 安全部门改革框架 (Next.js、Nuxt、SvelteKit)见 框架示例 部分——您需要在客户端进行动态导入。
没有邦德勒?使用CDN
捆绑包自动注册 `` 元素。无需安装npm,也不需要构建步骤。
3.开始复习
在浏览器中打开您的应用程序。您将在右下角看到一个浮动聊天按钮。单击它打开查看面板,或按 Alt+A 进入注释模式并直接单击元素。
______________________________________________________________________
浏览器UI功能
评审小组
浮动面板允许您浏览、筛选和管理所有评论:
- 筛选器选项卡 -在打开、已解决和所有评论之间切换
- 搜索 -在所有评论中进行全文搜索
- 标签过滤器 -按类别筛选:一般、错误、建议、问题
- 每次审查行动 -解析、重新打开、删除、回复、突出显示元素
- 线程回复 -回复来回讨论的评论
- 人工审核表 -撰写无注释的评论(Ctrl+Enter可提交)
- 徽章计数器 -浮动按钮显示打开的评论数
注释系统
注释系统允许您指向特定元素并为其附加评论:
- 单击以添加注释 -按Alt+A(或目标按钮),然后单击任何元素
- 多选拖动 -单击并拖动以选择包含多个元素的区域
- 悬停预览 -移动鼠标时实时查看元素标识
- 智能弹出窗口 -根据可用空间,显示在元素上方或下方
当你注释一个元素时,系统会捕获丰富的元数据,帮助AI代理准确理解你所指向的内容:
| 捕获的数据 | 示例 |
|---|---|
| 元素名称 | Button 'Save', Input[email] 'Your email', Heading 2 'Features' |
| CSS选择器 | #main-header, div.card > button.primary:nth-of-type(2) |
| 边界框 | 位置和尺寸(像素) |
| 附近的文本 | 自己的文本+上一个/下一个兄弟文本作为上下文 |
| 选定文本 | 如果在注释之前突出显示文本 |
| CSS类 | 已过滤(不包括框架生成的哈希) |
| 计算样式 | 颜色、背景、字体、边框、填充(智能按元素类型) |
| 完整DOM路径 | body > div#app > section.content > div.card > button |
| 可访问性 | ARIA角色、标签、tabindex、可聚焦性 |
| 兄弟姐妹上下文 | 父标记、子计数、相邻兄弟姐妹标记 |
标记徽章
带有注释的评论会在注释元素旁边的页面上显示编号的徽章:
- 单项审核 -带有审核ID的圆形徽章,红色(打开)或绿色(已解决)
- 堆积如山的评论 (同一元素上3+)-药丸徽章显示计数,渐变显示打开/解析比率
- 点击徽章 -在面板中打开评论
- 删除徽章 -通过悬停时的X按钮删除
- 工具提示 -悬停以查看作者、元素名称和评论预览
标签
每条评论都可以标记一个类别:
| 标签 | 颜色 | 用途 |
|---|---|---|
general | Indigo | 常规反馈(默认) |
bug | 红色 | 有东西坏了 |
suggestion | 绿色 | 改进理念 |
question | 琥珀色 | 需要澄清 |
键盘快捷键
| 快捷方式 | 操作 |
|---|---|
| Alt+A | 切换注释模式 |
| Ctrl+Enter | 提交审核或回复 |
| 逃脱 | 关闭弹出/退出注释模式 |
______________________________________________________________________
建筑
graph LR
Agent[AI Agent]
Browser[Reviewer - Browser]
Server[ui-ticket-mcp]
DB[(SQLite)]
Agent |stdio MCP| Server
Browser |HTTP REST :3200| Server
Server --- DB- 主控程序 (stdio)-您的代理框架会自动启动它。AI代理阅读、解决和管理评论的10个工具。
- REST API (HTTP:3200)-在后台启动,提供浏览器审查UI。所有来源都启用了CORS。
- SQLite (WAL模式)-并发读卡器+1个写入器,5s忙超时。数据库位于您的项目中
.reviews/reviews.db.
______________________________________________________________________
MCP工具
AI代理可用的10个工具:
get_review_summary()
所有带有评论计数的页面概述。
Page | Open | Resolved | Total
------------ | ---- | -------- | -----
user-profile | 3 | 1 | 4
dashboard | 0 | 2 | 2get_reviews(page_id?: str)
列出审核意见。可选择按页面过滤。显示状态、标记、元素上下文和回复链。
[#1] [OPEN] [bug] user-profile - alice: The header spacing is off
→ Element: Heading 2 'User Profile' | Selector: h2.page-title
[#2] [RESOLVED] user-profile - bob: Button color should be blueget_annotated_reviews(page_id?: str)
仅返回具有元素注释元数据的评论。包括元素名称、CSS选择器、完整DOM路径、选定文本、可访问性信息——代理定位和理解注释元素所需的一切。
get_pending_work()
所有打开的评论都按页面分组——代理的“待办事项列表”。
## user-profile (2 open)
- #1 [bug] (alice): The header spacing is off
- #3 [suggestion] (alice): Add hover state to buttons
## dashboard (1 open)
- #4 (bob): Chart labels are truncatedadd_review(page_id, author, text, tag?, metadata?, parent_id?)
创建新评论。支持标签、注释元数据(JSON)和线程 parent_id.
resolve_review(review_id, resolved_by?)
将审核标记为已解决。集合 resolved_at 时间戳和 resolved_by (默认为 "agent").
reopen_review(review_id)
重新打开以前已解决的审核。清除分辨率信息。
batch_resolve(page_id, resolved_by?)
一次解决页面上所有打开的评论。退货 Resolved 3 review(s) on user-profile.
find_source_file_tool(page_id)
在以下位置查找源文件 PROJECT_ROOT 匹配页面ID。按烤肉串、驼峰和球状图案搜索。跳绳 node_modules, dist, .git.
Found 3 file(s) for 'user-profile':
- src/app/user-profile/user-profile.component.ts
- src/app/user-profile/user-profile.component.html
- src/app/shared/UserProfile.tsget_setup_guide()
返回完整的设置指南(MCP配置、REST API、浏览器UI)。当代理需要帮助在新项目中建立审查系统时很有用。
典型的代理工作流程
graph TD
A["get_pending_work()"] -->|See what needs attention| B["get_annotated_reviews(page)"]
B -->|Get element metadata for context| C["find_source_file_tool(page)"]
C -->|Locate the source files| D["Read & edit the code"]
D --> E{Resolve}
E -->|Single| F["resolve_review(id)"]
E -->|All on page| G["batch_resolve(page)"]______________________________________________________________________
REST API
以下所有端点 /api所有来源均已启用.CORS。
评论
| 方法 | 端点 | 描述 | |||
|---|---|---|---|---|---|
| 得到 | /api/reviews/summary | 每页摘要,包括打开/已解决的计数 | |||
| 得到 | /api/reviews | 所有评论(最新者优先) | |||
| 得到 | /api/reviews/{page_id} | 对页面的评论。查询: `?status=open\ | resolved, ?tag=bug\ | suggestion\ | ...` |
| 职位 | /api/reviews/{page_id} | 创建评论 | |||
| 补丁 | /api/review/{id} | 更新审查(状态、文本、标签、元数据) | |||
| 删除 | /api/review/{id} | 永久删除评论 |
回复
| 方法 | 端点 | 描述 |
|---|---|---|
| 得到 | /api/review/{id}/replies | 获取评论的所有回复(按时间顺序) |
| 职位 | /api/reviews/{page_id} | 创建回复(包括 parent_id 体内) |
帖子正文
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
text | string | - | 评论(必填) |
author | 字符串 | "anonymous" | 审阅者姓名 |
tag | 字符串 | "general" | "general", "bug", "suggestion",或 "question" |
metadata | object | - | 注释上下文(元素、选择器、样式等) |
parent_id | integer | - | 线程回复的父审阅ID |
补片体
| 字段 | 类型 | 描述 | |
|---|---|---|---|
status | "open" | "resolved" | 解析自动设置 resolved_at 和 resolved_by |
text | string | 已更新的注释文本 | |
tag | string | 已更新标记 | |
resolved_by | string | 谁解决了它(默认值: "user" 通过API, "agent" 通过MCP) | |
metadata | object | 已更新注释元数据 |
______________________________________________________________________
数据库
评论存储在项目中的SQLite中 {PROJECT_ROOT}/.reviews/reviews.db。数据库在首次运行时自动创建。
这 .reviews/ 目录包括:
| 文件 | 目的 |
|---|---|
reviews.db | SQLite数据库(提交git与您的团队分享评论) |
.gitkeep | 确保目录被跟踪 |
.gitignore | 忽略WAL临时文件(*.db-wal, *.db-shm) |
路径分辨率:
REVIEW_DB_PATHenv-var(显式重写)PROJECT_ROOT/.reviews/reviews.db(默认)./reviews.db(回退)
模式
reviews (
id INTEGER PRIMARY KEY,
page_id TEXT NOT NULL,
author TEXT DEFAULT 'anonymous',
text TEXT NOT NULL,
status TEXT DEFAULT 'open', -- 'open' | 'resolved'
created_at TEXT NOT NULL, -- ISO 8601
resolved_at TEXT,
resolved_by TEXT,
metadata TEXT, -- JSON: annotation context
tag TEXT DEFAULT 'general', -- 'general' | 'bug' | 'suggestion' | 'question'
parent_id INTEGER REFERENCES reviews(id) -- threaded replies
)注释元数据(JSON)
当通过注释创建评论时 metadata 字段包含:
{
"element": "Button 'Save'",
"selector": "button.btn-primary",
"boundingBox": { "x": 100, "y": 200, "width": 80, "height": 40 },
"selectedText": "Click to save",
"cssClasses": "btn btn-primary active",
"nearbyText": "Save your work | [after:] Cancel",
"nearbyElements": "Parent: form.editor (5 children) | Siblings: input, button.secondary",
"computedStyles": "color: #fff, background: #3b82f6, border-radius: 4px",
"fullPath": "body > div#app > div.modal > form > button",
"accessibility": "role=\"button\", tabindex=\"0\", focusable",
"isMultiSelect": false,
"url": "http://localhost:4200/user-profile"
}此元数据为AI代理提供了关于您注释内容的精确上下文——哪个元素、它在哪里、它是什么样子,以及如何在DOM中找到它。
______________________________________________________________________
Web组件属性
| 属性 | 必填 | 描述 |
|---|---|---|
api-url | 是 | REST API基本URL(例如。 http://localhost:3200/api) |
page-id | 否 | 用于筛选评论的显式页面标识符。如果省略,则使用自动检测(推荐) |
页面标识
面板需要知道用户所在的页面,以便显示和归档该特定页面的评论。有两种模式:
自动检测(推荐)
当否 page-id 如果设置了属性,面板将从URL路径名中导出页面标识符:
| URL | 页面ID |
|---|---|
/ | home |
/analytics | analytics |
/settings | settings |
/user/profile | user/profile |
该面板还监听SPA导航事件(pushState, replaceState, popstate)并在路线改变时自动重新加载评论。这意味着它可以在React Router、Vue Router、Angular Router、Next.js等客户端路由中开箱即用。
显式页面ID
如果您需要自己控制页面ID(例如,您的页面不能清晰地映射到URL路径),请设置 page-id 属性:
重要提示: 这两种模式是相互排斥的。当 page-id 设置后,自动检测完全禁用——面板不会对路线更改做出反应。不要把两者结合起来。程序化API
const panel = document.querySelector('review-panel');
// Change page without reloading
panel.setPageId('dashboard');______________________________________________________________________
包裹
| 包 | 注册表 | 描述 |
|---|---|---|
ui-ticket-mcp | PyPI | Python MCP服务器+REST API |
ui-ticket-panel | npm | `` Web组件 |
ui-ticket-core | npm | Framework-agnostic核心:类型、API客户端、反应存储、注释引擎 |
______________________________________________________________________
环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
PROJECT_ROOT | - | 审查项目的根源。DB自动创建于 {PROJECT_ROOT}/.reviews/ |
REVIEW_DB_PATH | (自动) | 显式数据库路径覆盖。优先考虑 PROJECT_ROOT |
REVIEW_PORT | 3200 | REST API服务器的端口 |
______________________________________________________________________
框架示例
与邦德勒
在您的参赛档案中(例如。 main.ts, main.js):
import { defineReviewPanel } from 'ui-ticket-panel';
defineReviewPanel();然后在HTML中:
纯HTML(无打包器/CDN)
反应
import { defineReviewPanel } from 'ui-ticket-panel';
defineReviewPanel();
function App() {
return ;
}Vue
import { defineReviewPanel } from 'ui-ticket-panel';
defineReviewPanel();
Angular
// app.config.ts
import { defineReviewPanel } from 'ui-ticket-panel';
defineReviewPanel();
// component - add CUSTOM_ELEMENTS_SCHEMA
@Component({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: ``
})斯维尔特
import { defineReviewPanel } from 'ui-ticket-panel';
defineReviewPanel();
Next.js(SSR)
Web组件使用 window 和 HTMLElement 这些在服务器端渲染过程中不存在。您必须在客户端动态加载面板:
// components/ReviewPanel.tsx
'use client';
import { useEffect } from 'react';
export default function ReviewPanel() {
useEffect(() => {
import('ui-ticket-panel').then(m => m.defineReviewPanel());
}, []);
return ;
}然后在根布局中使用它:
// app/layout.tsx
import ReviewPanel from './components/ReviewPanel';
export default function RootLayout({ children }) {
return (
{children}
);
}Nuxt(SSR)
import { onMounted } from 'vue';
onMounted(async () => {
const { defineReviewPanel } = await import('ui-ticket-panel');
defineReviewPanel();
});
SvelteKit(SSR)
import { onMount } from 'svelte';
onMount(async () => {
const { defineReviewPanel } = await import('ui-ticket-panel');
defineReviewPanel();
});
______________________________________________________________________
问题与反馈
发现错误或有功能请求? 打开一个问题 在这个存储库上。
______________________________________________________________________
许可证
CC BY-NC 4.0-免费用于学习、研究和非商业用途。看 许可证 了解详情。
______________________________________________________________________
建造于 西蒙Cmar, 拉迪斯拉夫·索普科 & 洛伦佐 莱昂尼
