Skip to main content
Glama

Tactual

スクリーンリーダーのナビゲーションコスト分析ツール。支援技術のユーザーがWeb上のインタラクティブなターゲットを発見し、到達し、操作することがどれほど困難かを測定します。

機能

既存のアクセシビリティツールは適合性(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はオプションのピア依存関係です。PlaywrightはCLIおよびページ分析に必要です。MCP SDKはtactual-mcpサーバーを実行するために必要です。事前に取得した状態を使用してライブラリ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

WebページをSRナビゲーションコストについて分析します。デフォルトの形式は sarif です。waitForSelectorwaitTimeminSeverityfocusexcludeSelectorexcludemaxFindingssummaryOnlytimeoutstorageState パラメータをサポートしています。結果にはPlaywrightのロケーターセレクターが含まれます。キーボードプローブには probe: true を渡してください。オフラインの trace_path 用にキャプチャされた状態を取得するには includeStates: true を渡してください。

trace_path

特定のターゲットへのステップバイステップのナビゲーションパスを追跡します。各アクション、コスト、モデル化されたSRアナウンスを表示します。ターゲットIDまたはグロブパターン(例: *search*)を受け入れます。ブラウザの起動をスキップするには、以前の analyze_url からの statesJson を渡してください。認証済みページ用に storageState をサポートしています。

list_profiles

利用可能なATプロファイルを一覧表示します

diff_results

2つの分析結果を比較します。解決/追加されたペナルティ、重大度の変化、ターゲットごとのステータスを表示します。

suggest_remediations

影響度順にランク付けされた修正案。SARIF出力の場合は冗長です(修正はインラインで行われるため)。

save_auth

Webアプリで認証し、セッション状態を保存します。認証済みコンテンツを分析するために、出力ファイルパスを storageState として他のツールに渡してください。

analyze_pages

サイトレベルの集計を行い、1回の呼び出しで複数のページを分析します。ページあたり約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 Code Scanningにアップロードし、平均スコアがしきい値を下回った場合にビルドを失敗させます。後続のステップのために 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。各次元は、log(0)を避けるためにログを取る前に1を下限としています。これは、いずれかの次元がゼロであれば全体スコアが大幅に低下することを意味します。到達できないものは操作できないためです。

重大度バンド:

スコア

バンド

意味

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.io および ARIA-ATプロジェクト から派生したARIAロール/属性サポートデータの静的スナップショットが含まれています。AT/ブラウザ間でサポートのギャップが知られているロールには、相互運用性リスクペナルティが適用されます。

ロール

リスク

button, link, heading

0

十分にサポートされています

dialog

5

フォーカス管理が異なります

combobox

8

最も相互運用性に問題があるパターン

tree

10

JAWS以外ではサポートが不十分

application

15

誤用すると危険

出力形式の推奨事項

形式

標準サイズ

最適な用途

console

~8KB

ターミナルでの人間によるレビュー

markdown

~11KB

PRおよびIssueのコメント

json

~18KB

プログラムによる消費

sarif

~4-40KB

GitHub Code Scanning / CI

SARIF以外のすべての形式は、要約された出力(統計、グループ化された問題、最悪の発見(最大15件))を出力します。SARIFは最大25件の結果に制限されます。出力が切り捨てられた場合、上部に注記が表示されます。

MCP使用の場合、sarif がデフォルトであり、推奨される形式です。最小限のヘルスチェック(約835バイト:統計、重大度カウント、上位3つの問題)には summaryOnly: true を使用してください。

キャリブレーション

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はインタラクティブな要素をアクティブにする前に3つの階層に分類します:

階層

アクション

安全

アクティブ化

タブ、メニュー項目、開閉式要素、アコーディオン、ページ内アンカー

注意

注意してアクティブ化

外部リンク、曖昧なボタン、送信ボタン

安全でない

スキップ

削除、サインアウト、購入、デプロイ、登録解除

これはキーワードベースのヒューリスティックであり、意味的な欺瞞(例:実際にはデータを削除する「保存」ボタン)を検出したり、サーバー側の動作を検査したりすることはできません。本番環境で使用する場合は、常に信頼できる環境またはサンドボックス化された環境に対して探索を実行してください。

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