mcp应用程序验证器
验证MCP服务器是否支持UI扩展(SEP-1865):通过StreamableHTTP或SSE连接,发现 ui:// 资源,验证HTML内容、CSP、权限、显示模式、主题化、工具链接、优雅降级,测量延迟,并返回一个包含12个布尔类别和18个输入字段的结构化快照。
快速启动
git clone https://github.com/agentprobe/mcp-apps-validator.git
cd mcp-apps-validator
npm iimport { McpAppsValidator } from 'mcp-apps-validator'
const { status, messages, categories, entries } = await McpAppsValidator.start( {
endpoint: 'https://your-mcp-server.example.com/mcp',
timeout: 15000
} )特性
- 使用SSE回退通过StreamableHTTP连接到MCP服务器
- 发现
ui://通过以下方式链接资源和工具UI_meta.ui.resourceUri - 验证UI资源的HTML内容
- 检查CSP(内容安全策略)配置
- 验证权限声明
- 检测显示模式支持(嵌入式、面板、全屏、弹出)
- 检查主题/样式变量支持
- 验证非UI主机的文本回退是否优雅降级
- 将12个布尔类别(可达、MCP、MCP应用程序、UI资源、工具链接、主题、显示模式)分类
- 测量listResources和readResource延迟
- 比较两个快照并生成结构化差异
- 连接失败时返回包含所有错误类别的空快照
建筑
验证管道按六个顺序步骤处理MCP服务器:
flowchart LR
A[endpoint] --> B[McpAppsConnector.connect]
B --> C[McpAppsConnector.discover]
C --> D[UiResourceValidator.validate]
D --> E[CapabilityClassifier.classify]
E --> F[SnapshotBuilder.build]目录
- .start() - .compare()
方法
所有方法都是静态的。参数作为对象传递,返回值是对象。
.start()
连接到MCP服务器,发现UI资源,验证HTML内容、CSP、权限、显示模式、主题化、工具链接,测量延迟,并返回结构化快照。
方法
.start( { endpoint, timeout } )| 密钥 | 类型 | 描述 | 必填 |
|---|---|---|---|
| endpoint | string | MCP服务器的URL。示例 'https://server.example.com/mcp' | 是的 |
| timeout | number | 连接超时(毫秒)。默认 10000 | 没有 |
示例
import { McpAppsValidator } from 'mcp-apps-validator'
const { status, messages, categories, entries } = await McpAppsValidator.start( {
endpoint: 'https://your-mcp-server.example.com/mcp',
timeout: 15000
} )
console.log( `Status: ${status ? 'PASS' : 'FAIL'}` )
console.log( `UI Resources: ${entries['uiResourceCount']}` )
console.log( `MCP Apps: ${categories['supportsMcpApps']}` )
console.log( `Extension: ${entries['extensionVersion']}` )退货
{ status, messages, categories, entries }______________________________________________________________________
.compare()
比较由生成的两个快照 .start() 并返回一个结构化的diff,每个部分包含添加、删除和修改的项目。
方法
.compare( { before, after } )| 密钥 | 类型 | 描述 | 必填 |
|---|---|---|---|
| before | object | 以前的快照 .start() 电话。必须包含 categories 和 entries | 是的 |
| after | 对象 | 以后的快照 .start() 电话。必须包含 categories 和 entries | 是的 |
示例
import { McpAppsValidator } from 'mcp-apps-validator'
const before = await McpAppsValidator.start( { endpoint: 'https://server.example.com/mcp' } )
const after = await McpAppsValidator.start( { endpoint: 'https://server.example.com/mcp' } )
const { status, messages, hasChanges, diff } = McpAppsValidator.compare( { before, after } )
console.log( `Changes detected: ${hasChanges}` )
console.log( `UI resources added: ${diff['uiResources']['added'].length}` )
console.log( `UI resources removed: ${diff['uiResources']['removed'].length}` )退货
{ status, messages, hasChanges, diff }| 密钥 | 类型 | 描述 |
|---|---|---|
| 状态 | 布尔值 | true 比较完成时 |
| messages | 字符串数组 | 完整性警告(URL不匹配、时间戳问题) |
| hasChanges | 布尔值 | true 当任何差异部分发生变化时 |
| diff | object | 带节的结构化diff: server, uiResources, uiLinkedTools, csp, permissions, latency, categories |
分类
返回了12个布尔标志 categories:
| 密钥 | 描述 |
|---|---|
| isReachable | 服务器已响应连接尝试 |
| supportsMcp | MCP握手已完成 |
| 支持MCPApps | 服务器已 io.modelcontextprotocol/ui 扩展 |
| hasUiResources | 至少一个 ui:// 已发现资源 |
| hasUiToolLink | 至少有一个工具具有 _meta.ui.resourceUri |
| hasValidUiHtml | UI资源包含有效的HTML内容 |
| hasValidCsp | CSP配置存在于所有已验证的资源上 |
| 支持主题 | 支持主题/样式变量 |
| supportsDisplayModes | 已声明显示模式 |
| hasToolVisibility | 工具 _meta.ui.visibility 字段已使用 |
| hasValidPermissions | 未声明未知权限 |
| hasGracefulDegradation | 文本回退可用于非UI主机 |
条目
中返回了18个数据字段 entries:
| 密钥 | 类型 | 描述 |
|---|---|---|
| endpoint | string | 已验证的MCP服务器端点URL |
| serverName | string | 来自MCP握手的服务器名称 |
| 服务器版本 | 字符串 | 服务器版本 |
| 服务器描述 | 字符串 | 服务器描述 |
| protocolVersion | string | MCP协议版本 |
| extensionVersion | 字符串 | io.modelcontextprotocol/ui 扩展版本 |
| 功能 | 对象 | 原始服务器功能 |
| ui资源计数 | 数量 | 数量 ui:// 发现的资源 |
| UI资源 | 数组 | 具有uri、name、mimeType、hasCsp、hasPermissions、displayModes的UI资源 |
| uiLinkedToolCount | 数量 | 链接到UI资源的工具数量 |
| uiLinkedTools | array | 具有名称、资源URI和可见性的工具 |
| appOnly工具计数 | 数量 | 具有可见性的工具 ["app"] 只有 |
| cspSummary | 对象 | connectDomains, resourceDomains, frameDomains |
| permissionsSummary | array | 所有资源的聚合权限 |
| displayModes | array | 所有资源的聚合显示模式 |
| 工具 | 数组 | 所有已发现的工具 |
| resources | array | 所有已发现的资源 |
| 延迟 | 对象 | listResources 和 readResource 以毫秒为单位 |
| timestamp | string | ISO 8601验证时间戳 |
验证码
VAL——输入验证
| 代码 | 严重性 | 描述 |
|---|---|---|
| VAL-001 | 错误 | 端点:缺少值 |
| VAL-002 | 错误 | 端点:必须是字符串 |
| VAL-003 | 错误 | 端点:不能为空 |
| VAL-004 | 错误 | 端点:必须是有效的URL |
| VAL-005 | 错误 | 超时:必须是数字 |
| VAL-006 | 错误 | 超时:必须大于0 |
| VAL-010 | 错误 | 之前:缺少值 |
| VAL-011 | 错误 | 之前:必须是对象 |
| VAL-012 | 错误 | 之前:缺少类别或条目 |
| VAL-013 | 错误 | 之后:缺少值 |
| VAL-014 | 错误 | 之后:必须是对象 |
| VAL-015 | 错误 | 之后:缺少类别或条目 |
CON-MCP连接
| 代码 | 严重性 | 描述 |
|---|---|---|
| CON-001 | 错误 | 端点:无法访问服务器 |
| CON-004 | 错误 | mcp:初始化握手失败 |
| CON-008 | 警告 | 工具/列表:请求失败或响应格式无效 |
| CON-010 | 警告 | 资源/列表:请求失败 |
UIR-UI资源访问
| 代码 | 严重性 | 描述 |
|---|---|---|
| UIR-001 | 警告 | 资源/读取:资源读取失败 |
| UIR-002 | 警告 | 资源/阅读:预期文本/html内容 |
UIV-UI验证
| 代码 | 严重性 | 描述 |
|---|---|---|
| UIV-010 | 警告 | 缺少HTML内容 |
| UIV-011 | 警告 | HTML内容不是字符串 |
| UIV-012 | 警告 | HTML内容为空 |
| UIV-013 | 警告 | HTML内容似乎无效 |
| UIV-020 | 警告 | 未声明CSP配置 |
| UIV-021 | 警告 | CSP域应使用https://或wss:// |
| UIV-022 | 警告 | CSP包含通配符域 |
| UIV-030 | 警告 | 声明的权限未知 |
| UIV-031 | 警告 | 请求敏感权限 |
| UIV-040 | 信息 | 未知显示模式 |
| UIV-041 | 信息 | 未声明显示模式 |
| UIV-050 | 信息 | 未找到主题确认 |
| UIV-060 | 警告 | 工具引用了不存在的UI资源 |
| UIV-061 | 警告 | 工具的可见性值无效 |
| UIV-062 | 信息 | 没有链接到UI资源的工具 |
| UIV-063 | 信息 | 工具有UI元数据,但没有资源URI |
| UIV-070 | 信息 | 未发现优雅降级 |
| UIV-080 | 信息 | 未声明MCP应用程序扩展 |
| UIV-081 | 信息 | 未指定扩展版本 |
CMP——比较
| 代码 | 严重性 | 描述 |
|---|---|---|
| CMP-001 | 警告 | 快照来自不同的服务器 |
| CMP-002 | 警告 | 快照之前没有时间戳 |
| CMP-003 | 警告 | 快照后比以前旧 |
许可证
麻省理工学院
