tactual-mcp
OfficialTactual
Analizador de coste de navegación para lectores de pantalla. Mide lo difícil que es para los usuarios de tecnología asistiva descubrir, alcanzar y operar objetivos interactivos en la web.
Qué hace
Las herramientas de accesibilidad existentes comprueban la conformidad: ¿es correcto el ARIA? ¿Es suficiente la relación de contraste?
Tactual mide el coste de navegación: ¿cuántas acciones necesita un usuario de lector de pantalla para llegar al botón de pago? ¿Qué sucede si se pasan de largo? ¿Pueden siquiera descubrir que existe?
Funciona capturando instantáneas de accesibilidad de Playwright, construyendo un grafo de navegación y puntuando cada objetivo bajo un perfil de tecnología asistiva.
Instalación
# For CLI usage
npm install tactual playwright
# For MCP server usage (AI tools)
npm install tactual playwright @modelcontextprotocol/sdkPlaywright y @modelcontextprotocol/sdk son dependencias opcionales. Playwright es necesario para la CLI y el análisis de páginas. El SDK de MCP es necesario para ejecutar el servidor tactual-mcp. Ninguno es necesario si solo utilizas la API de la biblioteca con estados previamente capturados.
Inicio rápido
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 initAPI de la biblioteca
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);
}Servidor MCP
Tactual incluye un servidor MCP para el consumo por parte de agentes de IA:
# 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)Herramientas MCP disponibles:
Herramienta | Descripción |
| Analiza una página web para determinar el coste de navegación con lector de pantalla. El formato predeterminado es |
| Rastrea la ruta de navegación paso a paso hasta un objetivo específico. Muestra cada acción, coste y anuncio de lector de pantalla modelado. Acepta ID de objetivo o patrón glob (p. ej., |
| Lista los perfiles de tecnología asistiva (AT) disponibles |
| Compara dos resultados de análisis. Muestra penalizaciones resueltas/añadidas, cambios de gravedad y estado por objetivo. |
| Sugerencias de corrección clasificadas por impacto. Redundante para la salida SARIF (las correcciones están integradas). |
| Autentícate con una aplicación web y guarda el estado de la sesión. Pasa la ruta del archivo de salida como |
| Analiza varias páginas en una sola llamada con agregación a nivel de sitio. Devuelve ~200 bytes por página. Úsalo para el triaje del sitio antes de profundizar en páginas individuales. |
Configuración mediante herramienta de IA
Primero instala los paquetes necesarios en tu proyecto:
npm install tactual playwright @modelcontextprotocol/sdkClaude Code — añade a .mcp.json en la raíz de tu proyecto:
{
"mcpServers": {
"tactual": {
"type": "stdio",
"command": "npx",
"args": ["tactual-mcp"]
}
}
}GitHub Copilot — añade a .copilot/mcp.json o ~/.copilot/mcp-config.json:
{
"mcpServers": {
"tactual": {
"type": "stdio",
"command": "npx",
"args": ["tactual-mcp"]
}
}
}Cursor / Windsurf / Cline — mismo formato en la configuración MCP de tu editor:
{
"mcpServers": {
"tactual": {
"command": "npx",
"args": ["tactual-mcp"]
}
}
}Directo (instalación global) — si prefieres no usar npx:
npm install -g tactual playwright
tactual-mcp # starts the MCP server on stdioGitHub Actions
Utiliza la acción compuesta del 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"La acción instala Tactual y Playwright, ejecuta el análisis, sube el SARIF a GitHub Code Scanning y hace fallar la compilación si la puntuación media está por debajo del umbral. Genera average-score y result-file para pasos posteriores.
O utiliza la CLI directamente para tener más control:
- 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.sarifConfiguración
Flags de la 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 diagnosticstactual.json
Créalo con tactual init o manualmente:
{
"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"
}
}La configuración se detecta automáticamente desde el directorio de trabajo (tactual.json o .tactualrc.json). Los flags de la CLI se fusionan y sobrescriben los ajustes de configuración.
Perfiles de tecnología asistiva (AT)
Perfil | Plataforma | Descripción |
| Móvil | Primitivas de lector de pantalla móvil normalizadas (predeterminado) |
| Móvil | VoiceOver en iOS Safari — navegación basada en rotor |
| Móvil | TalkBack en Android Chrome — controles de lectura |
| Escritorio | NVDA en Windows — teclas rápidas del modo exploración |
| Escritorio | JAWS en Windows — cursor virtual con modo de formularios automático |
Los perfiles definen el coste de cada acción de navegación, los pesos de las dimensiones de puntuación, costSensitivity (escala la curva de decaimiento de la alcanzabilidad) y modificadores dependientes del contexto. Consulta src/profiles/ para obtener detalles de implementación.
Puntuación
Cada objetivo recibe un vector de puntuación de 5 dimensiones:
Dimensión | Qué mide |
Descubribilidad | ¿Puede el usuario saber que el objetivo existe? |
Alcanzabilidad | ¿Cuál es el coste de navegación para llegar allí? |
Operabilidad | ¿El control se comporta de forma predecible? |
Recuperación | ¿Qué tan difícil es recuperarse de pasarse de largo? |
Riesgo de interoperabilidad | ¿Qué probabilidad hay de varianza en el soporte de AT/navegador? (penalización) |
Los pesos de las dimensiones varían según el perfil:
Perfil | 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 |
Compuesto: Media geométrica ponderada: overall = exp(sum(w_i * ln(score_i)) / sum(w_i)) - interopRisk. Cada dimensión se establece en un mínimo de 1 antes del logaritmo para evitar log(0). Esto significa que un cero en cualquier dimensión reduce drásticamente la puntuación general: no puedes operar lo que no puedes alcanzar.
Bandas de gravedad:
Puntuación | Banda | Significado |
90-100 | Fuerte | Poca preocupación |
75-89 | Aceptable | Mejorable |
60-74 | Moderado | Debe ser triado |
40-59 | Alto | Probable fricción significativa |
0-39 | Severo | Probable bloqueo |
Diagnóstico
Tactual detecta e informa cuando el análisis puede no ser fiable:
Código | Nivel | Significado |
| error | Desafío de Cloudflare/bot detectado |
| error | No se encontraron objetivos en absoluto |
| advertencia | Sospechosamente pocos objetivos para una página http |
| advertencia | Solo se encontraron 1-4 objetivos |
| advertencia | Contenido protegido por autenticación (detecta redirecciones de ruta |
| info | El consentimiento de cookies puede ocultar contenido |
| advertencia | Aterrizó en un dominio diferente |
| advertencia | No se encontraron elementos de encabezado |
| advertencia | No se encontraron regiones de puntos de referencia |
Exploración
El flag --explore activa la exploración de ramas acotada:
Abre menús, pestañas, divulgaciones, acordeones y diálogos
Captura nuevos estados de accesibilidad de la interfaz de usuario oculta
Marca los objetivos descubiertos como
requiresBranchOpenRespeta los presupuestos de profundidad, recuento de acciones, recuento de objetivos y novedad
La política de acciones seguras bloquea las interacciones destructivas
La exploración es útil para páginas con una interfaz de usuario oculta significativa (p. ej., menús desplegables, interfaces con pestañas, diálogos modales).
Los candidatos a exploración se ordenan por una clave estable (rol + nombre) antes de iterar, por lo que el mismo contenido de página produce el mismo orden de exploración en todas las ejecuciones.
Presupuestos de exploración
Presupuesto | Flag de CLI | Predeterminado | Propósito |
Profundidad |
| 3 | Profundidad máxima de recursión |
Acciones |
| 50 | Presupuesto total de clics en todas las ramas |
Objetivos |
| 2000 | Detener si los objetivos acumulados superan esto |
Tiempo | (solo biblioteca) | 120s | Tiempo de espera global |
Detección de framework SPA
Tactual detecta cuando el contenido SPA se ha renderizado antes de capturar el árbol de accesibilidad. Frameworks detectados: React, Next.js, Vue, Nuxt, Angular, Svelte y SvelteKit. También se comprueban las señales de contenido HTML5 genérico (puntos de referencia, encabezados, navegación, enlaces). Para SPAs no cubiertos por la detección automática, utiliza --wait-for-selector (CLI) o waitForSelector (MCP/API) para especificar un selector CSS que indique que tu aplicación se ha hidratado.
Después de la detección inicial del framework, Tactual utiliza el sondeo basado en convergencia —tomando instantáneas repetidamente del árbol de accesibilidad hasta que el recuento de objetivos se estabiliza—, lo que funciona independientemente del framework.
Riesgo de interoperabilidad
Tactual incluye una instantánea estática de datos de soporte de roles/atributos ARIA derivados de a11ysupport.io y el proyecto ARIA-AT. Los roles con brechas de soporte conocidas entre AT/navegador reciben una penalización por riesgo de interoperabilidad.
Rol | Riesgo | Nota |
| 0 | Bien soportado |
| 5 | La gestión del foco varía |
| 8 | Patrón más problemático para la interoperabilidad |
| 10 | Mal soportado fuera de JAWS |
| 15 | Peligroso si se usa mal |
Recomendaciones de formato de salida
Formato | Tamaño típico | Mejor para |
| ~8KB | Revisión humana en terminal |
| ~11KB | PRs y comentarios de problemas |
| ~18KB | Consumo programático |
| ~4-40KB | GitHub Code Scanning / CI |
Todos los formatos que no son SARIF emiten una salida resumida: estadísticas, problemas agrupados y peores hallazgos (limitado a 15). SARIF limita a 25 resultados. Cuando la salida se trunca, aparece una nota en la parte superior.
Para el uso de MCP, sarif es el formato predeterminado y recomendado. Usa summaryOnly: true para una comprobación de salud mínima (~835 bytes: estadísticas, recuentos de gravedad, 3 problemas principales).
Calibración
Tactual incluye un framework de calibración (src/calibration/, exportado como tactual/calibration) para ajustar los parámetros de puntuación frente a conjuntos de datos de verdad fundamental. Consulta docs/CALIBRATION.md para obtener más detalles.
Desarrollo
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 # ESLintSeguridad
Sandboxing del navegador
Tactual siempre ejecuta Playwright con el sandboxing de Chromium predeterminado habilitado. Nunca desactiva la seguridad web ni modifica el modelo de seguridad del navegador. Todas las interacciones de página ocurren dentro del sandbox del proceso estándar de Chromium.
Política de acciones seguras
Cuando la exploración está habilitada (--explore), Tactual clasifica los elementos interactivos en tres niveles antes de activarlos:
Nivel | Acción | Ejemplos |
Seguro | Activado | Pestañas, elementos de menú, divulgaciones, acordeones, anclas de la misma página |
Precaución | Activado con cuidado | Enlaces externos, botones ambiguos, botones de envío |
Inseguro | Omitido | Eliminar, cerrar sesión, comprar, desplegar, cancelar suscripción |
Esta es una heurística basada en palabras clave: no puede detectar el engaño semántico (p. ej., un botón "Guardar" que en realidad elimina datos) ni inspeccionar el comportamiento del lado del servidor. Para uso en producción, ejecuta siempre la exploración en entornos de confianza o aislados (sandboxed).
Validación de URL
Todas las URL se validan antes de la navegación. Los rangos de IP privados/internos y los esquemas que no son HTTP(S) se rechazan de forma predeterminada.
Licencia
Apache-2.0
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