synapse-hub 0.0.0-stage → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/agents/failure-analyst.md +47 -0
- package/.agents/agents/live-explorer.md +41 -0
- package/.agents/agents/orchestrator.md +43 -0
- package/.agents/agents/pom-crafter.md +81 -0
- package/.agents/agents/quality-gatekeeper.md +47 -0
- package/.agents/agents/test-runner.md +43 -0
- package/.agents/rules/context-engineering.md +88 -0
- package/.agents/rules/git-push-protocol.md +101 -0
- package/.agents/rules/graphify.md +14 -0
- package/.agents/rules/lessons-learned.md +23 -0
- package/.agents/rules/mandatory-playwright-live.md +29 -0
- package/.agents/rules/skill-precedence.md +42 -0
- package/.agents/rules/systematic-debugging.md +99 -0
- package/.agents/skills/agent-orchestration-multi-agent-optimize/SKILL.md +239 -0
- package/.agents/skills/antigravity-test-sentinel/SKILL.md +64 -0
- package/.agents/skills/api-network-mocking-interception/SKILL.md +142 -0
- package/.agents/skills/api-spec-to-e2e-matrix/SKILL.md +70 -0
- package/.agents/skills/architecture-decision-records/SKILL.md +441 -0
- package/.agents/skills/auth-session-and-cookie-manager/SKILL.md +72 -0
- package/.agents/skills/backend-load-and-stress-patterns/SKILL.md +214 -0
- package/.agents/skills/bats-testing-patterns/SKILL.md +100 -0
- package/.agents/skills/bats-testing-patterns/resources/implementation-playbook.md +614 -0
- package/.agents/skills/clean-pom-crafter/SKILL.md +75 -0
- package/.agents/skills/clean-pom-crafter/examples/standard_test_case.groovy +28 -0
- package/.agents/skills/clean-pom-crafter/references/pom_patterns.groovy +138 -0
- package/.agents/skills/code-refactoring-refactor-clean/SKILL.md +64 -0
- package/.agents/skills/code-refactoring-refactor-clean/resources/implementation-playbook.md +879 -0
- package/.agents/skills/db-state-verifier-and-seeder/SKILL.md +123 -0
- package/.agents/skills/e2e-testing-patterns/SKILL.md +103 -0
- package/.agents/skills/e2e-testing-patterns/resources/implementation-playbook.md +522 -0
- package/.agents/skills/failure-autopsy-and-healing/SKILL.md +54 -0
- package/.agents/skills/failure-autopsy-and-healing/references/healing_matrix.md +64 -0
- package/.agents/skills/failure-autopsy-and-healing/references/qa_investigation_protocol.md +56 -0
- package/.agents/skills/failure-autopsy-and-healing/scripts/triage_failures.sh +98 -0
- package/.agents/skills/file-and-report-validator/SKILL.md +90 -0
- package/.agents/skills/flaky-test-sentinel-and-quarantine/SKILL.md +114 -0
- package/.agents/skills/github-actions-templates/SKILL.md +334 -0
- package/.agents/skills/graphify-impact-analyzer/SKILL.md +78 -0
- package/.agents/skills/katalon-cli-runner/SKILL.md +76 -0
- package/.agents/skills/katalon-cli-runner/references/groovy-patterns.md +209 -0
- package/.agents/skills/katalon-cli-runner/references/katalon-api.md +155 -0
- package/.agents/skills/katalon-cli-runner/references/runner_commands.md +67 -0
- package/.agents/skills/lam-script-generator/SKILL.md +83 -0
- package/.agents/skills/playwright-live-interaction/SKILL.md +86 -0
- package/.agents/skills/playwright-live-interaction/references/advanced_superpowers.md +160 -0
- package/.agents/skills/playwright-live-interaction/references/compact_accessibility_snapshots.md +75 -0
- package/.agents/skills/playwright-live-interaction/references/recipes.md +388 -0
- package/.agents/skills/playwright-live-interaction/references/swarm_orchestration.md +134 -0
- package/.agents/skills/security-dast-sentinel/SKILL.md +176 -0
- package/.agents/skills/self-healing-locator/SKILL.md +73 -0
- package/.agents/skills/synthetic-test-data-generator/SKILL.md +135 -0
- package/.agents/skills/token-and-context-optimizer/SKILL.md +70 -0
- package/.agents/skills/visual-regression-sentinel/SKILL.md +62 -0
- package/.agents/skills/wcag-audit-patterns/SKILL.md +77 -0
- package/.agents/skills/wcag-audit-patterns/resources/implementation-playbook.md +541 -0
- package/.agents/skills/web-vitals-and-performance-profiler/SKILL.md +65 -0
- package/.agents/templates/completion_report.md +57 -0
- package/.agents/workflows/graphify.md +10 -0
- package/.agents/workflows/test-impact.md +15 -0
- package/.agents/workflows/verify.md +34 -0
- package/AGENTS.md +115 -0
- package/README.md +394 -2
- package/bin/agent-qa.js +90 -0
- package/package.json +59 -4
- package/skills_manifest.json +262 -0
- package/templates/PROJECT_AI_GUIDE_TEMPLATE.md +97 -0
- package/templates/PROJECT_STATE_TEMPLATE.md +20 -0
- package/tools/TOOLS_RUNBOOK.md +298 -0
- package/tools/agent_canary.py +501 -0
- package/tools/analyze_project.py +242 -0
- package/tools/api_drift_sentinel.py +208 -0
- package/tools/auto_heal.py +189 -0
- package/tools/browser_helpers.js +593 -0
- package/tools/bug_reporter.py +224 -0
- package/tools/cache_resolver.py +846 -0
- package/tools/check_env.py +288 -0
- package/tools/ci_healing_hook.py +128 -0
- package/tools/cli.py +402 -0
- package/tools/config_decoupler.py +253 -0
- package/tools/db_sandbox.py +341 -0
- package/tools/distill_log.py +152 -0
- package/tools/e2e_flow_prober.ps1 +65 -0
- package/tools/flaky_detector.py +222 -0
- package/tools/fuzz_payloads.py +197 -0
- package/tools/generate_allure_report.ps1 +30 -0
- package/tools/generate_api_matrix.py +193 -0
- package/tools/generate_tc_from_story.py +182 -0
- package/tools/generate_test_reports.ps1 +135 -0
- package/tools/git_pre_commit_guard.py +203 -0
- package/tools/heal_pr_automator.py +195 -0
- package/tools/heuristic_locator_matcher.py +202 -0
- package/tools/infer_linter.py +238 -0
- package/tools/lint_ai_docs.py +254 -0
- package/tools/lookup_tc.py +165 -0
- package/tools/lookup_xpath.py +167 -0
- package/tools/matrix_sharder.py +146 -0
- package/tools/mcp_excel_server.ps1 +251 -0
- package/tools/mcp_server.py +490 -0
- package/tools/micro_mutator.py +309 -0
- package/tools/network_mock_shield.py +170 -0
- package/tools/omni_emitter.py +500 -0
- package/tools/omni_parser.py +435 -0
- package/tools/omni_transpiler.py +168 -0
- package/tools/pinpoint_failure.py +88 -0
- package/tools/project_state.py +169 -0
- package/tools/repo_map.json +12 -0
- package/tools/repo_map.py +277 -0
- package/tools/repo_map.txt +7 -0
- package/tools/safety_firewall.py +245 -0
- package/tools/setup_project.py +265 -0
- package/tools/smart_visual_masker.py +134 -0
- package/tools/test_impact.py +321 -0
- package/tools/tms_sync_bridge.py +342 -0
- package/tools/trace_data_flow.py +240 -0
- package/tools/traffic_session_converter.py +256 -0
- package/tools/universal_ir.py +480 -0
- package/tools/validate_groovy_scripts.py +173 -0
- package/tools/verify_all.py +496 -0
- package/tools/verify_all.sh +4 -0
- package/tools/visual_diff_canvas.py +142 -0
- package/tools/visual_som_helper.py +418 -0
- package/tools/wcag_audit.py +214 -0
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Enterprise Model Context Protocol (MCP) Standard Server
|
|
4
|
+
-------------------------------------------------------
|
|
5
|
+
Exposes centralized tools/ capabilities as standardized JSON-RPC 2.0 MCP Tools
|
|
6
|
+
compatible with Google Antigravity, Cursor, Claude Desktop, Windsurf, and any MCP client.
|
|
7
|
+
Communicates via standard JSON-RPC stdio.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
import json
|
|
13
|
+
import traceback
|
|
14
|
+
from typing import Dict, Any, List
|
|
15
|
+
|
|
16
|
+
# Enforce UTF-8 stdio encoding
|
|
17
|
+
if hasattr(sys.stdout, 'reconfigure'):
|
|
18
|
+
try:
|
|
19
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
20
|
+
sys.stderr.reconfigure(encoding='utf-8')
|
|
21
|
+
sys.stdin.reconfigure(encoding='utf-8')
|
|
22
|
+
except Exception:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
26
|
+
HUB_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, ".."))
|
|
27
|
+
sys.path.insert(0, SCRIPT_DIR)
|
|
28
|
+
|
|
29
|
+
import verify_all
|
|
30
|
+
import analyze_project
|
|
31
|
+
import setup_project
|
|
32
|
+
import auto_heal
|
|
33
|
+
import safety_firewall
|
|
34
|
+
import api_drift_sentinel
|
|
35
|
+
import cache_resolver
|
|
36
|
+
import distill_log
|
|
37
|
+
import micro_mutator
|
|
38
|
+
import heal_pr_automator
|
|
39
|
+
import matrix_sharder
|
|
40
|
+
import tms_sync_bridge
|
|
41
|
+
import db_sandbox
|
|
42
|
+
import traffic_session_converter
|
|
43
|
+
import visual_som_helper
|
|
44
|
+
|
|
45
|
+
SERVER_NAME = "enterprise-agent-qa"
|
|
46
|
+
SERVER_VERSION = "2.0.0"
|
|
47
|
+
|
|
48
|
+
MCP_TOOLS = [
|
|
49
|
+
{
|
|
50
|
+
"name": "verify_all_gates",
|
|
51
|
+
"description": "Validates the 8 Quality Gates Definition of Done (UTF-8, paths, Clean POM, AI docs, blacklist, security, infer linter, micro-mutator).",
|
|
52
|
+
"inputSchema": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"properties": {
|
|
55
|
+
"repo_path": {"type": "string", "description": "Absolute or relative path to the target repository. Defaults to CWD."}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "analyze_project",
|
|
61
|
+
"description": "Executes 5-in-1 project health and AST intelligence analysis, creating PROJECT_HEALTH_REPORT.md and repo_map.txt.",
|
|
62
|
+
"inputSchema": {
|
|
63
|
+
"type": "object",
|
|
64
|
+
"properties": {
|
|
65
|
+
"repo_path": {"type": "string", "description": "Target project repository directory to audit."}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "setup_project",
|
|
71
|
+
"description": "Autonomous 1-click bootstrap of any test project: detects stack, generates PROJECT_AI_GUIDE.md, installs Git hook, and maps AST.",
|
|
72
|
+
"inputSchema": {
|
|
73
|
+
"type": "object",
|
|
74
|
+
"properties": {
|
|
75
|
+
"repo_path": {"type": "string", "description": "Path to target project to bootstrap."}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "auto_heal_failure",
|
|
81
|
+
"description": "Diagnoses test failures in 0.1s from JUnit XML and queries semantic memory cache for proven patches.",
|
|
82
|
+
"inputSchema": {
|
|
83
|
+
"type": "object",
|
|
84
|
+
"properties": {
|
|
85
|
+
"target_dir": {"type": "string", "description": "Target project root directory."},
|
|
86
|
+
"junit_xml_path": {"type": "string", "description": "Optional direct path to failing JUnit XML report."}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"name": "check_action_safety",
|
|
92
|
+
"description": "Action Safety Firewall: verifies whether an intended UI action (click, fill) touches destructive elements (Delete, Pay, Drop).",
|
|
93
|
+
"inputSchema": {
|
|
94
|
+
"type": "object",
|
|
95
|
+
"properties": {
|
|
96
|
+
"action_type": {"type": "string", "description": "Action type (e.g. click, fill, submit)."},
|
|
97
|
+
"element_text": {"type": "string", "description": "Text or label of target DOM element."},
|
|
98
|
+
"selector": {"type": "string", "description": "CSS or XPath selector of element."},
|
|
99
|
+
"force": {"type": "boolean", "description": "Force bypass firewall."}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "check_contract_drift",
|
|
105
|
+
"description": "Compares two OpenAPI / Swagger specifications and detects breaking changes (removed endpoints, changed types, newly required params).",
|
|
106
|
+
"inputSchema": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"properties": {
|
|
109
|
+
"old_spec_path": {"type": "string", "description": "Path to baseline OpenAPI JSON file."},
|
|
110
|
+
"new_spec_path": {"type": "string", "description": "Path to current OpenAPI JSON file."}
|
|
111
|
+
},
|
|
112
|
+
"required": ["old_spec_path", "new_spec_path"]
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "query_memory_cache",
|
|
117
|
+
"description": "Queries the 0-token SQLite semantic memory cache for known UI exceptions and proven repair patches.",
|
|
118
|
+
"inputSchema": {
|
|
119
|
+
"type": "object",
|
|
120
|
+
"properties": {
|
|
121
|
+
"error_signature": {"type": "string", "description": "Exception trace or error message to lookup."}
|
|
122
|
+
},
|
|
123
|
+
"required": ["error_signature"]
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"name": "distill_log",
|
|
128
|
+
"description": "Filters verbose CLI or Gradle build logs by 95%, retaining only actionable stacktraces and pointers.",
|
|
129
|
+
"inputSchema": {
|
|
130
|
+
"type": "object",
|
|
131
|
+
"properties": {
|
|
132
|
+
"raw_log_text": {"type": "string", "description": "Raw terminal log output to compress."}
|
|
133
|
+
},
|
|
134
|
+
"required": ["raw_log_text"]
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name": "run_micro_mutation",
|
|
139
|
+
"description": "Injects AST micro-mutants (flipping operators, booleans) to verify that AI-generated test assertions are robust.",
|
|
140
|
+
"inputSchema": {
|
|
141
|
+
"type": "object",
|
|
142
|
+
"properties": {
|
|
143
|
+
"target_path": {"type": "string", "description": "Path to test script or directory to mutate."}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "plan_healing_pr",
|
|
149
|
+
"description": "Calculates composite confidence score for healed locators and formats an automated Pull Request draft.",
|
|
150
|
+
"inputSchema": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"properties": {
|
|
153
|
+
"page_file": {"type": "string", "description": "Page Class path."},
|
|
154
|
+
"old_locator": {"type": "string", "description": "Original stale selector."},
|
|
155
|
+
"new_locator": {"type": "string", "description": "Healed replacement selector."},
|
|
156
|
+
"aom_score": {"type": "number", "description": "AOM match score 0.0-1.0."},
|
|
157
|
+
"spatial_score": {"type": "number", "description": "Spatial score 0.0-1.0."},
|
|
158
|
+
"visual_score": {"type": "number", "description": "Visual SSIM score 0.0-1.0."}
|
|
159
|
+
},
|
|
160
|
+
"required": ["page_file", "old_locator", "new_locator"]
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "shard_test_matrix",
|
|
165
|
+
"description": "Distributes test cases evenly across N parallel CI/CD runners using Duration-Balanced Bin-Packing.",
|
|
166
|
+
"inputSchema": {
|
|
167
|
+
"type": "object",
|
|
168
|
+
"properties": {
|
|
169
|
+
"target_dir": {"type": "string", "description": "Target project root directory."},
|
|
170
|
+
"num_shards": {"type": "integer", "description": "Number of parallel workers (default 4)."}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"name": "pull_alm_story",
|
|
176
|
+
"description": "Pulls User Story and Acceptance Criteria (Given-When-Then) from Jira, Xray, or TestRail for test generation context.",
|
|
177
|
+
"inputSchema": {
|
|
178
|
+
"type": "object",
|
|
179
|
+
"properties": {
|
|
180
|
+
"issue_key": {"type": "string", "description": "ALM Issue Key (e.g. PROJ-1042)."}
|
|
181
|
+
},
|
|
182
|
+
"required": ["issue_key"]
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"name": "report_alm_defect",
|
|
187
|
+
"description": "Creates an automated Bug Ticket in Jira/TMS with full diagnostic reproduction steps, stack trace, and screenshot attachments.",
|
|
188
|
+
"inputSchema": {
|
|
189
|
+
"type": "object",
|
|
190
|
+
"properties": {
|
|
191
|
+
"project_key": {"type": "string", "description": "Target project key (e.g. PROJ)."},
|
|
192
|
+
"test_case_id": {"type": "string", "description": "Failing test case ID."},
|
|
193
|
+
"summary": {"type": "string", "description": "Defect summary."},
|
|
194
|
+
"error_message": {"type": "string", "description": "Exact failure error message."},
|
|
195
|
+
"stack_trace": {"type": "string", "description": "Exception stack trace."},
|
|
196
|
+
"screenshot_path": {"type": "string", "description": "Path to FAILED screenshot image."}
|
|
197
|
+
},
|
|
198
|
+
"required": ["project_key", "test_case_id", "summary", "error_message"]
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"name": "manage_db_sandbox",
|
|
203
|
+
"description": "Zero-pollution ephemeral database manager: creates baseline snapshot, restores pristine DB state, or executes transaction savepoints.",
|
|
204
|
+
"inputSchema": {
|
|
205
|
+
"type": "object",
|
|
206
|
+
"properties": {
|
|
207
|
+
"action": {"type": "string", "enum": ["snapshot", "restore", "audit_and_purge"], "description": "Sandbox operation to execute."},
|
|
208
|
+
"db_path": {"type": "string", "description": "Path to database file (optional for SQLite)."},
|
|
209
|
+
"snapshot_id": {"type": "string", "description": "Snapshot identifier (default: pristine_baseline)."}
|
|
210
|
+
},
|
|
211
|
+
"required": ["action"]
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"name": "convert_traffic_session",
|
|
216
|
+
"description": "Shift-Right Replay: Transforms recorded HTTP Archive (.har) or RUM session into PII-sanitized Playwright test suite.",
|
|
217
|
+
"inputSchema": {
|
|
218
|
+
"type": "object",
|
|
219
|
+
"properties": {
|
|
220
|
+
"input_file": {"type": "string", "description": "Path to .har or JSON network session file."},
|
|
221
|
+
"test_name": {"type": "string", "description": "Generated test suite name."}
|
|
222
|
+
},
|
|
223
|
+
"required": ["input_file"]
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"name": "resolve_visual_som_coordinates",
|
|
228
|
+
"description": "Multimodal Vision Grounding: Resolves click coordinates (x, y) on HTML5 Canvas or Shadow DOM using Set-of-Marks (SoM).",
|
|
229
|
+
"inputSchema": {
|
|
230
|
+
"type": "object",
|
|
231
|
+
"properties": {
|
|
232
|
+
"image_path": {"type": "string", "description": "Path to screenshot image."},
|
|
233
|
+
"target_label": {"type": "string", "description": "Target element label or text."},
|
|
234
|
+
"mark_id": {"type": "integer", "description": "Specific Mark ID to click."}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def handle_tool_call(name: str, arguments: Dict[str, Any]) -> str:
|
|
242
|
+
"""Executes the corresponding internal tool function and returns text response."""
|
|
243
|
+
if name == "verify_all_gates":
|
|
244
|
+
repo = arguments.get("repo_path") or os.getcwd()
|
|
245
|
+
mode = verify_all.detect_repo_mode(repo)
|
|
246
|
+
passed = True
|
|
247
|
+
gates = [
|
|
248
|
+
("Gate 1: UTF-8 No BOM", verify_all.gate_1_bom_check),
|
|
249
|
+
("Gate 2: Path Portability", verify_all.gate_2_path_portability),
|
|
250
|
+
("Gate 3: Clean POM", verify_all.gate_3_clean_pom),
|
|
251
|
+
("Gate 4: AI Docs Linter", verify_all.gate_4_ai_docs_lint),
|
|
252
|
+
("Gate 5: Temp Blacklist", verify_all.gate_5_cleanup_blacklist),
|
|
253
|
+
("Gate 6: Credential Security", verify_all.gate_6_credential_security),
|
|
254
|
+
("Gate 7: Infer Linter", verify_all.gate_7_infer_linter),
|
|
255
|
+
("Gate 8: AST Mutation Sentinel", verify_all.gate_8_micro_mutator),
|
|
256
|
+
]
|
|
257
|
+
results = []
|
|
258
|
+
for g_name, g_fn in gates:
|
|
259
|
+
res = g_fn(repo, mode=mode)
|
|
260
|
+
results.append(f"{g_name}: {'PASS' if res else 'FAIL'}")
|
|
261
|
+
if not res:
|
|
262
|
+
passed = False
|
|
263
|
+
summary = "100% ALL 8 GATES PASSED" if passed else "VERIFICATION FAILED"
|
|
264
|
+
return f"[{summary}]\n" + "\n".join(results)
|
|
265
|
+
|
|
266
|
+
elif name == "analyze_project":
|
|
267
|
+
repo = arguments.get("repo_path") or os.getcwd()
|
|
268
|
+
code = analyze_project.run_full_analysis(repo)
|
|
269
|
+
return f"Project Analysis finished with exit code {code}. Report saved at {os.path.join(repo, 'PROJECT_HEALTH_REPORT.md')}."
|
|
270
|
+
|
|
271
|
+
elif name == "setup_project":
|
|
272
|
+
repo = arguments.get("repo_path") or os.getcwd()
|
|
273
|
+
code = setup_project.run_setup(repo)
|
|
274
|
+
return f"Project Setup finished with exit code {code}."
|
|
275
|
+
|
|
276
|
+
elif name == "auto_heal_failure":
|
|
277
|
+
target = arguments.get("target_dir") or os.getcwd()
|
|
278
|
+
xml = arguments.get("junit_xml_path")
|
|
279
|
+
plan = auto_heal.diagnose_and_plan_heal(target, xml)
|
|
280
|
+
return json.dumps(plan, indent=2)
|
|
281
|
+
|
|
282
|
+
elif name == "check_action_safety":
|
|
283
|
+
auth = safety_firewall.inspect_and_authorize(
|
|
284
|
+
action_type=arguments.get("action_type", "click"),
|
|
285
|
+
text=arguments.get("element_text", ""),
|
|
286
|
+
selector=arguments.get("selector", ""),
|
|
287
|
+
force=arguments.get("force", False)
|
|
288
|
+
)
|
|
289
|
+
return json.dumps(auth, indent=2)
|
|
290
|
+
|
|
291
|
+
elif name == "check_contract_drift":
|
|
292
|
+
old_data = api_drift_sentinel.load_spec(arguments["old_spec_path"])
|
|
293
|
+
new_data = api_drift_sentinel.load_spec(arguments["new_spec_path"])
|
|
294
|
+
analysis = api_drift_sentinel.compare_specs(old_data, new_data)
|
|
295
|
+
return api_drift_sentinel.generate_markdown_report(analysis, arguments["old_spec_path"], arguments["new_spec_path"])
|
|
296
|
+
|
|
297
|
+
elif name == "query_memory_cache":
|
|
298
|
+
res = cache_resolver.query_cache(arguments["error_signature"])
|
|
299
|
+
return json.dumps(res, indent=2) if res else "No matching solution found in memory cache."
|
|
300
|
+
|
|
301
|
+
elif name == "distill_log":
|
|
302
|
+
distilled = distill_log.distill_log_content(arguments["raw_log_text"])
|
|
303
|
+
return distilled
|
|
304
|
+
|
|
305
|
+
elif name == "run_micro_mutation":
|
|
306
|
+
target = arguments.get("target_path") or os.getcwd()
|
|
307
|
+
mutants = micro_mutator.scan_directory_for_mutants(target) if os.path.isdir(target) else micro_mutator.generate_mutants_for_code(open(target).read(), target)
|
|
308
|
+
return json.dumps({"total_mutants": len(mutants), "sample_mutants": mutants[:5]}, indent=2)
|
|
309
|
+
|
|
310
|
+
elif name == "plan_healing_pr":
|
|
311
|
+
conf = heal_pr_automator.calculate_healing_confidence(
|
|
312
|
+
arguments.get("aom_score", 0.95),
|
|
313
|
+
arguments.get("spatial_score", 0.90),
|
|
314
|
+
arguments.get("visual_score", 0.92)
|
|
315
|
+
)
|
|
316
|
+
pr = heal_pr_automator.generate_pr_draft(arguments["page_file"], arguments["old_locator"], arguments["new_locator"], conf)
|
|
317
|
+
return json.dumps({"confidence": conf, "pr": pr}, indent=2)
|
|
318
|
+
|
|
319
|
+
elif name == "shard_test_matrix":
|
|
320
|
+
target = arguments.get("target_dir") or os.getcwd()
|
|
321
|
+
num_shards = arguments.get("num_shards", 4)
|
|
322
|
+
files = matrix_sharder.find_test_files(target)
|
|
323
|
+
shards = matrix_sharder.shard_tests_lpt(files, target, num_shards)
|
|
324
|
+
return json.dumps({"total_tests": len(files), "shards": shards}, indent=2)
|
|
325
|
+
|
|
326
|
+
elif name == "pull_alm_story":
|
|
327
|
+
bridge = tms_sync_bridge.TMSBridge()
|
|
328
|
+
story = bridge.pull_story_acceptance_criteria(arguments["issue_key"])
|
|
329
|
+
return json.dumps(story, indent=2)
|
|
330
|
+
|
|
331
|
+
elif name == "report_alm_defect":
|
|
332
|
+
bridge = tms_sync_bridge.TMSBridge()
|
|
333
|
+
ticket = bridge.report_defect(
|
|
334
|
+
project_key=arguments["project_key"],
|
|
335
|
+
test_case_id=arguments["test_case_id"],
|
|
336
|
+
summary=arguments["summary"],
|
|
337
|
+
error_message=arguments["error_message"],
|
|
338
|
+
stack_trace=arguments.get("stack_trace", ""),
|
|
339
|
+
screenshot_path=arguments.get("screenshot_path", "")
|
|
340
|
+
)
|
|
341
|
+
return json.dumps(ticket, indent=2)
|
|
342
|
+
|
|
343
|
+
elif name == "manage_db_sandbox":
|
|
344
|
+
action = arguments["action"]
|
|
345
|
+
sandbox = db_sandbox.DBSandbox(db_path=arguments.get("db_path", ""))
|
|
346
|
+
if action == "snapshot":
|
|
347
|
+
res = sandbox.create_snapshot(arguments.get("snapshot_id", "pristine_baseline"))
|
|
348
|
+
elif action == "restore":
|
|
349
|
+
res = sandbox.restore_snapshot(arguments.get("snapshot_id", "pristine_baseline"))
|
|
350
|
+
elif action == "audit_and_purge":
|
|
351
|
+
res = sandbox.audit_and_purge_pollution()
|
|
352
|
+
else:
|
|
353
|
+
raise ValueError(f"Unknown sandbox action: {action}")
|
|
354
|
+
return json.dumps(res, indent=2)
|
|
355
|
+
|
|
356
|
+
elif name == "convert_traffic_session":
|
|
357
|
+
input_file = arguments["input_file"]
|
|
358
|
+
test_name = arguments.get("test_name", "ProductionTrafficReplay")
|
|
359
|
+
with open(input_file, "r", encoding="utf-8", errors="ignore") as f:
|
|
360
|
+
data = json.load(f)
|
|
361
|
+
converter = traffic_session_converter.TrafficConverter(sanitize_pii=True)
|
|
362
|
+
requests = converter.parse_har(data)
|
|
363
|
+
test_code = converter.generate_playwright_test(requests, test_name=test_name)
|
|
364
|
+
return json.dumps({"total_requests": len(requests), "generated_test": test_code}, indent=2)
|
|
365
|
+
|
|
366
|
+
elif name == "resolve_visual_som_coordinates":
|
|
367
|
+
helper = visual_som_helper.VisualSoMHelper()
|
|
368
|
+
img = arguments.get("image_path", "screenshot.png")
|
|
369
|
+
lbl = arguments.get("target_label")
|
|
370
|
+
mid = arguments.get("mark_id")
|
|
371
|
+
marked_img, marks_map = helper.generate_som_overlay(img, [])
|
|
372
|
+
resolved = helper.resolve_mark_coordinates(marks_map, target_mark_id=mid, target_label=lbl)
|
|
373
|
+
return json.dumps({"marked_image": marked_img, "resolved_target": resolved}, indent=2)
|
|
374
|
+
|
|
375
|
+
raise ValueError(f"Unknown MCP tool: {name}")
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def process_message(msg: Dict[str, Any]) -> Dict[str, Any]:
|
|
379
|
+
"""Processes an incoming JSON-RPC 2.0 message."""
|
|
380
|
+
method = msg.get("method")
|
|
381
|
+
msg_id = msg.get("id")
|
|
382
|
+
|
|
383
|
+
if method == "initialize":
|
|
384
|
+
return {
|
|
385
|
+
"jsonrpc": "2.0",
|
|
386
|
+
"id": msg_id,
|
|
387
|
+
"result": {
|
|
388
|
+
"protocolVersion": "2024-11-05",
|
|
389
|
+
"capabilities": {
|
|
390
|
+
"tools": {}
|
|
391
|
+
},
|
|
392
|
+
"serverInfo": {
|
|
393
|
+
"name": SERVER_NAME,
|
|
394
|
+
"version": SERVER_VERSION
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
elif method in ("notifications/initialized", "initialized"):
|
|
400
|
+
return None # No response needed for notification
|
|
401
|
+
|
|
402
|
+
elif method == "tools/list":
|
|
403
|
+
return {
|
|
404
|
+
"jsonrpc": "2.0",
|
|
405
|
+
"id": msg_id,
|
|
406
|
+
"result": {
|
|
407
|
+
"tools": MCP_TOOLS
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
elif method == "tools/call":
|
|
412
|
+
params = msg.get("params", {})
|
|
413
|
+
tool_name = params.get("name")
|
|
414
|
+
arguments = params.get("arguments", {})
|
|
415
|
+
try:
|
|
416
|
+
output_text = handle_tool_call(tool_name, arguments)
|
|
417
|
+
return {
|
|
418
|
+
"jsonrpc": "2.0",
|
|
419
|
+
"id": msg_id,
|
|
420
|
+
"result": {
|
|
421
|
+
"content": [
|
|
422
|
+
{
|
|
423
|
+
"type": "text",
|
|
424
|
+
"text": output_text
|
|
425
|
+
}
|
|
426
|
+
],
|
|
427
|
+
"isError": False
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
except Exception as e:
|
|
431
|
+
return {
|
|
432
|
+
"jsonrpc": "2.0",
|
|
433
|
+
"id": msg_id,
|
|
434
|
+
"result": {
|
|
435
|
+
"content": [
|
|
436
|
+
{
|
|
437
|
+
"type": "text",
|
|
438
|
+
"text": f"Error executing {tool_name}: {str(e)}\n{traceback.format_exc()}"
|
|
439
|
+
}
|
|
440
|
+
],
|
|
441
|
+
"isError": True
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
elif method == "ping":
|
|
446
|
+
return {"jsonrpc": "2.0", "id": msg_id, "result": {}}
|
|
447
|
+
|
|
448
|
+
return {
|
|
449
|
+
"jsonrpc": "2.0",
|
|
450
|
+
"id": msg_id,
|
|
451
|
+
"error": {
|
|
452
|
+
"code": -32601,
|
|
453
|
+
"message": f"Method not found: {method}"
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def run_stdio_server():
|
|
459
|
+
"""Runs the MCP server over standard input/output."""
|
|
460
|
+
while True:
|
|
461
|
+
try:
|
|
462
|
+
line = sys.stdin.readline()
|
|
463
|
+
if not line:
|
|
464
|
+
break
|
|
465
|
+
line = line.strip()
|
|
466
|
+
if not line:
|
|
467
|
+
continue
|
|
468
|
+
|
|
469
|
+
msg = json.loads(line)
|
|
470
|
+
response = process_message(msg)
|
|
471
|
+
if response is not None:
|
|
472
|
+
sys.stdout.write(json.dumps(response) + "\n")
|
|
473
|
+
sys.stdout.flush()
|
|
474
|
+
except KeyboardInterrupt:
|
|
475
|
+
break
|
|
476
|
+
except Exception as e:
|
|
477
|
+
err_resp = {
|
|
478
|
+
"jsonrpc": "2.0",
|
|
479
|
+
"id": None,
|
|
480
|
+
"error": {
|
|
481
|
+
"code": -32700,
|
|
482
|
+
"message": f"Parse error: {str(e)}"
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
sys.stdout.write(json.dumps(err_resp) + "\n")
|
|
486
|
+
sys.stdout.flush()
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
if __name__ == "__main__":
|
|
490
|
+
run_stdio_server()
|