travis234-websec-mcp 0.1.0__tar.gz

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.
Files changed (150) hide show
  1. travis234_websec_mcp-0.1.0/PKG-INFO +248 -0
  2. travis234_websec_mcp-0.1.0/README.md +233 -0
  3. travis234_websec_mcp-0.1.0/extensions/websec_mcp.py +11 -0
  4. travis234_websec_mcp-0.1.0/libexec/travis234-websec-mcp/server.py +10 -0
  5. travis234_websec_mcp-0.1.0/pyproject.toml +46 -0
  6. travis234_websec_mcp-0.1.0/setup.cfg +4 -0
  7. travis234_websec_mcp-0.1.0/tests/test_acceptance.py +42 -0
  8. travis234_websec_mcp-0.1.0/tests/test_application.py +222 -0
  9. travis234_websec_mcp-0.1.0/tests/test_comparison.py +179 -0
  10. travis234_websec_mcp-0.1.0/tests/test_config.py +97 -0
  11. travis234_websec_mcp-0.1.0/tests/test_container_qualification.py +69 -0
  12. travis234_websec_mcp-0.1.0/tests/test_exports.py +334 -0
  13. travis234_websec_mcp-0.1.0/tests/test_extension.py +181 -0
  14. travis234_websec_mcp-0.1.0/tests/test_http_executor.py +1020 -0
  15. travis234_websec_mcp-0.1.0/tests/test_http_fixture.py +47 -0
  16. travis234_websec_mcp-0.1.0/tests/test_installed_contract.py +61 -0
  17. travis234_websec_mcp-0.1.0/tests/test_installed_wheel.py +137 -0
  18. travis234_websec_mcp-0.1.0/tests/test_matching.py +221 -0
  19. travis234_websec_mcp-0.1.0/tests/test_mcp_output.py +86 -0
  20. travis234_websec_mcp-0.1.0/tests/test_mcp_protocol.py +324 -0
  21. travis234_websec_mcp-0.1.0/tests/test_presentation.py +78 -0
  22. travis234_websec_mcp-0.1.0/tests/test_prompt_compatibility.py +114 -0
  23. travis234_websec_mcp-0.1.0/tests/test_protocol_redaction.py +39 -0
  24. travis234_websec_mcp-0.1.0/tests/test_raw_request.py +53 -0
  25. travis234_websec_mcp-0.1.0/tests/test_redaction.py +574 -0
  26. travis234_websec_mcp-0.1.0/tests/test_rendering.py +41 -0
  27. travis234_websec_mcp-0.1.0/tests/test_requests.py +81 -0
  28. travis234_websec_mcp-0.1.0/tests/test_results.py +25 -0
  29. travis234_websec_mcp-0.1.0/tests/test_scope.py +43 -0
  30. travis234_websec_mcp-0.1.0/tests/test_sdk_rendering.py +31 -0
  31. travis234_websec_mcp-0.1.0/tests/test_skill_protocol.py +77 -0
  32. travis234_websec_mcp-0.1.0/tests/test_stdio_io.py +251 -0
  33. travis234_websec_mcp-0.1.0/tests/test_store.py +99 -0
  34. travis234_websec_mcp-0.1.0/tests/test_transforms.py +90 -0
  35. travis234_websec_mcp-0.1.0/travis234_websec_mcp/__init__.py +1 -0
  36. travis234_websec_mcp-0.1.0/travis234_websec_mcp/analysis_budget.py +35 -0
  37. travis234_websec_mcp-0.1.0/travis234_websec_mcp/application.py +145 -0
  38. travis234_websec_mcp-0.1.0/travis234_websec_mcp/cli.py +52 -0
  39. travis234_websec_mcp-0.1.0/travis234_websec_mcp/comparison.py +49 -0
  40. travis234_websec_mcp-0.1.0/travis234_websec_mcp/config.py +103 -0
  41. travis234_websec_mcp-0.1.0/travis234_websec_mcp/errors.py +7 -0
  42. travis234_websec_mcp-0.1.0/travis234_websec_mcp/exports.py +134 -0
  43. travis234_websec_mcp-0.1.0/travis234_websec_mcp/extension.py +10 -0
  44. travis234_websec_mcp-0.1.0/travis234_websec_mcp/host.py +93 -0
  45. travis234_websec_mcp-0.1.0/travis234_websec_mcp/http_executor.py +133 -0
  46. travis234_websec_mcp-0.1.0/travis234_websec_mcp/lifetime.py +22 -0
  47. travis234_websec_mcp-0.1.0/travis234_websec_mcp/limits.py +21 -0
  48. travis234_websec_mcp-0.1.0/travis234_websec_mcp/matching.py +184 -0
  49. travis234_websec_mcp-0.1.0/travis234_websec_mcp/mcp_output.py +73 -0
  50. travis234_websec_mcp-0.1.0/travis234_websec_mcp/mcp_server.py +131 -0
  51. travis234_websec_mcp-0.1.0/travis234_websec_mcp/presentation.py +69 -0
  52. travis234_websec_mcp-0.1.0/travis234_websec_mcp/raw_request.py +57 -0
  53. travis234_websec_mcp-0.1.0/travis234_websec_mcp/redaction.py +324 -0
  54. travis234_websec_mcp-0.1.0/travis234_websec_mcp/rendering.py +151 -0
  55. travis234_websec_mcp-0.1.0/travis234_websec_mcp/requests.py +101 -0
  56. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/SOURCES.json +525 -0
  57. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ai-security/LICENSE.txt +21 -0
  58. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ai-security/SKILL.md +602 -0
  59. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ai-security/TRAVIS234.md +50 -0
  60. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-api-security/LICENSE.txt +21 -0
  61. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-api-security/SKILL.md +511 -0
  62. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-api-security/TRAVIS234.md +50 -0
  63. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-idor/LICENSE.txt +21 -0
  64. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-idor/SKILL.md +618 -0
  65. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-idor/TRAVIS234.md +50 -0
  66. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-jwt/LICENSE.txt +21 -0
  67. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-jwt/SKILL.md +281 -0
  68. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-jwt/TRAVIS234.md +50 -0
  69. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-reporting/LICENSE.txt +21 -0
  70. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-reporting/SKILL.md +378 -0
  71. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-reporting/TRAVIS234.md +50 -0
  72. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssrf/LICENSE.txt +21 -0
  73. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssrf/SKILL.md +840 -0
  74. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssrf/TRAVIS234.md +50 -0
  75. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssti/LICENSE.txt +21 -0
  76. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssti/SKILL.md +626 -0
  77. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssti/TRAVIS234.md +50 -0
  78. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/LICENSE.txt +21 -0
  79. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/SKILL.md +43 -0
  80. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/TRAVIS234.md +50 -0
  81. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/INDEX.md +75 -0
  82. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/access-control-resources.md +133 -0
  83. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/business-logic-resources.md +130 -0
  84. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/information-disclosure-resources.md +166 -0
  85. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/race-conditions-resources.md +132 -0
  86. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/data-leakage-redirect.md +73 -0
  87. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/header-bypass.md +169 -0
  88. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/idor-action.md +65 -0
  89. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/idor-read.md +176 -0
  90. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/mass-assignment.md +118 -0
  91. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/method-bypass.md +102 -0
  92. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/multi-step-bypass.md +63 -0
  93. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/parameter-based-controls.md +114 -0
  94. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/referer-bypass.md +58 -0
  95. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/unprotected-functionality.md +86 -0
  96. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/burp-extension-scanner.md +146 -0
  97. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/coupon-stacking.md +243 -0
  98. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/csrf-and-session-bypass.md +117 -0
  99. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/email-domain-bypass.md +123 -0
  100. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/gift-card-loop.md +265 -0
  101. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/parameter-pollution.md +249 -0
  102. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/price-manipulation.md +183 -0
  103. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/quantity-manipulation.md +267 -0
  104. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/regex-input-validation-bypass.md +53 -0
  105. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/workflow-bypass.md +150 -0
  106. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/deception-delimiter.md +119 -0
  107. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/deception-normalization.md +109 -0
  108. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/deception-path-mapping.md +123 -0
  109. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/deception-via-smuggling.md +60 -0
  110. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/poisoning-body-args.md +99 -0
  111. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/poisoning-setnx-race.md +132 -0
  112. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/poisoning-unkeyed-headers.md +239 -0
  113. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/poisoning-unkeyed-params.md +222 -0
  114. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/backups-and-version-control.md +167 -0
  115. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/client-side-storage-audit.md +88 -0
  116. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/debug-pages-and-cms-apis.md +133 -0
  117. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/error-messages.md +106 -0
  118. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/http-method-disclosure.md +103 -0
  119. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/javascript-source-review.md +81 -0
  120. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/multi-port-and-storage-discovery.md +117 -0
  121. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/security-headers-audit.md +134 -0
  122. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/advanced-techniques.md +205 -0
  123. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/container-startup-admin-registration.md +75 -0
  124. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/detection-and-baseline.md +273 -0
  125. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/file-upload-race.md +102 -0
  126. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/limit-overrun.md +90 -0
  127. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/multi-endpoint.md +102 -0
  128. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/partial-construction.md +87 -0
  129. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/rate-limit-bypass.md +107 -0
  130. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/single-endpoint-collision.md +78 -0
  131. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/timestamp-collision.md +81 -0
  132. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/toctou-session.md +132 -0
  133. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/web-app-logic-principles.md +59 -0
  134. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/web-cache-deception-resources.md +135 -0
  135. travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/web-cache-poisoning-resources.md +169 -0
  136. travis234_websec_mcp-0.1.0/travis234_websec_mcp/results.py +21 -0
  137. travis234_websec_mcp-0.1.0/travis234_websec_mcp/schemas.py +87 -0
  138. travis234_websec_mcp-0.1.0/travis234_websec_mcp/scope.py +54 -0
  139. travis234_websec_mcp-0.1.0/travis234_websec_mcp/skill_library.py +166 -0
  140. travis234_websec_mcp-0.1.0/travis234_websec_mcp/stdio_io.py +149 -0
  141. travis234_websec_mcp-0.1.0/travis234_websec_mcp/store.py +73 -0
  142. travis234_websec_mcp-0.1.0/travis234_websec_mcp/transforms.py +65 -0
  143. travis234_websec_mcp-0.1.0/travis234_websec_mcp/transport.py +94 -0
  144. travis234_websec_mcp-0.1.0/travis234_websec_mcp/types.py +50 -0
  145. travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/PKG-INFO +248 -0
  146. travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/SOURCES.txt +148 -0
  147. travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/dependency_links.txt +1 -0
  148. travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/entry_points.txt +2 -0
  149. travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/requires.txt +7 -0
  150. travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/top_level.txt +1 -0
@@ -0,0 +1,248 @@
1
+ Metadata-Version: 2.4
2
+ Name: travis234-websec-mcp
3
+ Version: 0.1.0
4
+ Summary: Independent bounded HTTP security workbench for MCP clients and Travis234.
5
+ License-Expression: MIT
6
+ Requires-Python: <3.14,>=3.13
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: mcp<3,>=2.2
9
+ Requires-Dist: pydantic<3,>=2.12
10
+ Requires-Dist: httpx<1,>=0.27
11
+ Requires-Dist: httpcore<2,>=1
12
+ Requires-Dist: anyio<5,>=4
13
+ Requires-Dist: ahocorasick-rs<2,>=1.0.3
14
+ Requires-Dist: travis234-mcp-adapter<0.5,>=0.4
15
+
16
+ # Travis234 Websec MCP
17
+
18
+ An optional external HTTP workbench for Travis234 and standard stdio MCP clients.
19
+ Python 3.13 and macOS or Linux are required. Travis core and its existing MCP
20
+ adapter supply the host integration; this package owns requests, HTTP execution,
21
+ sanitization and evidence. KHackBar is a workflow reference and is not a dependency.
22
+
23
+ This milestone supports individual request experiments. Payload catalogs,
24
+ generators, batch fuzzing, login/token extraction and browser capture remain
25
+ future work. The package also includes imported assessment skills, built into
26
+ Travis and exposed to other clients through MCP
27
+ resources and prompts. These guides do not install external scanners. See the repository's
28
+ [complete KHackBar feature mapping](../../docs/verification/2026-10-18-khackbar-feature-crosscheck.md).
29
+
30
+ ## Build, install and activate
31
+
32
+ Run these commands from the Travis234 repository root:
33
+
34
+ ```sh
35
+ uv sync --project packages/travis234-websec-mcp --locked --group source-test
36
+ websec_dist_dir="$(mktemp -d "${TMPDIR:-/tmp}/websec-dist.XXXXXX")"
37
+ uv build --wheel --out-dir "$websec_dist_dir" packages/travis234-mcp-adapter
38
+ uv build --wheel --out-dir "$websec_dist_dir" packages/travis234-websec-mcp
39
+ export PIP_FIND_LINKS="$websec_dist_dir"
40
+ export UV_FIND_LINKS="$websec_dist_dir"
41
+ websec_wheel_uri="$(packages/travis234-websec-mcp/.venv/bin/python -c 'from pathlib import Path; import sys; print(next(Path(sys.argv[1]).glob("travis234_websec_mcp-*.whl")).resolve().as_uri())' "$websec_dist_dir")"
42
+ travis234 install "travis234-websec-mcp @ $websec_wheel_uri"
43
+ travis234 --tools read,bash,websec
44
+ ```
45
+
46
+ Installation registers the package-owned server and one `websec` facade through
47
+ the shared adapter. Discovery and `status` do not send a testing request. Tool
48
+ selection uses the existing `--tools` allowlist; there is no new Travis flag.
49
+
50
+ For another MCP client, install the wheel and its dependencies into that client's
51
+ Python 3.13 environment, then configure this stdio command:
52
+
53
+ ```sh
54
+ travis234-websec-mcp mcp --transport stdio
55
+ ```
56
+
57
+ The standalone server does not import the Travis extension. It uses the same
58
+ configuration, request bounds and evidence format.
59
+
60
+ ## Imported assessment skills
61
+
62
+ The source index is
63
+ [htooayelwinict/awesome-ai-offensive-security](https://github.com/htooayelwinict/awesome-ai-offensive-security/tree/0e3180f4a0ffd5b6703943cf112d85017895a842).
64
+ That repository contains links; the actual skills are imported from these
65
+ linked MIT-licensed projects at fixed revisions:
66
+
67
+ | Source | Included skills |
68
+ | --- | --- |
69
+ | [SnailSploit/Claude-Red](https://github.com/SnailSploit/Claude-Red/tree/a8de813edc9f66f60d44cfe42d47750e89d9930b) | `offensive-api-security`, `offensive-jwt`, `offensive-idor`, `offensive-ssrf`, `offensive-ssti`, `offensive-ai-security`, `offensive-reporting` |
70
+ | [transilienceai/communitytools](https://github.com/transilienceai/communitytools/tree/95fdc128af4ca1ae16b3226f9430f1bad97b0656/skills/web-app-logic) | `web-app-logic`, including its reference and scenario files |
71
+
72
+ All eight skills ship as read-only built-ins in Travis's Python and npm
73
+ distributions, using its existing lazy loader, precedence and trust rules.
74
+ Installing this optional package adds the Websec tools. When the user asks to
75
+ use Websec MCP, its facade instructs the agent to try loading all eight
76
+ SKILL.md guides before its first Websec call, like Evidence MCP's research
77
+ skill. This guidance also accompanies authorized delegation. User overrides
78
+ and `--no-skills` remain effective; unavailable guides are reported. Additional
79
+ reference files load only as needed. The package does not register duplicate
80
+ skill directories. A standalone installation exposes the same documents
81
+ through MCP resources and prompts. No skill is copied into the user's Codex installation.
82
+
83
+ Each imported skill has a `TRAVIS234.md` guide describing the supported tools
84
+ and request workflow. Local changes add compatible YAML metadata and a link to
85
+ that guide. Upstream methodology and references are retained. Each skill keeps
86
+ its upstream license; [SOURCES.json](travis234_websec_mcp/resources/skills/SOURCES.json)
87
+ records repository revisions, source paths, original hashes and shipped hashes.
88
+ Imports are bundled: startup, discovery and reads do not fetch updates or run
89
+ upstream code.
90
+
91
+ For a standard MCP client:
92
+
93
+ - `resources/list` enumerates skill documents in pages of eight. Pass its
94
+ `nextCursor` back as `cursor` until it is absent.
95
+ - Read `websec://skills/index` for the skill index, then a skill's
96
+ `websec://skills/<name>/TRAVIS234.md` and `websec://skills/<name>/SKILL.md`.
97
+ - A document larger than 4 KiB returns an ordered part index. Read the listed
98
+ `?part=1`, `?part=2`, … URIs in order. All bytes are retained, with UTF-8
99
+ characters kept intact. Relative references resolve within the skill's URI
100
+ directory. Each part is at most 4 KiB before protocol encoding. When literal
101
+ code examples cannot pass the existing text classifier unchanged, the read
102
+ uses a standard MCP blob with the same MIME type: Base64-decode it as UTF-8
103
+ to recover the exact text.
104
+ - `prompts/list` exposes eight entry prompts, named `websec-<skill-name>`.
105
+ `prompts/get` takes that name and no arguments; it directs the client to the
106
+ integration guide and relevant upstream resources.
107
+
108
+ Resource reads accept only bundled catalog URIs. Unknown URIs, prompts and
109
+ cursors return fixed errors. The original document is checked before any part
110
+ is returned, and the existing final MCP frame checks still apply. When a known
111
+ credential overlaps a document, its read fails without returning that document.
112
+
113
+ The existing seven request operations retain their contracts. Browser sessions,
114
+ raw protocol experiments, parallel probes and external tools mentioned in a
115
+ guide require those capabilities separately. Imported methodology does not
116
+ enable them in the Websec executor.
117
+
118
+ ## Try the actual acceptance fixture
119
+
120
+ In one terminal, start the bundled fixture. It prints its actual loopback origin:
121
+
122
+ ```sh
123
+ packages/travis234-websec-mcp/.venv/bin/python packages/travis234-websec-mcp/tests/http_fixture.py
124
+ ```
125
+
126
+ Keep it running. In a second terminal, copy that origin into
127
+ `WEBSEC_FIXTURE_ORIGIN`, then create an isolated lab configuration:
128
+
129
+ ```sh
130
+ export WEBSEC_FIXTURE_ORIGIN='http://127.0.0.1:<printed-port>'
131
+ export WEBSEC_LAB_TOKEN='synthetic-lab-token'
132
+ websec_lab_dir="$(mktemp -d "${TMPDIR:-/tmp}/websec-lab.XXXXXX")"
133
+ export TRAVIS234_CODING_AGENT_DIR="$websec_lab_dir/agent"
134
+ packages/travis234-websec-mcp/.venv/bin/python - <<'PY'
135
+ import json
136
+ import os
137
+ from pathlib import Path
138
+ from urllib.parse import urlsplit
139
+
140
+ origin = os.environ['WEBSEC_FIXTURE_ORIGIN']
141
+ assert urlsplit(origin).hostname == '127.0.0.1' and urlsplit(origin).port
142
+ path = Path(os.environ['TRAVIS234_CODING_AGENT_DIR']) / 'websec' / 'config.json'
143
+ path.parent.mkdir(parents=True, exist_ok=True)
144
+ path.write_text(json.dumps({'version': 1, 'profiles': {'lab': {
145
+ 'origins': [origin],
146
+ 'headers': {'Authorization': 'Bearer ${WEBSEC_LAB_TOKEN}'},
147
+ 'deadline_seconds': 10,
148
+ }}}))
149
+ PY
150
+ ```
151
+
152
+ Run installation and activation in that same terminal so Travis inherits the
153
+ directory override and credential reference. Stop the fixture with Ctrl-C.
154
+ Normal operator configuration lives at `~/.travis234/agent/websec/config.json`;
155
+ the existing `TRAVIS234_CODING_AGENT_DIR` override changes the agent directory.
156
+ The package never loads `.env` files. Headers accept exact `$env:NAME` references
157
+ or `${NAME}` interpolation. Missing or empty references leave offline operations
158
+ available and make `send` return `authentication_unavailable` before connecting.
159
+
160
+ ## Request workflow
161
+
162
+ Call `websec` with the following operation arguments. Replace the fixture origin
163
+ with its printed value and copy each returned ID exactly:
164
+
165
+ | Operation | Arguments and result |
166
+ | --- | --- |
167
+ | `status` | `{}` or `{"operation":"status"}` returns configuration, profiles and limits. |
168
+ | `prepare` | `{"operation":"prepare","profile":"lab","request":{"url":"<fixture-origin>/query-echo?q=original&q=untouched"}}` creates an immutable request ID. Optional request fields are `method`, header pairs and a UTF-8 `body`. |
169
+ | `mutate` | `{"operation":"mutate","request_id":"<original-id>","location":"query","index":0,"value":"changed"}` creates a new ID. Header mutation is also indexed; body mutation replaces the whole body. |
170
+ | `transform` | `{"operation":"transform","value":"a b","codec":"url","direction":"encode"}` returns `a%20b`. Codecs are `url`, `base64`, `hex`, `double_url`, `html`, `unicode` and `reverse`; both directions are supported. |
171
+ | `send` | `{"operation":"send","request_id":"<request-id>"}` executes that snapshot once. Send the original and changed IDs separately. |
172
+ | `compare` | `{"operation":"compare","left_response_id":"<original-response-id>","right_response_id":"<changed-response-id>"}` returns measured differences, completeness and an optional sanitized diff. |
173
+ | `export` | The same response pair with `"operation":"export"` writes a new evidence file and returns its basename, ID and byte count. |
174
+
175
+ The fixture receives `original`, then `changed`, with the second query entry
176
+ unchanged. Its UTF-8 response bodies have 8 and 7 bytes respectively. Reusing the
177
+ original ID sends the original value again. `prepare` also accepts strict raw
178
+ HTTP/1.1 text using `raw_request` and an explicit `origin`, instead of `request`.
179
+ Ambiguous framing, invalid fields and unavailable IDs return specific bounded
180
+ errors. Comparisons report observations rather than vulnerability verdicts.
181
+
182
+ ### Additional text codecs
183
+
184
+ | Codec | Defined behavior |
185
+ | --- | --- |
186
+ | `double_url` | Apply the existing UTF-8 URL conversion exactly twice. Decoding rejects malformed percent escapes or invalid UTF-8 at either step. A literal `+` stays `+`. |
187
+ | `html` | Encode the five HTML special characters; the apostrophe becomes `&#x27;`. Decode named/numeric entities once using HTML5 rules. Markup stays text: decoding `&lt;b&gt;é&lt;/b&gt;` returns `<b>é</b>`. |
188
+ | `unicode` | Encode each UTF-16 unit as a lowercase `\uXXXX` escape, including valid pairs for supplementary characters. Decode those escapes once, combine valid surrogate pairs and reject malformed or unpaired units. Other backslash sequences and percent escapes stay literal. |
189
+ | `reverse` | Reverse Unicode code points. Both directions perform the same operation; `A😀é` becomes `é😀A`. Combining marks reverse individually. |
190
+
191
+ These operations retain the 16 KiB input and 64 KiB output limits. The aggregate
192
+ MCP frame limit also applies, so a valid engine result can return `output_limit`
193
+ at the public boundary. Errors never return a successful partial transformation.
194
+ Known credentials are checked in both the source value and the derived result.
195
+
196
+ ## Bounds, credentials and lifetime
197
+
198
+ Origins are exact normalized scheme/host/port allowlists. Every send checks its
199
+ final target. The client performs one exchange, follows no redirects, retries
200
+ nothing, carries no cookie jar, verifies TLS and ignores proxy environment
201
+ variables. Only one send runs at a time; an overlapping send returns `busy`.
202
+ Cancellation and shutdown close and join owned HTTP work.
203
+
204
+ | Resource | Limit |
205
+ | --- | --- |
206
+ | URL / request body / raw import | 8 / 64 / 128 KiB |
207
+ | Wire headers, including authentication and framing | 100 entries / 32 KiB |
208
+ | Transform input / output | 16 / 64 KiB |
209
+ | Deadline | Default 10 seconds; profile integer 1–30. A caller may only lower it with `timeout_seconds`. |
210
+ | Retained response / text preview | 1 MiB / 8 KiB |
211
+ | Requests / responses in memory | 32 / 16; unpinned oldest entries are evicted. |
212
+ | Complete outgoing MCP frame / exported JSON | 32 KiB / 4 MiB |
213
+
214
+ Compressed responses are reported as `unsupported_encoding` and are not decoded.
215
+ Binary and incomplete responses preserve honest byte measurements; comparison
216
+ does not infer complete text equality or an exact complete-body length from them.
217
+ Incomplete or oversized presentation values are withheld in full, with explicit
218
+ omission flags. Complete bounded JSON can retain unrelated public fields.
219
+
220
+ Keep credentials in the operator environment and profile references. Never paste
221
+ them into tool arguments: the host records those inputs before the plugin sees
222
+ them. Available referenced values and bounded URL/Base64/hex forms are sanitized
223
+ from returned results and exports. Authentication values go only to an allowed
224
+ origin's request.
225
+
226
+ Request and response IDs belong to one server process. Shutdown, reload or
227
+ eviction can invalidate them. Exports persist under
228
+ `<agent-directory>/websec/evidence/` as new atomic mode-0600 JSON files; the tool
229
+ does not accept arbitrary export paths or overwrite prior evidence.
230
+
231
+ Restart the entire Travis process after changing profile configuration,
232
+ credential references/environment or the installed package. Registrations are
233
+ process-local; an existing host does not replace a different descriptor in place.
234
+ Stop Travis before removing the package, then start a new process to confirm the
235
+ facade is absent. Removing the package preserves exported evidence.
236
+
237
+ ## Qualification
238
+
239
+ ```sh
240
+ PYTHONDONTWRITEBYTECODE=1 packages/travis234-websec-mcp/.venv/bin/python -m pytest -q -p no:cacheprovider packages/travis234-websec-mcp/tests
241
+ ```
242
+
243
+ The acceptance test builds actual wheels, installs through Travis's package
244
+ manager in a fresh interpreter outside the checkout, binds a real session, uses
245
+ a deterministic model stream and real HTTP/MCP transports, scans persisted
246
+ session JSONL, and checks A1–A13. Container qualification uses the same driver
247
+ with offline wheels, a nonroot user and Docker networking disabled. A build or
248
+ unit-test pass alone does not establish installed acceptance or deployment.
@@ -0,0 +1,233 @@
1
+ # Travis234 Websec MCP
2
+
3
+ An optional external HTTP workbench for Travis234 and standard stdio MCP clients.
4
+ Python 3.13 and macOS or Linux are required. Travis core and its existing MCP
5
+ adapter supply the host integration; this package owns requests, HTTP execution,
6
+ sanitization and evidence. KHackBar is a workflow reference and is not a dependency.
7
+
8
+ This milestone supports individual request experiments. Payload catalogs,
9
+ generators, batch fuzzing, login/token extraction and browser capture remain
10
+ future work. The package also includes imported assessment skills, built into
11
+ Travis and exposed to other clients through MCP
12
+ resources and prompts. These guides do not install external scanners. See the repository's
13
+ [complete KHackBar feature mapping](../../docs/verification/2026-10-18-khackbar-feature-crosscheck.md).
14
+
15
+ ## Build, install and activate
16
+
17
+ Run these commands from the Travis234 repository root:
18
+
19
+ ```sh
20
+ uv sync --project packages/travis234-websec-mcp --locked --group source-test
21
+ websec_dist_dir="$(mktemp -d "${TMPDIR:-/tmp}/websec-dist.XXXXXX")"
22
+ uv build --wheel --out-dir "$websec_dist_dir" packages/travis234-mcp-adapter
23
+ uv build --wheel --out-dir "$websec_dist_dir" packages/travis234-websec-mcp
24
+ export PIP_FIND_LINKS="$websec_dist_dir"
25
+ export UV_FIND_LINKS="$websec_dist_dir"
26
+ websec_wheel_uri="$(packages/travis234-websec-mcp/.venv/bin/python -c 'from pathlib import Path; import sys; print(next(Path(sys.argv[1]).glob("travis234_websec_mcp-*.whl")).resolve().as_uri())' "$websec_dist_dir")"
27
+ travis234 install "travis234-websec-mcp @ $websec_wheel_uri"
28
+ travis234 --tools read,bash,websec
29
+ ```
30
+
31
+ Installation registers the package-owned server and one `websec` facade through
32
+ the shared adapter. Discovery and `status` do not send a testing request. Tool
33
+ selection uses the existing `--tools` allowlist; there is no new Travis flag.
34
+
35
+ For another MCP client, install the wheel and its dependencies into that client's
36
+ Python 3.13 environment, then configure this stdio command:
37
+
38
+ ```sh
39
+ travis234-websec-mcp mcp --transport stdio
40
+ ```
41
+
42
+ The standalone server does not import the Travis extension. It uses the same
43
+ configuration, request bounds and evidence format.
44
+
45
+ ## Imported assessment skills
46
+
47
+ The source index is
48
+ [htooayelwinict/awesome-ai-offensive-security](https://github.com/htooayelwinict/awesome-ai-offensive-security/tree/0e3180f4a0ffd5b6703943cf112d85017895a842).
49
+ That repository contains links; the actual skills are imported from these
50
+ linked MIT-licensed projects at fixed revisions:
51
+
52
+ | Source | Included skills |
53
+ | --- | --- |
54
+ | [SnailSploit/Claude-Red](https://github.com/SnailSploit/Claude-Red/tree/a8de813edc9f66f60d44cfe42d47750e89d9930b) | `offensive-api-security`, `offensive-jwt`, `offensive-idor`, `offensive-ssrf`, `offensive-ssti`, `offensive-ai-security`, `offensive-reporting` |
55
+ | [transilienceai/communitytools](https://github.com/transilienceai/communitytools/tree/95fdc128af4ca1ae16b3226f9430f1bad97b0656/skills/web-app-logic) | `web-app-logic`, including its reference and scenario files |
56
+
57
+ All eight skills ship as read-only built-ins in Travis's Python and npm
58
+ distributions, using its existing lazy loader, precedence and trust rules.
59
+ Installing this optional package adds the Websec tools. When the user asks to
60
+ use Websec MCP, its facade instructs the agent to try loading all eight
61
+ SKILL.md guides before its first Websec call, like Evidence MCP's research
62
+ skill. This guidance also accompanies authorized delegation. User overrides
63
+ and `--no-skills` remain effective; unavailable guides are reported. Additional
64
+ reference files load only as needed. The package does not register duplicate
65
+ skill directories. A standalone installation exposes the same documents
66
+ through MCP resources and prompts. No skill is copied into the user's Codex installation.
67
+
68
+ Each imported skill has a `TRAVIS234.md` guide describing the supported tools
69
+ and request workflow. Local changes add compatible YAML metadata and a link to
70
+ that guide. Upstream methodology and references are retained. Each skill keeps
71
+ its upstream license; [SOURCES.json](travis234_websec_mcp/resources/skills/SOURCES.json)
72
+ records repository revisions, source paths, original hashes and shipped hashes.
73
+ Imports are bundled: startup, discovery and reads do not fetch updates or run
74
+ upstream code.
75
+
76
+ For a standard MCP client:
77
+
78
+ - `resources/list` enumerates skill documents in pages of eight. Pass its
79
+ `nextCursor` back as `cursor` until it is absent.
80
+ - Read `websec://skills/index` for the skill index, then a skill's
81
+ `websec://skills/<name>/TRAVIS234.md` and `websec://skills/<name>/SKILL.md`.
82
+ - A document larger than 4 KiB returns an ordered part index. Read the listed
83
+ `?part=1`, `?part=2`, … URIs in order. All bytes are retained, with UTF-8
84
+ characters kept intact. Relative references resolve within the skill's URI
85
+ directory. Each part is at most 4 KiB before protocol encoding. When literal
86
+ code examples cannot pass the existing text classifier unchanged, the read
87
+ uses a standard MCP blob with the same MIME type: Base64-decode it as UTF-8
88
+ to recover the exact text.
89
+ - `prompts/list` exposes eight entry prompts, named `websec-<skill-name>`.
90
+ `prompts/get` takes that name and no arguments; it directs the client to the
91
+ integration guide and relevant upstream resources.
92
+
93
+ Resource reads accept only bundled catalog URIs. Unknown URIs, prompts and
94
+ cursors return fixed errors. The original document is checked before any part
95
+ is returned, and the existing final MCP frame checks still apply. When a known
96
+ credential overlaps a document, its read fails without returning that document.
97
+
98
+ The existing seven request operations retain their contracts. Browser sessions,
99
+ raw protocol experiments, parallel probes and external tools mentioned in a
100
+ guide require those capabilities separately. Imported methodology does not
101
+ enable them in the Websec executor.
102
+
103
+ ## Try the actual acceptance fixture
104
+
105
+ In one terminal, start the bundled fixture. It prints its actual loopback origin:
106
+
107
+ ```sh
108
+ packages/travis234-websec-mcp/.venv/bin/python packages/travis234-websec-mcp/tests/http_fixture.py
109
+ ```
110
+
111
+ Keep it running. In a second terminal, copy that origin into
112
+ `WEBSEC_FIXTURE_ORIGIN`, then create an isolated lab configuration:
113
+
114
+ ```sh
115
+ export WEBSEC_FIXTURE_ORIGIN='http://127.0.0.1:<printed-port>'
116
+ export WEBSEC_LAB_TOKEN='synthetic-lab-token'
117
+ websec_lab_dir="$(mktemp -d "${TMPDIR:-/tmp}/websec-lab.XXXXXX")"
118
+ export TRAVIS234_CODING_AGENT_DIR="$websec_lab_dir/agent"
119
+ packages/travis234-websec-mcp/.venv/bin/python - <<'PY'
120
+ import json
121
+ import os
122
+ from pathlib import Path
123
+ from urllib.parse import urlsplit
124
+
125
+ origin = os.environ['WEBSEC_FIXTURE_ORIGIN']
126
+ assert urlsplit(origin).hostname == '127.0.0.1' and urlsplit(origin).port
127
+ path = Path(os.environ['TRAVIS234_CODING_AGENT_DIR']) / 'websec' / 'config.json'
128
+ path.parent.mkdir(parents=True, exist_ok=True)
129
+ path.write_text(json.dumps({'version': 1, 'profiles': {'lab': {
130
+ 'origins': [origin],
131
+ 'headers': {'Authorization': 'Bearer ${WEBSEC_LAB_TOKEN}'},
132
+ 'deadline_seconds': 10,
133
+ }}}))
134
+ PY
135
+ ```
136
+
137
+ Run installation and activation in that same terminal so Travis inherits the
138
+ directory override and credential reference. Stop the fixture with Ctrl-C.
139
+ Normal operator configuration lives at `~/.travis234/agent/websec/config.json`;
140
+ the existing `TRAVIS234_CODING_AGENT_DIR` override changes the agent directory.
141
+ The package never loads `.env` files. Headers accept exact `$env:NAME` references
142
+ or `${NAME}` interpolation. Missing or empty references leave offline operations
143
+ available and make `send` return `authentication_unavailable` before connecting.
144
+
145
+ ## Request workflow
146
+
147
+ Call `websec` with the following operation arguments. Replace the fixture origin
148
+ with its printed value and copy each returned ID exactly:
149
+
150
+ | Operation | Arguments and result |
151
+ | --- | --- |
152
+ | `status` | `{}` or `{"operation":"status"}` returns configuration, profiles and limits. |
153
+ | `prepare` | `{"operation":"prepare","profile":"lab","request":{"url":"<fixture-origin>/query-echo?q=original&q=untouched"}}` creates an immutable request ID. Optional request fields are `method`, header pairs and a UTF-8 `body`. |
154
+ | `mutate` | `{"operation":"mutate","request_id":"<original-id>","location":"query","index":0,"value":"changed"}` creates a new ID. Header mutation is also indexed; body mutation replaces the whole body. |
155
+ | `transform` | `{"operation":"transform","value":"a b","codec":"url","direction":"encode"}` returns `a%20b`. Codecs are `url`, `base64`, `hex`, `double_url`, `html`, `unicode` and `reverse`; both directions are supported. |
156
+ | `send` | `{"operation":"send","request_id":"<request-id>"}` executes that snapshot once. Send the original and changed IDs separately. |
157
+ | `compare` | `{"operation":"compare","left_response_id":"<original-response-id>","right_response_id":"<changed-response-id>"}` returns measured differences, completeness and an optional sanitized diff. |
158
+ | `export` | The same response pair with `"operation":"export"` writes a new evidence file and returns its basename, ID and byte count. |
159
+
160
+ The fixture receives `original`, then `changed`, with the second query entry
161
+ unchanged. Its UTF-8 response bodies have 8 and 7 bytes respectively. Reusing the
162
+ original ID sends the original value again. `prepare` also accepts strict raw
163
+ HTTP/1.1 text using `raw_request` and an explicit `origin`, instead of `request`.
164
+ Ambiguous framing, invalid fields and unavailable IDs return specific bounded
165
+ errors. Comparisons report observations rather than vulnerability verdicts.
166
+
167
+ ### Additional text codecs
168
+
169
+ | Codec | Defined behavior |
170
+ | --- | --- |
171
+ | `double_url` | Apply the existing UTF-8 URL conversion exactly twice. Decoding rejects malformed percent escapes or invalid UTF-8 at either step. A literal `+` stays `+`. |
172
+ | `html` | Encode the five HTML special characters; the apostrophe becomes `&#x27;`. Decode named/numeric entities once using HTML5 rules. Markup stays text: decoding `&lt;b&gt;é&lt;/b&gt;` returns `<b>é</b>`. |
173
+ | `unicode` | Encode each UTF-16 unit as a lowercase `\uXXXX` escape, including valid pairs for supplementary characters. Decode those escapes once, combine valid surrogate pairs and reject malformed or unpaired units. Other backslash sequences and percent escapes stay literal. |
174
+ | `reverse` | Reverse Unicode code points. Both directions perform the same operation; `A😀é` becomes `é😀A`. Combining marks reverse individually. |
175
+
176
+ These operations retain the 16 KiB input and 64 KiB output limits. The aggregate
177
+ MCP frame limit also applies, so a valid engine result can return `output_limit`
178
+ at the public boundary. Errors never return a successful partial transformation.
179
+ Known credentials are checked in both the source value and the derived result.
180
+
181
+ ## Bounds, credentials and lifetime
182
+
183
+ Origins are exact normalized scheme/host/port allowlists. Every send checks its
184
+ final target. The client performs one exchange, follows no redirects, retries
185
+ nothing, carries no cookie jar, verifies TLS and ignores proxy environment
186
+ variables. Only one send runs at a time; an overlapping send returns `busy`.
187
+ Cancellation and shutdown close and join owned HTTP work.
188
+
189
+ | Resource | Limit |
190
+ | --- | --- |
191
+ | URL / request body / raw import | 8 / 64 / 128 KiB |
192
+ | Wire headers, including authentication and framing | 100 entries / 32 KiB |
193
+ | Transform input / output | 16 / 64 KiB |
194
+ | Deadline | Default 10 seconds; profile integer 1–30. A caller may only lower it with `timeout_seconds`. |
195
+ | Retained response / text preview | 1 MiB / 8 KiB |
196
+ | Requests / responses in memory | 32 / 16; unpinned oldest entries are evicted. |
197
+ | Complete outgoing MCP frame / exported JSON | 32 KiB / 4 MiB |
198
+
199
+ Compressed responses are reported as `unsupported_encoding` and are not decoded.
200
+ Binary and incomplete responses preserve honest byte measurements; comparison
201
+ does not infer complete text equality or an exact complete-body length from them.
202
+ Incomplete or oversized presentation values are withheld in full, with explicit
203
+ omission flags. Complete bounded JSON can retain unrelated public fields.
204
+
205
+ Keep credentials in the operator environment and profile references. Never paste
206
+ them into tool arguments: the host records those inputs before the plugin sees
207
+ them. Available referenced values and bounded URL/Base64/hex forms are sanitized
208
+ from returned results and exports. Authentication values go only to an allowed
209
+ origin's request.
210
+
211
+ Request and response IDs belong to one server process. Shutdown, reload or
212
+ eviction can invalidate them. Exports persist under
213
+ `<agent-directory>/websec/evidence/` as new atomic mode-0600 JSON files; the tool
214
+ does not accept arbitrary export paths or overwrite prior evidence.
215
+
216
+ Restart the entire Travis process after changing profile configuration,
217
+ credential references/environment or the installed package. Registrations are
218
+ process-local; an existing host does not replace a different descriptor in place.
219
+ Stop Travis before removing the package, then start a new process to confirm the
220
+ facade is absent. Removing the package preserves exported evidence.
221
+
222
+ ## Qualification
223
+
224
+ ```sh
225
+ PYTHONDONTWRITEBYTECODE=1 packages/travis234-websec-mcp/.venv/bin/python -m pytest -q -p no:cacheprovider packages/travis234-websec-mcp/tests
226
+ ```
227
+
228
+ The acceptance test builds actual wheels, installs through Travis's package
229
+ manager in a fresh interpreter outside the checkout, binds a real session, uses
230
+ a deterministic model stream and real HTTP/MCP transports, scans persisted
231
+ session JSONL, and checks A1–A13. Container qualification uses the same driver
232
+ with offline wheels, a nonroot user and Docker networking disabled. A build or
233
+ unit-test pass alone does not establish installed acceptance or deployment.
@@ -0,0 +1,11 @@
1
+ from importlib import import_module
2
+ from pathlib import Path
3
+ import sys
4
+
5
+ payload_root = Path(__file__).resolve().parents[1]
6
+ if str(payload_root) not in sys.path:
7
+ sys.path.insert(0, str(payload_root))
8
+
9
+ extension = import_module("travis234_websec_mcp.extension").extension
10
+
11
+ __all__ = ["extension"]
@@ -0,0 +1,10 @@
1
+ from importlib import import_module
2
+ from pathlib import Path
3
+ import sys
4
+
5
+ payload_root = Path(__file__).resolve().parents[2]
6
+ if str(payload_root) not in sys.path:
7
+ sys.path.insert(0, str(payload_root))
8
+
9
+ module = import_module("travis234_websec_mcp.cli")
10
+ raise SystemExit(module.main())
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.3", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "travis234-websec-mcp"
7
+ version = "0.1.0"
8
+ description = "Independent bounded HTTP security workbench for MCP clients and Travis234."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.13,<3.14"
12
+ dependencies = [
13
+ "mcp>=2.2,<3",
14
+ "pydantic>=2.12,<3",
15
+ "httpx>=0.27,<1",
16
+ "httpcore>=1,<2",
17
+ "anyio>=4,<5",
18
+ "ahocorasick-rs>=1.0.3,<2",
19
+ "travis234-mcp-adapter>=0.4,<0.5",
20
+ ]
21
+
22
+ [project.scripts]
23
+ travis234-websec-mcp = "travis234_websec_mcp.cli:main"
24
+
25
+ [dependency-groups]
26
+ source-test = ["pytest>=8", "pytest-asyncio>=1", "travis234", "travis234-evidence-mcp"]
27
+
28
+ [tool.uv.sources]
29
+ travis234 = { path = "../..", editable = true }
30
+ travis234-evidence-mcp = { path = "../travis234-evidence-mcp", editable = true }
31
+ travis234-mcp-adapter = { path = "../travis234-mcp-adapter", editable = true }
32
+
33
+ [tool.setuptools.packages.find]
34
+ where = ["."]
35
+ include = ["travis234_websec_mcp*"]
36
+ namespaces = false
37
+
38
+ [tool.setuptools.package-data]
39
+ travis234_websec_mcp = ["resources/skills/**/*.md", "resources/skills/**/LICENSE.txt", "resources/skills/SOURCES.json"]
40
+
41
+ [tool.setuptools.data-files]
42
+ "libexec/travis234-websec-mcp" = ["libexec/travis234-websec-mcp/server.py"]
43
+ "extensions" = ["extensions/websec_mcp.py"]
44
+
45
+ [tool.pytest.ini_options]
46
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,42 @@
1
+ """Acceptance uses a fresh installed host, real session, MCP child and loopback."""
2
+
3
+ import hashlib
4
+ import json
5
+ from pathlib import Path
6
+ import shutil
7
+ import subprocess
8
+
9
+ from installed_support import REPOSITORY, installed_environment, run
10
+
11
+
12
+ def test_installed_artifact_satisfies_A1_through_A13(artifacts, tmp_path):
13
+ source = Path(__file__).with_name("acceptance_driver.py")
14
+ assert source.is_file(), "Missing planned installed-artifact acceptance driver."
15
+ built = artifacts()
16
+ python, environment = installed_environment(tmp_path / "installed", built)
17
+ project = tmp_path / "project"
18
+ project.mkdir()
19
+ for name in (source.name, "http_fixture.py", "skill_protocol_checks.py"):
20
+ shutil.copyfile(Path(__file__).with_name(name), project / name)
21
+ revision = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=REPOSITORY, text=True).strip()
22
+ report_path = tmp_path / "acceptance-report.json"
23
+ result = run([str(python), str(project / source.name), "--wheel", str(built.websec),
24
+ "--repository", str(REPOSITORY), "--source-revision", revision, "--report", str(report_path)],
25
+ cwd=project, environ=environment)
26
+ assert result.stderr == ""
27
+ report = json.loads(result.stdout)
28
+ assert json.loads(report_path.read_bytes()) == report
29
+ expected = {"A" + str(number) for number in range(1, 14)}
30
+ assert expected <= report.keys()
31
+ assert all(report[key]["passed"] is True and report[key]["observations"] for key in expected)
32
+ assert report["provenance"]["wheel_sha256"] == hashlib.sha256(built.websec.read_bytes()).hexdigest()
33
+ assert report["provenance"]["source_revision"] == revision
34
+ assert report["A3"]["observations"]["pair_values"] == ["original", "changed"]
35
+ assert report["A4"]["observations"]["body_bytes"] == [8, 7]
36
+ assert report["A8"]["observations"]["disconnect_seconds"] < 2
37
+ assert report["A10"]["observations"]["persisted_tool_results"] > 0
38
+ assert report["A12"]["observations"]["remaining_children"] == 0
39
+ assert report["A13"]["observations"]["skill_protocol"]["documents_reassembled"] == 80
40
+ assert report["A13"]["observations"]["skill_protocol"]["prompts_read"] == 8
41
+ assert "synthetic-websec-acceptance-private-token" not in result.stdout + result.stderr
42
+ print("Acceptance report:", report_path)