Skip to main content
Glama

Tactual

屏幕阅读器导航成本分析器。用于衡量辅助技术用户在网页上发现、到达和操作交互式目标点的难度。

功能概述

现有的无障碍工具主要检查合规性——ARIA 是否正确?对比度是否足够?

Tactual 衡量的是导航成本——屏幕阅读器用户需要多少次操作才能到达结账按钮?如果他们操作过头了会发生什么?他们甚至能发现该按钮的存在吗?

它的工作原理是捕获 Playwright 无障碍快照,构建导航图,并根据辅助技术配置文件对每个目标点进行评分。

安装

# For CLI usage
npm install tactual playwright

# For MCP server usage (AI tools)
npm install tactual playwright @modelcontextprotocol/sdk

Playwright 和 @modelcontextprotocol/sdk 是可选的对等依赖项。CLI 和页面分析需要 Playwright。运行 tactual-mcp 服务器需要 MCP SDK。如果您仅将库 API 用于预捕获的状态,则无需安装这两者。

快速入门

CLI

# Analyze a URL (default profile: generic-mobile-web-sr-v0)
tactual analyze-url https://example.com

# Analyze with a specific AT profile
tactual analyze-url https://example.com --profile voiceover-ios-v0

# Explore hidden UI (menus, tabs, dialogs, disclosures)
tactual analyze-url https://example.com --explore

# Output as JSON, Markdown, or SARIF
tactual analyze-url https://example.com --format json --output report.json
tactual analyze-url https://example.com --format sarif --output report.sarif

# Compare two analysis runs
tactual diff baseline.json candidate.json

# List available AT profiles
tactual profiles

# Run benchmark suite
tactual benchmark

# Initialize a tactual.json config file
tactual init

库 API

import { analyze, getProfile } from "tactual";
import { captureState } from "tactual/playwright";
import { chromium } from "playwright";

const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto("https://example.com");

const state = await captureState(page);
await browser.close();

const profile = getProfile("generic-mobile-web-sr-v0");
const result = analyze([state], profile);

for (const finding of result.findings) {
  console.log(finding.targetId, finding.scores.overall, finding.severity);
}

MCP 服务器

Tactual 包含一个供 AI 代理使用的 MCP 服务器:

# Start the MCP server (stdio transport — default)
tactual-mcp

# Start with HTTP transport (for hosted platforms, remote clients)
tactual-mcp --http              # listens on http://127.0.0.1:8787/mcp
tactual-mcp --http --port=3000  # custom port (or set PORT env var)
tactual-mcp --http --host=0.0.0.0  # bind to all interfaces (default: 127.0.0.1)

可用的 MCP 工具:

工具

描述

analyze_url

分析网页的 SR 导航成本。默认格式为 sarif。支持 waitForSelectorwaitTimeminSeverityfocusexcludeSelectorexcludemaxFindingssummaryOnlytimeoutstorageState 参数。分析结果包含 Playwright 定位器选择器。传入 probe: true 可进行键盘探测。传入 includeStates: true 可获取用于离线 trace_path 的捕获状态。

trace_path

追踪到特定目标点的分步导航路径。显示每次操作、成本和模拟的 SR 播报。接受目标 ID 或 glob 模式(例如 *search*)。传入来自先前 analyze_urlstatesJson 可跳过浏览器启动过程。支持用于已认证页面的 storageState

list_profiles

列出可用的 AT 配置文件

diff_results

比较两个分析结果。显示已解决/新增的惩罚项、严重性变化以及每个目标点的状态。

suggest_remediations

按影响程度排序的修复建议。对于 SARIF 输出是多余的(修复建议已内联)。

save_auth

对 Web 应用进行身份验证并保存会话状态。将输出文件路径作为 storageState 传递给其他工具,以分析已认证的内容。

analyze_pages

在一次调用中分析多个页面并进行站点级聚合。每页返回约 200 字节。适用于在深入分析单个页面之前的站点分类。

通过 AI 工具设置

首先在您的项目中安装所需的包:

npm install tactual playwright @modelcontextprotocol/sdk

Claude Code — 添加到项目根目录的 .mcp.json 中:

{
  "mcpServers": {
    "tactual": {
      "type": "stdio",
      "command": "npx",
      "args": ["tactual-mcp"]
    }
  }
}

GitHub Copilot — 添加到 .copilot/mcp.json~/.copilot/mcp-config.json

{
  "mcpServers": {
    "tactual": {
      "type": "stdio",
      "command": "npx",
      "args": ["tactual-mcp"]
    }
  }
}

Cursor / Windsurf / Cline — 在编辑器的 MCP 配置中使用相同格式:

{
  "mcpServers": {
    "tactual": {
      "command": "npx",
      "args": ["tactual-mcp"]
    }
  }
}

直接安装(全局安装) — 如果您不想使用 npx:

npm install -g tactual playwright
tactual-mcp  # starts the MCP server on stdio

GitHub Actions

使用 GitHub Actions Marketplace 中的组合操作:

jobs:
  a11y:
    runs-on: ubuntu-latest
    steps:
      - name: Analyze accessibility
        uses: tactual-dev/tactual@v0.2.1
        with:
          url: https://your-app.com
          explore: "true"
          fail-below: "70"

该操作会安装 Tactual 和 Playwright,运行分析,将 SARIF 上传到 GitHub 代码扫描,如果平均分低于阈值,则构建失败。输出 average-scoreresult-file 供后续步骤使用。

或者直接使用 CLI 以获得更多控制权:

- name: Install Tactual
  run: npm install tactual playwright

- name: Install browsers
  run: npx playwright install chromium --with-deps

- name: Run accessibility analysis
  run: npx tactual analyze-url https://your-app.com --format sarif --output results.sarif --threshold 70

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: results.sarif

配置

CLI 标志

Options:
  -p, --profile <id>              AT profile (default: generic-mobile-web-sr-v0)
  -f, --format <format>           json | markdown | console | sarif (default: console)
  -o, --output <path>             Write to file instead of stdout
  -d, --device <name>             Playwright device emulation
  -e, --explore                   Explore hidden branches
  --explore-depth <n>             Max exploration depth (default: 3)
  --explore-budget <n>            Max exploration actions (default: 50)
  --explore-max-targets <n>       Max accumulated targets before stopping (default: 2000)
  --exclude <patterns...>         Exclude targets by name/role glob
  --exclude-selector <css...>     Exclude elements by CSS selector
  --focus <landmarks...>          Only analyze within these landmarks
  --suppress <codes...>           Suppress diagnostic codes
  --top <n>                       Show only worst N findings
  --min-severity <level>          Minimum severity to report
  --threshold <n>                 Exit non-zero if avg score < N
  --config <path>                 Path to tactual.json
  --no-headless                   Headed browser (for bot-blocked sites)
  --timeout <ms>                  Page load timeout (default: 30000)
  --probe                         Run keyboard probes (focus, activation, Escape, Tab)
  --wait-for-selector <css>       Wait for selector before capturing (for SPAs)
  --wait-time <ms>                Additional wait after page load
  --storage-state <path>          Playwright storageState JSON for authenticated pages
  --summary-only                  Return only summary stats, no individual findings
  -q, --quiet                     Suppress info diagnostics

tactual.json

使用 tactual init 创建或手动创建:

{
  "profile": "voiceover-ios-v0",
  "exclude": ["easter*", "admin*", "debug*"],
  "excludeSelectors": ["#easter-egg", ".admin-only", ".third-party-widget"],
  "focus": ["main"],
  "suppress": ["possible-cookie-wall"],
  "threshold": 70,
  "priority": {
    "checkout*": "critical",
    "footer*": "low",
    "analytics*": "ignore"
  }
}

配置会自动从工作目录(tactual.json.tactualrc.json)检测。CLI 标志会与配置设置合并并覆盖它们。

AT 配置文件

配置文件

平台

描述

generic-mobile-web-sr-v0

移动端

标准化移动端 SR 原语(默认)

voiceover-ios-v0

移动端

iOS Safari 上的 VoiceOver — 基于转子的导航

talkback-android-v0

移动端

Android Chrome 上的 TalkBack — 阅读控件

nvda-desktop-v0

桌面端

Windows 上的 NVDA — 浏览模式快捷键

jaws-desktop-v0

桌面端

Windows 上的 JAWS — 带有自动表单模式的虚拟光标

配置文件定义了每个导航操作的成本、评分维度权重、costSensitivity(缩放可达性衰减曲线)以及依赖于上下文的修饰符。有关实现细节,请参阅 src/profiles/

评分

每个目标点都会收到一个 5 维评分向量

维度

衡量内容

可发现性 (Discoverability)

用户能否判断目标点是否存在?

可达性 (Reachability)

到达该处所需的导航成本是多少?

可操作性 (Operability)

控件的行为是否可预测?

恢复性 (Recovery)

从操作过头中恢复的难度如何?

互操作风险 (Interop Risk)

AT/浏览器支持差异的可能性有多大?(惩罚项)

维度权重因配置文件而异:

配置文件

D

R

O

Rec

costSensitivity

generic-mobile-web-sr-v0

0.30

0.40

0.20

0.10

1.0

voiceover-ios-v0

0.30

0.35

0.20

0.15

1.1

talkback-android-v0

0.25

0.45

0.20

0.10

1.3

nvda-desktop-v0

0.35

0.25

0.30

0.10

0.7

jaws-desktop-v0

0.30

0.25

0.35

0.10

0.6

综合评分: 加权几何平均值:overall = exp(sum(w_i * ln(score_i)) / sum(w_i)) - interopRisk。在取对数之前,每个维度至少为 1,以避免 log(0)。这意味着任何维度的零分都会严重拖累总分——你无法操作你无法到达的东西。

严重性等级:

分数

等级

含义

90-100

低关注度

75-89

可接受

可改进

60-74

中等

应进行分类处理

40-59

可能存在明显的摩擦

0-39

严重

可能存在阻塞

诊断

Tactual 会在分析可能不可靠时进行检测并报告:

代码

级别

含义

blocked-by-bot-protection

错误

检测到 Cloudflare/机器人挑战

empty-page

错误

未找到任何目标点

possibly-degraded-content

警告

对于 http 页面来说目标点数量异常少

sparse-content

警告

仅找到 1-4 个目标点

possible-login-wall

警告

身份验证受限内容(检测到 /login/signin/auth 路径重定向)

possible-cookie-wall

信息

Cookie 同意弹窗可能遮挡了内容

redirect-detected

警告

跳转到了不同的域名

no-headings

警告

未找到标题元素

no-landmarks

警告

未找到地标区域

探索

--explore 标志可激活有界分支探索:

  • 打开菜单、选项卡、披露框、手风琴和对话框

  • 从隐藏的 UI 中捕获新的无障碍状态

  • 将发现的目标点标记为 requiresBranchOpen

  • 遵守深度、操作次数、目标点数量和新颖性预算

  • 安全操作策略会阻止破坏性交互

探索对于具有大量隐藏 UI(例如下拉菜单、选项卡式界面、模态对话框)的页面非常有用。

探索候选对象在迭代前按稳定键(角色 + 名称)排序,因此相同的内容在多次运行中会产生相同的探索顺序。

探索预算

预算

CLI 标志

默认值

用途

深度

--explore-depth

3

最大递归深度

操作

--explore-budget

50

所有分支的总点击预算

目标点

--explore-max-targets

2000

如果累计目标点超过此值则停止

时间

(仅限库)

120s

全局挂钟超时

SPA 框架检测

Tactual 会在捕获无障碍树之前检测 SPA 内容是否已渲染。检测到的框架:React、Next.js、Vue、Nuxt、Angular、Svelte 和 SvelteKit。还会检查通用的 HTML5 内容信号(地标、标题、导航、链接)。对于自动检测未覆盖的 SPA,请使用 --wait-for-selector (CLI) 或 waitForSelector (MCP/API) 来指定指示您的应用已水合的 CSS 选择器。

在初始框架检测后,Tactual 使用基于收敛的轮询——重复对无障碍树进行快照,直到目标点数量稳定——这适用于任何框架。

互操作风险

Tactual 包含从 a11ysupport.ioARIA-AT 项目 导出的 ARIA 角色/属性支持数据的静态快照。具有已知跨 AT/浏览器支持差距的角色会受到互操作风险惩罚。

角色

风险

注意

button, link, heading

0

支持良好

dialog

5

焦点管理各异

combobox

8

最具互操作性问题的模式

tree

10

在 JAWS 之外支持较差

application

15

滥用时很危险

输出格式建议

格式

典型大小

最佳用途

console

~8KB

终端中的人工审查

markdown

~11KB

PR 和议题评论

json

~18KB

程序化消费

sarif

~4-40KB

GitHub 代码扫描 / CI

所有非 SARIF 格式都会发出汇总输出:统计信息、分组问题和最差发现(上限为 15)。SARIF 上限为 25 个结果。当输出被截断时,顶部会出现提示。

对于 MCP 使用,sarif 是默认且推荐的格式。使用 summaryOnly: true 进行最小化的健康检查(约 835 字节:统计信息、严重性计数、前 3 个问题)。

校准

Tactual 包含一个校准框架(src/calibration/,导出为 tactual/calibration),用于根据真实数据集调整评分参数。详情请参阅 docs/CALIBRATION.md

开发

npm install                    # Install dependencies
npm run build                  # Build with tsup
npm run test                   # Run unit + integration tests
npm run test:benchmark         # Run benchmark suite
npm run typecheck              # TypeScript type checking
npm run lint                   # ESLint

安全性

浏览器沙箱

Tactual 始终在启用默认 Chromium 沙箱的情况下运行 Playwright。它从不禁用 Web 安全性或修改浏览器的安全模型。所有页面交互都在标准的 Chromium 进程沙箱内进行。

安全操作策略

启用探索功能(--explore)时,Tactual 会在激活交互元素之前将其分为三个层级:

层级

操作

示例

安全

已激活

选项卡、菜单项、披露框、手风琴、页内锚点

谨慎

谨慎激活

外部链接、模糊按钮、提交按钮

不安全

跳过

删除、注销、购买、部署、取消订阅

这是一种基于关键字的启发式方法——它无法检测语义欺骗(例如,实际上会删除数据的“保存”按钮)或检查服务器端行为。在生产环境中使用时,请务必在受信任或沙箱环境中运行探索。

URL 验证

所有 URL 在导航前都会经过验证。默认情况下,私有/内部 IP 范围和非 HTTP(S) 方案会被拒绝。

许可证

Apache-2.0

Install Server
A
security – no known vulnerabilities
A
license - permissive license
A
quality - A tier

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tactual-dev/tactual'

If you have feedback or need assistance with the MCP directory API, please join our Discord server