This commit is contained in:
Josh at WLTechBlog
2025-10-16 11:26:23 -05:00
parent 4d55acca95
commit 1b01b1e857
6 changed files with 1302 additions and 21 deletions

View File

@@ -0,0 +1,154 @@
# Axe-Core Auto-Injection Enhancement
## Summary
Enhanced the cremote daemon to automatically inject axe-core when needed, eliminating the requirement for manual `web_inject_axe_cremotemcp` calls before running accessibility tests.
## Problem
Previously, users had to manually inject axe-core before running any axe-based accessibility tests:
```yaml
# Old workflow - 2 steps required
1. web_inject_axe_cremotemcp: {}
2. web_run_axe_cremotemcp: {run_only: ["wcag2a", "wcag2aa"]}
```
This was:
- **Inconvenient**: Extra step to remember
- **Error-prone**: Easy to forget injection, causing test failures
- **Verbose**: Required additional tool calls in multi-page assessments
## Solution
Modified `daemon/daemon.go` function `runAxeCore()` to automatically detect if axe-core is loaded and inject it if not:
```go
// Check if axe is loaded, auto-inject if not
checkCode := `() => typeof axe !== 'undefined'`
checkResult, err := page.Eval(checkCode)
if err != nil || !checkResult.Value.Bool() {
d.debugLog("axe-core not loaded, auto-injecting...")
if err := d.injectAxeCore(tabID, "", 30); err != nil {
return nil, fmt.Errorf("failed to auto-inject axe-core: %v", err)
}
}
```
## Benefits
### 1. Simplified Workflow
```yaml
# New workflow - 1 step
web_run_axe_cremotemcp: {run_only: ["wcag2a", "wcag2aa"]}
```
### 2. Fewer Errors
No more "axe-core is not loaded" errors from forgetting to inject.
### 3. Token Efficiency
For multi-page assessments, eliminates one tool call per page:
- **Before**: 20 tool calls for 10 pages (inject + test × 10)
- **After**: 10 tool calls for 10 pages (test × 10)
### 4. Backward Compatible
Manual `web_inject_axe_cremotemcp` calls still work for users who want explicit control over injection timing or version.
## Affected Tools
The following tools now auto-inject axe-core:
1. **`web_run_axe_cremotemcp`** - Direct axe-core test runner
2. **`web_page_accessibility_report_cremotemcp`** - Comprehensive page assessment (uses `runAxeCore` internally)
## Documentation Updates
Updated the following files to reflect auto-injection:
### 1. `daemon/daemon.go`
- Modified `runAxeCore()` function to auto-inject when needed
- Added debug logging for auto-injection events
### 2. `mcp/main.go`
- Updated `web_inject_axe_cremotemcp` description to note auto-injection
- Updated `web_run_axe_cremotemcp` description to mention auto-injection
- Updated `web_page_accessibility_report_cremotemcp` description to mention auto-injection
### 3. `docs/llm_instructions.md`
- Removed requirement to manually inject before tests
- Added note that auto-injection is automatic
- Simplified testing sequences
### 4. `mcp/LLM_USAGE_GUIDE.md`
- Added bold notes about auto-injection to relevant tool descriptions
- Updated workflow examples to remove manual injection steps
## Technical Details
### Injection Logic
1. Check if `axe` object exists in page context using `typeof axe !== 'undefined'`
2. If not found, call `injectAxeCore()` with default parameters (version 4.8.0, 30s timeout)
3. If injection fails, return error with clear message
4. If injection succeeds, proceed with test execution
### Performance Impact
- **Minimal**: Injection check is a simple JavaScript evaluation (~10ms)
- **One-time cost**: Injection only happens once per page load
- **Cached**: Once injected, subsequent tests on same page use existing axe instance
### Error Handling
If auto-injection fails, users get a clear error message:
```
Failed to auto-inject axe-core: [specific error]
```
This helps diagnose issues like:
- Network problems preventing CDN access
- Page security policies blocking script injection
- Browser context issues
## Migration Guide
### For LLM Agents
**No changes required!** Existing code continues to work:
```yaml
# This still works (explicit injection)
web_inject_axe_cremotemcp: {}
web_run_axe_cremotemcp: {}
# This now works too (auto-injection)
web_run_axe_cremotemcp: {}
```
### For Documentation/Prompts
Update any instructions that require manual injection:
**Before:**
```
1. Inject axe-core using web_inject_axe_cremotemcp
2. Run tests using web_run_axe_cremotemcp
```
**After:**
```
1. Run tests using web_run_axe_cremotemcp (auto-injects if needed)
```
## Testing
Build successful with no compilation errors:
```bash
make build
# Builds: cremotedaemon, cremote, cremote-mcp
```
## Future Enhancements
Potential improvements for consideration:
1. **Version Control**: Allow specifying axe-core version in test calls
2. **Injection Caching**: Track injection status per tab to avoid redundant checks
3. **Custom CDN**: Support custom axe-core CDN URLs for air-gapped environments
4. **Injection Metrics**: Log injection frequency for performance monitoring

View File

@@ -8901,11 +8901,14 @@ func (d *Daemon) runAxeCore(tabID string, options map[string]interface{}, timeou
return nil, fmt.Errorf("failed to get page: %v", err)
}
// Check if axe is loaded
// Check if axe is loaded, auto-inject if not
checkCode := `() => typeof axe !== 'undefined'`
checkResult, err := page.Eval(checkCode)
if err != nil || !checkResult.Value.Bool() {
return nil, fmt.Errorf("axe-core is not loaded - call inject-axe first")
d.debugLog("axe-core not loaded, auto-injecting...")
if err := d.injectAxeCore(tabID, "", 30); err != nil {
return nil, fmt.Errorf("failed to auto-inject axe-core: %v", err)
}
}
// Build axe.run() options

View File

@@ -37,31 +37,33 @@ Browser runs in container. File transfers are automatic:
## Testing Sequences
### Multi-page (10+ pages): Use token-efficient tools
### Multi-page (10+ pages): Token-efficient
```
Per page: web_page_accessibility_report_cremotemcp (~4k tokens)
Total 10 pages: ~40k tokens
```
### Single page deep dive: Use detailed tools
### Single page deep dive
```
1. web_inject_axe_cremotemcp
2. web_run_axe_cremotemcp
3. web_contrast_check_cremotemcp
4. web_keyboard_test_cremotemcp
5. web_zoom_test_cremotemcp
6. web_reflow_test_cremotemcp
1. web_run_axe_cremotemcp
2. web_contrast_check_cremotemcp
3. web_keyboard_test_cremotemcp
4. web_zoom_test_cremotemcp
5. web_reflow_test_cremotemcp
```
**NOTE**: Axe-core auto-injects when needed. Manual `web_inject_axe_cremotemcp` calls are optional.
## Usage Examples
### Full page audit (~4k tokens)
```
web_page_accessibility_report_cremotemcp:
tests: ["all"]
standard: "WCAG21AA"
timeout: 30
Returns: compliance_status, overall_score, legal_risk, issues by severity, remediation_hours
1. web_inject_axe_cremotemcp (required first)
2. web_page_accessibility_report_cremotemcp:
tests: ["all"]
standard: "WCAG21AA"
timeout: 30
Returns: compliance_status, overall_score, legal_risk, issues by severity, remediation_hours
```
### Contrast audit (~4k tokens)

View File

@@ -340,12 +340,12 @@ Query accessibility tree by role/name.
Get MCP server and daemon version information. No parameters required.
### web_inject_axe_cremotemcp
Inject axe-core accessibility testing library.
Inject axe-core accessibility testing library. **NOTE**: Auto-injection happens automatically when using web_run_axe_cremotemcp or web_page_accessibility_report_cremotemcp, so manual injection is optional.
- `version` (optional): axe-core version (default: "4.8.0")
- Default timeout: 10s
### web_run_axe_cremotemcp
Run axe-core tests, return violations/passes/incomplete/inapplicable.
Run axe-core tests, return violations/passes/incomplete/inapplicable. **Automatically injects axe-core if not already loaded.**
- `run_only` (optional): array of tags (e.g., ["wcag2a", "wcag2aa", "wcag21aa"])
- `rules` (optional): specific rules configuration object
- Returns: {url, timestamp, test_engine, violations[], passes[], incomplete[], inapplicable[]}
@@ -395,7 +395,7 @@ Comprehensive form accessibility check: labels, ARIA, keyboard, contrast.
- Default timeout: 10s
### web_page_accessibility_report_cremotemcp
Comprehensive page assessment combining axe-core, contrast, keyboard, forms. Token-efficient format (~4k tokens vs ~80k).
Comprehensive page assessment combining axe-core, contrast, keyboard, forms. Token-efficient format (~4k tokens vs ~80k). **Automatically injects axe-core if not already loaded.**
- `tests` (optional): array of test types (e.g., ["wcag", "contrast", "keyboard", "forms"]) or ["all"]
- `standard` (optional): WCAG standard (default: "WCAG21AA")
- `include_screenshots` (optional): boolean (default: false)

1122
mcp/cremote_usage_guide.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3525,7 +3525,7 @@ func main() {
// Register web_inject_axe tool
mcpServer.AddTool(mcp.Tool{
Name: "web_inject_axe_cremotemcp",
Description: "Inject axe-core accessibility testing library into the page for comprehensive WCAG 2.1 AA/AAA testing",
Description: "Inject axe-core accessibility testing library into the page. NOTE: Auto-injection happens automatically when using web_run_axe_cremotemcp or web_page_accessibility_report_cremotemcp, so manual injection is optional.",
InputSchema: mcp.ToolInputSchema{
Type: "object",
Properties: map[string]any{
@@ -3577,7 +3577,7 @@ func main() {
// Register web_run_axe tool
mcpServer.AddTool(mcp.Tool{
Name: "web_run_axe_cremotemcp",
Description: "Run axe-core accessibility tests and return violations, passes, incomplete checks, and inapplicable rules",
Description: "Run axe-core accessibility tests and return violations, passes, incomplete checks, and inapplicable rules. Automatically injects axe-core if not already loaded.",
InputSchema: mcp.ToolInputSchema{
Type: "object",
Properties: map[string]any{
@@ -5050,7 +5050,7 @@ func main() {
// Register web_page_accessibility_report tool
mcpServer.AddTool(mcp.Tool{
Name: "web_page_accessibility_report_cremotemcp",
Description: "Perform comprehensive accessibility assessment of a page and return a summarized report with actionable findings. This tool combines multiple accessibility tests (axe-core, contrast, keyboard, forms) and returns only the critical findings in a token-efficient format.",
Description: "Perform comprehensive accessibility assessment of a page and return a summarized report with actionable findings. This tool combines multiple accessibility tests (axe-core, contrast, keyboard, forms) and returns only the critical findings in a token-efficient format. Automatically injects axe-core if not already loaded.",
InputSchema: mcp.ToolInputSchema{
Type: "object",
Properties: map[string]any{