This commit is contained in:
Josh at WLTechBlog
2025-10-03 12:49:50 -05:00
parent 3dc3a4caf1
commit a3a70d5091
11 changed files with 2634 additions and 2 deletions

View File

@@ -3648,7 +3648,7 @@ func main() {
if result.FailedAA > 0 {
summary += "WCAG AA Violations:\n"
for _, elem := range result.Elements {
if !elem.PassesAA && elem.Error == "" {
if !elem.PassesAA {
summary += fmt.Sprintf(" - %s: %.2f:1 (required: %.1f:1)\n"+
" Text: %s\n"+
" Colors: %s on %s\n",
@@ -5061,6 +5061,289 @@ func main() {
}, nil
})
// 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.",
InputSchema: mcp.ToolInputSchema{
Type: "object",
Properties: map[string]any{
"tab": map[string]any{
"type": "string",
"description": "Tab ID (optional, uses current tab)",
},
"tests": map[string]any{
"type": "array",
"description": "Array of test types to run (e.g., ['wcag', 'contrast', 'keyboard', 'forms']). Defaults to 'all'",
"items": map[string]any{
"type": "string",
},
},
"standard": map[string]any{
"type": "string",
"description": "WCAG standard to test against (default: WCAG21AA)",
"default": "WCAG21AA",
},
"include_screenshots": map[string]any{
"type": "boolean",
"description": "Whether to capture screenshots of violations (default: false)",
"default": false,
},
"timeout": map[string]any{
"type": "integer",
"description": "Timeout in seconds (default: 30)",
"default": 30,
},
},
Required: []string{},
},
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
params, ok := request.Params.Arguments.(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid arguments format")
}
tab := getStringParam(params, "tab", cremoteServer.currentTab)
standard := getStringParam(params, "standard", "WCAG21AA")
includeScreenshots := getBoolParam(params, "include_screenshots", false)
timeout := getIntParam(params, "timeout", 30)
// Parse tests array
var tests []string
if testsParam, ok := params["tests"].([]interface{}); ok {
for _, t := range testsParam {
if testStr, ok := t.(string); ok {
tests = append(tests, testStr)
}
}
}
result, err := cremoteServer.client.GetPageAccessibilityReport(tab, tests, standard, includeScreenshots, timeout)
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(fmt.Sprintf("Failed to get page accessibility report: %v", err)),
},
IsError: true,
}, nil
}
// Format results as JSON
resultJSON, err := json.MarshalIndent(result, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal results: %w", err)
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(string(resultJSON)),
},
IsError: false,
}, nil
})
// Register web_contrast_audit tool
mcpServer.AddTool(mcp.Tool{
Name: "web_contrast_audit_cremotemcp",
Description: "Perform smart contrast checking with prioritized failures and pattern detection. Returns only failures and common patterns, significantly reducing token usage compared to full contrast check.",
InputSchema: mcp.ToolInputSchema{
Type: "object",
Properties: map[string]any{
"tab": map[string]any{
"type": "string",
"description": "Tab ID (optional, uses current tab)",
},
"priority_selectors": map[string]any{
"type": "array",
"description": "Array of CSS selectors to prioritize (e.g., ['button', 'a', 'nav', 'footer'])",
"items": map[string]any{
"type": "string",
},
},
"threshold": map[string]any{
"type": "string",
"description": "WCAG level to test against: 'AA' or 'AAA' (default: AA)",
"default": "AA",
},
"timeout": map[string]any{
"type": "integer",
"description": "Timeout in seconds (default: 10)",
"default": 10,
},
},
Required: []string{},
},
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
params, ok := request.Params.Arguments.(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid arguments format")
}
tab := getStringParam(params, "tab", cremoteServer.currentTab)
threshold := getStringParam(params, "threshold", "AA")
timeout := getIntParam(params, "timeout", 10)
// Parse priority selectors array
var prioritySelectors []string
if selectorsParam, ok := params["priority_selectors"].([]interface{}); ok {
for _, s := range selectorsParam {
if selectorStr, ok := s.(string); ok {
prioritySelectors = append(prioritySelectors, selectorStr)
}
}
}
result, err := cremoteServer.client.GetContrastAudit(tab, prioritySelectors, threshold, timeout)
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(fmt.Sprintf("Failed to get contrast audit: %v", err)),
},
IsError: true,
}, nil
}
// Format results as JSON
resultJSON, err := json.MarshalIndent(result, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal results: %w", err)
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(string(resultJSON)),
},
IsError: false,
}, nil
})
// Register web_keyboard_audit tool
mcpServer.AddTool(mcp.Tool{
Name: "web_keyboard_audit_cremotemcp",
Description: "Perform keyboard navigation assessment with actionable results. Returns summary of issues rather than full element lists, reducing token usage by ~80%.",
InputSchema: mcp.ToolInputSchema{
Type: "object",
Properties: map[string]any{
"tab": map[string]any{
"type": "string",
"description": "Tab ID (optional, uses current tab)",
},
"check_focus_indicators": map[string]any{
"type": "boolean",
"description": "Check for visible focus indicators (default: true)",
"default": true,
},
"check_tab_order": map[string]any{
"type": "boolean",
"description": "Check tab order (default: true)",
"default": true,
},
"check_keyboard_traps": map[string]any{
"type": "boolean",
"description": "Check for keyboard traps (default: true)",
"default": true,
},
"timeout": map[string]any{
"type": "integer",
"description": "Timeout in seconds (default: 15)",
"default": 15,
},
},
Required: []string{},
},
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
params, ok := request.Params.Arguments.(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid arguments format")
}
tab := getStringParam(params, "tab", cremoteServer.currentTab)
checkFocusIndicators := getBoolParam(params, "check_focus_indicators", true)
checkTabOrder := getBoolParam(params, "check_tab_order", true)
checkKeyboardTraps := getBoolParam(params, "check_keyboard_traps", true)
timeout := getIntParam(params, "timeout", 15)
result, err := cremoteServer.client.GetKeyboardAudit(tab, checkFocusIndicators, checkTabOrder, checkKeyboardTraps, timeout)
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(fmt.Sprintf("Failed to get keyboard audit: %v", err)),
},
IsError: true,
}, nil
}
// Format results as JSON
resultJSON, err := json.MarshalIndent(result, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal results: %w", err)
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(string(resultJSON)),
},
IsError: false,
}, nil
})
// Register web_form_accessibility_audit tool
mcpServer.AddTool(mcp.Tool{
Name: "web_form_accessibility_audit_cremotemcp",
Description: "Perform comprehensive form accessibility check with summarized results. Analyzes labels, ARIA attributes, keyboard accessibility, and contrast issues.",
InputSchema: mcp.ToolInputSchema{
Type: "object",
Properties: map[string]any{
"tab": map[string]any{
"type": "string",
"description": "Tab ID (optional, uses current tab)",
},
"form_selector": map[string]any{
"type": "string",
"description": "CSS selector for specific form (optional, defaults to all forms)",
},
"timeout": map[string]any{
"type": "integer",
"description": "Timeout in seconds (default: 10)",
"default": 10,
},
},
Required: []string{},
},
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
params, ok := request.Params.Arguments.(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid arguments format")
}
tab := getStringParam(params, "tab", cremoteServer.currentTab)
formSelector := getStringParam(params, "form_selector", "")
timeout := getIntParam(params, "timeout", 10)
result, err := cremoteServer.client.GetFormAccessibilityAudit(tab, formSelector, timeout)
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(fmt.Sprintf("Failed to get form accessibility audit: %v", err)),
},
IsError: true,
}, nil
}
// Format results as JSON
resultJSON, err := json.MarshalIndent(result, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal results: %w", err)
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.NewTextContent(string(resultJSON)),
},
IsError: false,
}, nil
})
// Start the server
log.Printf("Cremote MCP server ready")
if err := server.ServeStdio(mcpServer); err != nil {