webmcp-cli 1.0.0 → 1.2.1

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 (347) hide show
  1. package/dist/agent/features/agent-simulator.d.ts +67 -0
  2. package/dist/agent/features/agent-simulator.js +368 -0
  3. package/dist/agent/features/agent-simulator.js.map +1 -0
  4. package/dist/agent/features/index.d.ts +8 -0
  5. package/dist/agent/features/index.js +9 -0
  6. package/dist/agent/features/index.js.map +1 -0
  7. package/dist/agent/features/simulation-judge.d.ts +78 -0
  8. package/dist/agent/features/simulation-judge.js +276 -0
  9. package/dist/agent/features/simulation-judge.js.map +1 -0
  10. package/dist/agent/features/test-case-generator.d.ts +35 -0
  11. package/dist/agent/features/test-case-generator.js +257 -0
  12. package/dist/agent/features/test-case-generator.js.map +1 -0
  13. package/dist/agent/index.d.ts +7 -0
  14. package/dist/agent/index.js +10 -0
  15. package/dist/agent/index.js.map +1 -0
  16. package/dist/agent/llm-client.d.ts +76 -0
  17. package/dist/agent/llm-client.js +198 -0
  18. package/dist/agent/llm-client.js.map +1 -0
  19. package/dist/audit/run-single-page-audit.d.ts +41 -0
  20. package/dist/audit/run-single-page-audit.js +103 -0
  21. package/dist/audit/run-single-page-audit.js.map +1 -0
  22. package/dist/bin/webmcp.d.ts +5 -0
  23. package/dist/bin/webmcp.js +14 -0
  24. package/dist/bin/webmcp.js.map +1 -0
  25. package/dist/browser/audit-runner.d.ts +30 -0
  26. package/dist/browser/audit-runner.js +77 -0
  27. package/dist/browser/audit-runner.js.map +1 -0
  28. package/dist/browser/index.d.ts +6 -0
  29. package/dist/browser/index.js +7 -0
  30. package/dist/browser/index.js.map +1 -0
  31. package/dist/browser/interceptor.d.ts +68 -0
  32. package/dist/browser/interceptor.js +257 -0
  33. package/dist/browser/interceptor.js.map +1 -0
  34. package/dist/browser/playwright.d.ts +98 -0
  35. package/dist/browser/playwright.js +158 -0
  36. package/dist/browser/playwright.js.map +1 -0
  37. package/dist/cli/commands/audit.d.ts +12 -0
  38. package/dist/cli/commands/audit.js +349 -0
  39. package/dist/cli/commands/audit.js.map +1 -0
  40. package/dist/cli/commands/interactive.d.ts +10 -0
  41. package/dist/cli/commands/interactive.js +34 -0
  42. package/dist/cli/commands/interactive.js.map +1 -0
  43. package/dist/cli/index.d.ts +17 -0
  44. package/dist/cli/index.js +84 -0
  45. package/dist/cli/index.js.map +1 -0
  46. package/dist/cli/options/parse-audit-options.d.ts +12 -0
  47. package/dist/cli/options/parse-audit-options.js +64 -0
  48. package/dist/cli/options/parse-audit-options.js.map +1 -0
  49. package/dist/core/constants.d.ts +102 -0
  50. package/dist/core/constants.js +214 -0
  51. package/dist/core/constants.js.map +1 -0
  52. package/dist/core/types/audit.d.ts +260 -0
  53. package/dist/core/types/audit.js +5 -0
  54. package/dist/core/types/audit.js.map +1 -0
  55. package/dist/core/types/index.d.ts +6 -0
  56. package/dist/core/types/index.js +7 -0
  57. package/dist/core/types/index.js.map +1 -0
  58. package/dist/core/types/rule.d.ts +190 -0
  59. package/dist/core/types/rule.js +26 -0
  60. package/dist/core/types/rule.js.map +1 -0
  61. package/dist/core/types/tool.d.ts +312 -0
  62. package/dist/core/types/tool.js +6 -0
  63. package/dist/core/types/tool.js.map +1 -0
  64. package/dist/detection/declarative.d.ts +27 -0
  65. package/dist/detection/declarative.js +343 -0
  66. package/dist/detection/declarative.js.map +1 -0
  67. package/dist/detection/imperative.d.ts +38 -0
  68. package/dist/detection/imperative.js +99 -0
  69. package/dist/detection/imperative.js.map +1 -0
  70. package/dist/detection/index.d.ts +5 -0
  71. package/dist/detection/index.js +6 -0
  72. package/dist/detection/index.js.map +1 -0
  73. package/dist/index.d.ts +12 -0
  74. package/dist/index.js +19 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/llm/advice-service.d.ts +38 -0
  77. package/dist/llm/advice-service.js +243 -0
  78. package/dist/llm/advice-service.js.map +1 -0
  79. package/dist/llm/evaluator.d.ts +89 -0
  80. package/dist/llm/evaluator.js +274 -0
  81. package/dist/llm/evaluator.js.map +1 -0
  82. package/dist/llm/index.d.ts +11 -0
  83. package/dist/llm/index.js +15 -0
  84. package/dist/llm/index.js.map +1 -0
  85. package/dist/llm/json-response.d.ts +12 -0
  86. package/dist/llm/json-response.js +67 -0
  87. package/dist/llm/json-response.js.map +1 -0
  88. package/dist/llm/providers/mock.d.ts +29 -0
  89. package/dist/llm/providers/mock.js +324 -0
  90. package/dist/llm/providers/mock.js.map +1 -0
  91. package/dist/llm/providers/openrouter.d.ts +53 -0
  92. package/dist/llm/providers/openrouter.js +321 -0
  93. package/dist/llm/providers/openrouter.js.map +1 -0
  94. package/dist/llm/request-cache.d.ts +28 -0
  95. package/dist/llm/request-cache.js +99 -0
  96. package/dist/llm/request-cache.js.map +1 -0
  97. package/dist/llm/types.d.ts +233 -0
  98. package/dist/llm/types.js +7 -0
  99. package/dist/llm/types.js.map +1 -0
  100. package/dist/rules/best-practices/BP-001.d.ts +11 -0
  101. package/dist/rules/best-practices/BP-001.js +56 -0
  102. package/dist/rules/best-practices/BP-001.js.map +1 -0
  103. package/dist/rules/best-practices/BP-002.d.ts +11 -0
  104. package/dist/rules/best-practices/BP-002.js +63 -0
  105. package/dist/rules/best-practices/BP-002.js.map +1 -0
  106. package/dist/rules/best-practices/BP-003.d.ts +11 -0
  107. package/dist/rules/best-practices/BP-003.js +68 -0
  108. package/dist/rules/best-practices/BP-003.js.map +1 -0
  109. package/dist/rules/coverage/COV-001.d.ts +8 -0
  110. package/dist/rules/coverage/COV-001.js +51 -0
  111. package/dist/rules/coverage/COV-001.js.map +1 -0
  112. package/dist/rules/description/DESC-003.d.ts +13 -0
  113. package/dist/rules/description/DESC-003.js +96 -0
  114. package/dist/rules/description/DESC-003.js.map +1 -0
  115. package/dist/rules/description/DESC-004.d.ts +8 -0
  116. package/dist/rules/description/DESC-004.js +61 -0
  117. package/dist/rules/description/DESC-004.js.map +1 -0
  118. package/dist/rules/description/DESC-005.d.ts +12 -0
  119. package/dist/rules/description/DESC-005.js +70 -0
  120. package/dist/rules/description/DESC-005.js.map +1 -0
  121. package/dist/rules/description/index.d.ts +4 -0
  122. package/dist/rules/description/index.js +5 -0
  123. package/dist/rules/description/index.js.map +1 -0
  124. package/dist/rules/implementation/IMP-001.d.ts +10 -0
  125. package/dist/rules/implementation/IMP-001.js +36 -0
  126. package/dist/rules/implementation/IMP-001.js.map +1 -0
  127. package/dist/rules/implementation/IMP-003.d.ts +9 -0
  128. package/dist/rules/implementation/IMP-003.js +45 -0
  129. package/dist/rules/implementation/IMP-003.js.map +1 -0
  130. package/dist/rules/implementation/IMP-004.d.ts +9 -0
  131. package/dist/rules/implementation/IMP-004.js +48 -0
  132. package/dist/rules/implementation/IMP-004.js.map +1 -0
  133. package/dist/rules/implementation/IMP-005.d.ts +9 -0
  134. package/dist/rules/implementation/IMP-005.js +54 -0
  135. package/dist/rules/implementation/IMP-005.js.map +1 -0
  136. package/dist/rules/implementation/IMP-007.d.ts +8 -0
  137. package/dist/rules/implementation/IMP-007.js +79 -0
  138. package/dist/rules/implementation/IMP-007.js.map +1 -0
  139. package/dist/rules/implementation/IMP-013.d.ts +9 -0
  140. package/dist/rules/implementation/IMP-013.js +55 -0
  141. package/dist/rules/implementation/IMP-013.js.map +1 -0
  142. package/dist/rules/implementation/index.d.ts +9 -0
  143. package/dist/rules/implementation/index.js +10 -0
  144. package/dist/rules/implementation/index.js.map +1 -0
  145. package/dist/rules/index.d.ts +51 -0
  146. package/dist/rules/index.js +100 -0
  147. package/dist/rules/index.js.map +1 -0
  148. package/dist/rules/llm/LLM-001.d.ts +14 -0
  149. package/dist/rules/llm/LLM-001.js +78 -0
  150. package/dist/rules/llm/LLM-001.js.map +1 -0
  151. package/dist/rules/llm/LLM-002.d.ts +14 -0
  152. package/dist/rules/llm/LLM-002.js +77 -0
  153. package/dist/rules/llm/LLM-002.js.map +1 -0
  154. package/dist/rules/llm/LLM-003.d.ts +16 -0
  155. package/dist/rules/llm/LLM-003.js +82 -0
  156. package/dist/rules/llm/LLM-003.js.map +1 -0
  157. package/dist/rules/llm/LLM-004.d.ts +14 -0
  158. package/dist/rules/llm/LLM-004.js +87 -0
  159. package/dist/rules/llm/LLM-004.js.map +1 -0
  160. package/dist/rules/llm/LLM-005.d.ts +16 -0
  161. package/dist/rules/llm/LLM-005.js +105 -0
  162. package/dist/rules/llm/LLM-005.js.map +1 -0
  163. package/dist/rules/llm/index.d.ts +10 -0
  164. package/dist/rules/llm/index.js +11 -0
  165. package/dist/rules/llm/index.js.map +1 -0
  166. package/dist/rules/runner.d.ts +54 -0
  167. package/dist/rules/runner.js +138 -0
  168. package/dist/rules/runner.js.map +1 -0
  169. package/dist/rules/schema/SCHEMA-001.d.ts +9 -0
  170. package/dist/rules/schema/SCHEMA-001.js +57 -0
  171. package/dist/rules/schema/SCHEMA-001.js.map +1 -0
  172. package/dist/rules/schema/SCHEMA-002.d.ts +9 -0
  173. package/dist/rules/schema/SCHEMA-002.js +59 -0
  174. package/dist/rules/schema/SCHEMA-002.js.map +1 -0
  175. package/dist/rules/schema/SCHEMA-003.d.ts +10 -0
  176. package/dist/rules/schema/SCHEMA-003.js +66 -0
  177. package/dist/rules/schema/SCHEMA-003.js.map +1 -0
  178. package/dist/rules/schema/SCHEMA-011.d.ts +10 -0
  179. package/dist/rules/schema/SCHEMA-011.js +62 -0
  180. package/dist/rules/schema/SCHEMA-011.js.map +1 -0
  181. package/dist/rules/security/SEC-001.d.ts +12 -0
  182. package/dist/rules/security/SEC-001.js +66 -0
  183. package/dist/rules/security/SEC-001.js.map +1 -0
  184. package/dist/rules/utils/keywords.d.ts +35 -0
  185. package/dist/rules/utils/keywords.js +100 -0
  186. package/dist/rules/utils/keywords.js.map +1 -0
  187. package/dist/scoring/calculator.d.ts +27 -0
  188. package/dist/scoring/calculator.js +194 -0
  189. package/dist/scoring/calculator.js.map +1 -0
  190. package/dist/scoring/grades.d.ts +34 -0
  191. package/dist/scoring/grades.js +167 -0
  192. package/dist/scoring/grades.js.map +1 -0
  193. package/dist/scoring/index.d.ts +5 -0
  194. package/dist/scoring/index.js +6 -0
  195. package/dist/scoring/index.js.map +1 -0
  196. package/dist/ui/banner.d.ts +21 -0
  197. package/dist/ui/banner.js +60 -0
  198. package/dist/ui/banner.js.map +1 -0
  199. package/dist/ui/design-tokens.d.ts +23 -0
  200. package/dist/ui/design-tokens.js +58 -0
  201. package/dist/ui/design-tokens.js.map +1 -0
  202. package/dist/ui/findings.d.ts +23 -0
  203. package/dist/ui/findings.js +190 -0
  204. package/dist/ui/findings.js.map +1 -0
  205. package/dist/ui/index.d.ts +9 -0
  206. package/dist/ui/index.js +10 -0
  207. package/dist/ui/index.js.map +1 -0
  208. package/dist/ui/ink/App.d.ts +14 -0
  209. package/dist/ui/ink/App.js +113 -0
  210. package/dist/ui/ink/App.js.map +1 -0
  211. package/dist/ui/ink/FullScreenLayout.d.ts +16 -0
  212. package/dist/ui/ink/FullScreenLayout.js +29 -0
  213. package/dist/ui/ink/FullScreenLayout.js.map +1 -0
  214. package/dist/ui/ink/InteractiveApp.d.ts +28 -0
  215. package/dist/ui/ink/InteractiveApp.js +229 -0
  216. package/dist/ui/ink/InteractiveApp.js.map +1 -0
  217. package/dist/ui/ink/RealAuditApp.d.ts +19 -0
  218. package/dist/ui/ink/RealAuditApp.js +170 -0
  219. package/dist/ui/ink/RealAuditApp.js.map +1 -0
  220. package/dist/ui/ink/components/AnimatedProgressBar.d.ts +20 -0
  221. package/dist/ui/ink/components/AnimatedProgressBar.js +46 -0
  222. package/dist/ui/ink/components/AnimatedProgressBar.js.map +1 -0
  223. package/dist/ui/ink/components/AsciiLogo.d.ts +12 -0
  224. package/dist/ui/ink/components/AsciiLogo.js +35 -0
  225. package/dist/ui/ink/components/AsciiLogo.js.map +1 -0
  226. package/dist/ui/ink/components/CategoryBars.d.ts +18 -0
  227. package/dist/ui/ink/components/CategoryBars.js +18 -0
  228. package/dist/ui/ink/components/CategoryBars.js.map +1 -0
  229. package/dist/ui/ink/components/FindingsTable.d.ts +18 -0
  230. package/dist/ui/ink/components/FindingsTable.js +19 -0
  231. package/dist/ui/ink/components/FindingsTable.js.map +1 -0
  232. package/dist/ui/ink/components/Footer.d.ts +15 -0
  233. package/dist/ui/ink/components/Footer.js +20 -0
  234. package/dist/ui/ink/components/Footer.js.map +1 -0
  235. package/dist/ui/ink/components/Header.d.ts +11 -0
  236. package/dist/ui/ink/components/Header.js +12 -0
  237. package/dist/ui/ink/components/Header.js.map +1 -0
  238. package/dist/ui/ink/components/LinkList.d.ts +17 -0
  239. package/dist/ui/ink/components/LinkList.js +44 -0
  240. package/dist/ui/ink/components/LinkList.js.map +1 -0
  241. package/dist/ui/ink/components/Navigation.d.ts +26 -0
  242. package/dist/ui/ink/components/Navigation.js +62 -0
  243. package/dist/ui/ink/components/Navigation.js.map +1 -0
  244. package/dist/ui/ink/components/ProgressBar.d.ts +15 -0
  245. package/dist/ui/ink/components/ProgressBar.js +14 -0
  246. package/dist/ui/ink/components/ProgressBar.js.map +1 -0
  247. package/dist/ui/ink/components/ScoreCard.d.ts +30 -0
  248. package/dist/ui/ink/components/ScoreCard.js +26 -0
  249. package/dist/ui/ink/components/ScoreCard.js.map +1 -0
  250. package/dist/ui/ink/components/SimulationResults.d.ts +33 -0
  251. package/dist/ui/ink/components/SimulationResults.js +23 -0
  252. package/dist/ui/ink/components/SimulationResults.js.map +1 -0
  253. package/dist/ui/ink/components/Spinner.d.ts +11 -0
  254. package/dist/ui/ink/components/Spinner.js +12 -0
  255. package/dist/ui/ink/components/Spinner.js.map +1 -0
  256. package/dist/ui/ink/components/ToolCard.d.ts +23 -0
  257. package/dist/ui/ink/components/ToolCard.js +20 -0
  258. package/dist/ui/ink/components/ToolCard.js.map +1 -0
  259. package/dist/ui/ink/components/shared/Badge.d.ts +21 -0
  260. package/dist/ui/ink/components/shared/Badge.js +39 -0
  261. package/dist/ui/ink/components/shared/Badge.js.map +1 -0
  262. package/dist/ui/ink/components/shared/Card.d.ts +18 -0
  263. package/dist/ui/ink/components/shared/Card.js +11 -0
  264. package/dist/ui/ink/components/shared/Card.js.map +1 -0
  265. package/dist/ui/ink/components/shared/HelpOverlay.d.ts +10 -0
  266. package/dist/ui/ink/components/shared/HelpOverlay.js +28 -0
  267. package/dist/ui/ink/components/shared/HelpOverlay.js.map +1 -0
  268. package/dist/ui/ink/components/shared/LoadingWithTimeout.d.ts +11 -0
  269. package/dist/ui/ink/components/shared/LoadingWithTimeout.js +21 -0
  270. package/dist/ui/ink/components/shared/LoadingWithTimeout.js.map +1 -0
  271. package/dist/ui/ink/components/shared/Menu.d.ts +23 -0
  272. package/dist/ui/ink/components/shared/Menu.js +43 -0
  273. package/dist/ui/ink/components/shared/Menu.js.map +1 -0
  274. package/dist/ui/ink/components/shared/Table.d.ts +23 -0
  275. package/dist/ui/ink/components/shared/Table.js +40 -0
  276. package/dist/ui/ink/components/shared/Table.js.map +1 -0
  277. package/dist/ui/ink/components/views/CrawlingView.d.ts +12 -0
  278. package/dist/ui/ink/components/views/CrawlingView.js +34 -0
  279. package/dist/ui/ink/components/views/CrawlingView.js.map +1 -0
  280. package/dist/ui/ink/components/views/DashboardView.d.ts +21 -0
  281. package/dist/ui/ink/components/views/DashboardView.js +51 -0
  282. package/dist/ui/ink/components/views/DashboardView.js.map +1 -0
  283. package/dist/ui/ink/components/views/FindingDetailView.d.ts +16 -0
  284. package/dist/ui/ink/components/views/FindingDetailView.js +34 -0
  285. package/dist/ui/ink/components/views/FindingDetailView.js.map +1 -0
  286. package/dist/ui/ink/components/views/FindingsView.d.ts +16 -0
  287. package/dist/ui/ink/components/views/FindingsView.js +79 -0
  288. package/dist/ui/ink/components/views/FindingsView.js.map +1 -0
  289. package/dist/ui/ink/components/views/OnboardingView.d.ts +12 -0
  290. package/dist/ui/ink/components/views/OnboardingView.js +40 -0
  291. package/dist/ui/ink/components/views/OnboardingView.js.map +1 -0
  292. package/dist/ui/ink/components/views/SimulationView.d.ts +17 -0
  293. package/dist/ui/ink/components/views/SimulationView.js +53 -0
  294. package/dist/ui/ink/components/views/SimulationView.js.map +1 -0
  295. package/dist/ui/ink/components/views/TestCaseDetailView.d.ts +11 -0
  296. package/dist/ui/ink/components/views/TestCaseDetailView.js +53 -0
  297. package/dist/ui/ink/components/views/TestCaseDetailView.js.map +1 -0
  298. package/dist/ui/ink/components/views/ToolDetailView.d.ts +15 -0
  299. package/dist/ui/ink/components/views/ToolDetailView.js +25 -0
  300. package/dist/ui/ink/components/views/ToolDetailView.js.map +1 -0
  301. package/dist/ui/ink/components/views/ToolsView.d.ts +15 -0
  302. package/dist/ui/ink/components/views/ToolsView.js +43 -0
  303. package/dist/ui/ink/components/views/ToolsView.js.map +1 -0
  304. package/dist/ui/ink/demo.d.ts +6 -0
  305. package/dist/ui/ink/demo.js +254 -0
  306. package/dist/ui/ink/demo.js.map +1 -0
  307. package/dist/ui/ink/hooks/useAnimation.d.ts +29 -0
  308. package/dist/ui/ink/hooks/useAnimation.js +89 -0
  309. package/dist/ui/ink/hooks/useAnimation.js.map +1 -0
  310. package/dist/ui/ink/hooks/useAudit.d.ts +69 -0
  311. package/dist/ui/ink/hooks/useAudit.js +99 -0
  312. package/dist/ui/ink/hooks/useAudit.js.map +1 -0
  313. package/dist/ui/ink/hooks/useCrawlAnimation.d.ts +19 -0
  314. package/dist/ui/ink/hooks/useCrawlAnimation.js +204 -0
  315. package/dist/ui/ink/hooks/useCrawlAnimation.js.map +1 -0
  316. package/dist/ui/ink/hooks/useKeyboardNav.d.ts +23 -0
  317. package/dist/ui/ink/hooks/useKeyboardNav.js +81 -0
  318. package/dist/ui/ink/hooks/useKeyboardNav.js.map +1 -0
  319. package/dist/ui/ink/hooks/useNavigation.d.ts +16 -0
  320. package/dist/ui/ink/hooks/useNavigation.js +42 -0
  321. package/dist/ui/ink/hooks/useNavigation.js.map +1 -0
  322. package/dist/ui/ink/hooks/useTerminalSize.d.ts +10 -0
  323. package/dist/ui/ink/hooks/useTerminalSize.js +29 -0
  324. package/dist/ui/ink/hooks/useTerminalSize.js.map +1 -0
  325. package/dist/ui/ink/index.d.ts +43 -0
  326. package/dist/ui/ink/index.js +50 -0
  327. package/dist/ui/ink/index.js.map +1 -0
  328. package/dist/ui/ink/render.d.ts +24 -0
  329. package/dist/ui/ink/render.js +14 -0
  330. package/dist/ui/ink/render.js.map +1 -0
  331. package/dist/ui/ink/theme.d.ts +37 -0
  332. package/dist/ui/ink/theme.js +38 -0
  333. package/dist/ui/ink/theme.js.map +1 -0
  334. package/dist/ui/ink/types.d.ts +77 -0
  335. package/dist/ui/ink/types.js +5 -0
  336. package/dist/ui/ink/types.js.map +1 -0
  337. package/dist/ui/score-display.d.ts +16 -0
  338. package/dist/ui/score-display.js +201 -0
  339. package/dist/ui/score-display.js.map +1 -0
  340. package/dist/ui/spinner.d.ts +45 -0
  341. package/dist/ui/spinner.js +112 -0
  342. package/dist/ui/spinner.js.map +1 -0
  343. package/dist/ui/utils.d.ts +13 -0
  344. package/dist/ui/utils.js +25 -0
  345. package/dist/ui/utils.js.map +1 -0
  346. package/package.json +61 -9
  347. package/index.js +0 -105
@@ -0,0 +1,68 @@
1
+ /**
2
+ * WebMCP API Interception Script
3
+ *
4
+ * This script is injected into pages BEFORE any page scripts run.
5
+ * It hooks the navigator.modelContext API to capture all tool registrations.
6
+ */
7
+ /**
8
+ * The interception script to be injected via page.addInitScript()
9
+ */
10
+ export declare const INTERCEPT_SCRIPT = "\n(function() {\n 'use strict';\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Storage for captured data\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n window.__agentready_captured_tools = [];\n window.__agentready_context_calls = [];\n window.__agentready_events = [];\n window.__agentready_hooked = false;\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Helper: Safely serialize an object (handles circular refs, functions)\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n function safeSerialize(obj) {\n try {\n return JSON.parse(JSON.stringify(obj, (key, value) => {\n if (typeof value === 'function') {\n return '[Function]';\n }\n if (value instanceof Error) {\n return { error: value.message, stack: value.stack };\n }\n return value;\n }));\n } catch (e) {\n return { serializationError: e.message };\n }\n }\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Hook the navigator.modelContext API\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n function hookModelContext() {\n if (window.__agentready_hooked) return true;\n if (!navigator.modelContext) return false;\n\n const mc = navigator.modelContext;\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Hook: registerTool()\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (typeof mc.registerTool === 'function') {\n const originalRegister = mc.registerTool.bind(mc);\n\n mc.registerTool = function(toolDef) {\n const captured = {\n name: toolDef.name || null,\n description: toolDef.description || null,\n inputSchema: safeSerialize(toolDef.inputSchema || {}),\n annotations: toolDef.annotations ? safeSerialize(toolDef.annotations) : null,\n hasExecute: typeof toolDef.execute === 'function',\n executeSource: null,\n registeredAt: Date.now(),\n registrationMethod: 'registerTool',\n pageUrl: window.location.href\n };\n\n // Try to capture execute function source\n if (typeof toolDef.execute === 'function') {\n try {\n captured.executeSource = toolDef.execute.toString();\n } catch (e) {\n captured.executeSource = '[Unable to serialize]';\n }\n }\n\n window.__agentready_captured_tools.push(captured);\n\n // Call original\n return originalRegister(toolDef);\n };\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Hook: provideContext()\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (typeof mc.provideContext === 'function') {\n const originalProvide = mc.provideContext.bind(mc);\n\n mc.provideContext = function(context) {\n // Record the provideContext call\n window.__agentready_context_calls.push({\n type: 'provideContext',\n timestamp: Date.now(),\n toolCount: context.tools ? context.tools.length : 0,\n pageUrl: window.location.href\n });\n\n // Capture each tool in the context\n if (context.tools && Array.isArray(context.tools)) {\n context.tools.forEach(function(toolDef) {\n const captured = {\n name: toolDef.name || null,\n description: toolDef.description || null,\n inputSchema: safeSerialize(toolDef.inputSchema || {}),\n annotations: toolDef.annotations ? safeSerialize(toolDef.annotations) : null,\n hasExecute: typeof toolDef.execute === 'function',\n executeSource: null,\n registeredAt: Date.now(),\n registrationMethod: 'provideContext',\n pageUrl: window.location.href\n };\n\n if (typeof toolDef.execute === 'function') {\n try {\n captured.executeSource = toolDef.execute.toString();\n } catch (e) {\n captured.executeSource = '[Unable to serialize]';\n }\n }\n\n window.__agentready_captured_tools.push(captured);\n });\n }\n\n return originalProvide(context);\n };\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Hook: unregisterTool()\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (typeof mc.unregisterTool === 'function') {\n const originalUnregister = mc.unregisterTool.bind(mc);\n\n mc.unregisterTool = function(name) {\n window.__agentready_context_calls.push({\n type: 'unregisterTool',\n toolName: name,\n timestamp: Date.now(),\n pageUrl: window.location.href\n });\n\n return originalUnregister(name);\n };\n }\n\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Hook: clearContext()\n // \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (typeof mc.clearContext === 'function') {\n const originalClear = mc.clearContext.bind(mc);\n\n mc.clearContext = function() {\n window.__agentready_context_calls.push({\n type: 'clearContext',\n timestamp: Date.now(),\n pageUrl: window.location.href\n });\n\n return originalClear();\n };\n }\n\n window.__agentready_hooked = true;\n return true;\n }\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Listen for WebMCP-specific events\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n window.addEventListener('toolactivated', function(e) {\n window.__agentready_events.push({\n type: 'toolactivated',\n toolName: e.toolName || e.detail?.toolName || null,\n timestamp: Date.now(),\n pageUrl: window.location.href\n });\n });\n\n window.addEventListener('toolcancel', function(e) {\n window.__agentready_events.push({\n type: 'toolcancel',\n toolName: e.toolName || e.detail?.toolName || null,\n timestamp: Date.now(),\n pageUrl: window.location.href\n });\n });\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Try to hook immediately, then poll if not available yet\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n if (!hookModelContext()) {\n // navigator.modelContext doesn't exist yet\n // Either WebMCP isn't enabled or it loads asynchronously\n let attempts = 0;\n const maxAttempts = 50;\n const pollInterval = 100; // ms\n\n const interval = setInterval(function() {\n if (hookModelContext() || attempts++ >= maxAttempts) {\n clearInterval(interval);\n }\n }, pollInterval);\n }\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Expose retrieval function for Playwright\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n window.__agentready_getData = function() {\n return {\n hasModelContext: typeof navigator.modelContext !== 'undefined' && navigator.modelContext !== null,\n hooked: window.__agentready_hooked,\n tools: window.__agentready_captured_tools,\n contextCalls: window.__agentready_context_calls,\n events: window.__agentready_events\n };\n };\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Expose function to check for feature detection patterns in scripts\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n window.__agentready_checkFeatureDetection = function() {\n const scripts = document.querySelectorAll('script');\n let hasFeatureDetection = false;\n\n scripts.forEach(function(script) {\n const content = script.textContent || '';\n // Check for common feature detection patterns\n if (\n content.includes('\"modelContext\" in navigator') ||\n content.includes(\"'modelContext' in navigator\") ||\n content.includes('navigator.modelContext') ||\n content.includes('typeof navigator.modelContext')\n ) {\n hasFeatureDetection = true;\n }\n });\n\n return hasFeatureDetection;\n };\n\n})();\n";
11
+ /**
12
+ * Interface for data returned by the interception script
13
+ */
14
+ export interface InterceptedData {
15
+ /**
16
+ * Whether navigator.modelContext exists
17
+ */
18
+ hasModelContext: boolean;
19
+ /**
20
+ * Whether we successfully hooked the API
21
+ */
22
+ hooked: boolean;
23
+ /**
24
+ * All captured tool registrations
25
+ */
26
+ tools: InterceptedTool[];
27
+ /**
28
+ * All context API calls (provideContext, unregisterTool, clearContext)
29
+ */
30
+ contextCalls: ContextCall[];
31
+ /**
32
+ * WebMCP events that were fired
33
+ */
34
+ events: WebMCPEvent[];
35
+ }
36
+ /**
37
+ * A tool captured from the interception
38
+ */
39
+ export interface InterceptedTool {
40
+ name: string | null;
41
+ description: string | null;
42
+ inputSchema: Record<string, unknown>;
43
+ annotations: Record<string, unknown> | null;
44
+ hasExecute: boolean;
45
+ executeSource: string | null;
46
+ registeredAt: number;
47
+ registrationMethod: 'registerTool' | 'provideContext';
48
+ pageUrl: string;
49
+ }
50
+ /**
51
+ * A context API call
52
+ */
53
+ export interface ContextCall {
54
+ type: 'provideContext' | 'unregisterTool' | 'clearContext';
55
+ toolName?: string;
56
+ toolCount?: number;
57
+ timestamp: number;
58
+ pageUrl: string;
59
+ }
60
+ /**
61
+ * A WebMCP event
62
+ */
63
+ export interface WebMCPEvent {
64
+ type: 'toolactivated' | 'toolcancel';
65
+ toolName: string | null;
66
+ timestamp: number;
67
+ pageUrl: string;
68
+ }
@@ -0,0 +1,257 @@
1
+ /**
2
+ * WebMCP API Interception Script
3
+ *
4
+ * This script is injected into pages BEFORE any page scripts run.
5
+ * It hooks the navigator.modelContext API to capture all tool registrations.
6
+ */
7
+ /**
8
+ * The interception script to be injected via page.addInitScript()
9
+ */
10
+ export const INTERCEPT_SCRIPT = `
11
+ (function() {
12
+ 'use strict';
13
+
14
+ // ═══════════════════════════════════════════════════════════════════
15
+ // Storage for captured data
16
+ // ═══════════════════════════════════════════════════════════════════
17
+
18
+ window.__agentready_captured_tools = [];
19
+ window.__agentready_context_calls = [];
20
+ window.__agentready_events = [];
21
+ window.__agentready_hooked = false;
22
+
23
+ // ═══════════════════════════════════════════════════════════════════
24
+ // Helper: Safely serialize an object (handles circular refs, functions)
25
+ // ═══════════════════════════════════════════════════════════════════
26
+
27
+ function safeSerialize(obj) {
28
+ try {
29
+ return JSON.parse(JSON.stringify(obj, (key, value) => {
30
+ if (typeof value === 'function') {
31
+ return '[Function]';
32
+ }
33
+ if (value instanceof Error) {
34
+ return { error: value.message, stack: value.stack };
35
+ }
36
+ return value;
37
+ }));
38
+ } catch (e) {
39
+ return { serializationError: e.message };
40
+ }
41
+ }
42
+
43
+ // ═══════════════════════════════════════════════════════════════════
44
+ // Hook the navigator.modelContext API
45
+ // ═══════════════════════════════════════════════════════════════════
46
+
47
+ function hookModelContext() {
48
+ if (window.__agentready_hooked) return true;
49
+ if (!navigator.modelContext) return false;
50
+
51
+ const mc = navigator.modelContext;
52
+
53
+ // ─────────────────────────────────────────────────────────────────
54
+ // Hook: registerTool()
55
+ // ─────────────────────────────────────────────────────────────────
56
+
57
+ if (typeof mc.registerTool === 'function') {
58
+ const originalRegister = mc.registerTool.bind(mc);
59
+
60
+ mc.registerTool = function(toolDef) {
61
+ const captured = {
62
+ name: toolDef.name || null,
63
+ description: toolDef.description || null,
64
+ inputSchema: safeSerialize(toolDef.inputSchema || {}),
65
+ annotations: toolDef.annotations ? safeSerialize(toolDef.annotations) : null,
66
+ hasExecute: typeof toolDef.execute === 'function',
67
+ executeSource: null,
68
+ registeredAt: Date.now(),
69
+ registrationMethod: 'registerTool',
70
+ pageUrl: window.location.href
71
+ };
72
+
73
+ // Try to capture execute function source
74
+ if (typeof toolDef.execute === 'function') {
75
+ try {
76
+ captured.executeSource = toolDef.execute.toString();
77
+ } catch (e) {
78
+ captured.executeSource = '[Unable to serialize]';
79
+ }
80
+ }
81
+
82
+ window.__agentready_captured_tools.push(captured);
83
+
84
+ // Call original
85
+ return originalRegister(toolDef);
86
+ };
87
+ }
88
+
89
+ // ─────────────────────────────────────────────────────────────────
90
+ // Hook: provideContext()
91
+ // ─────────────────────────────────────────────────────────────────
92
+
93
+ if (typeof mc.provideContext === 'function') {
94
+ const originalProvide = mc.provideContext.bind(mc);
95
+
96
+ mc.provideContext = function(context) {
97
+ // Record the provideContext call
98
+ window.__agentready_context_calls.push({
99
+ type: 'provideContext',
100
+ timestamp: Date.now(),
101
+ toolCount: context.tools ? context.tools.length : 0,
102
+ pageUrl: window.location.href
103
+ });
104
+
105
+ // Capture each tool in the context
106
+ if (context.tools && Array.isArray(context.tools)) {
107
+ context.tools.forEach(function(toolDef) {
108
+ const captured = {
109
+ name: toolDef.name || null,
110
+ description: toolDef.description || null,
111
+ inputSchema: safeSerialize(toolDef.inputSchema || {}),
112
+ annotations: toolDef.annotations ? safeSerialize(toolDef.annotations) : null,
113
+ hasExecute: typeof toolDef.execute === 'function',
114
+ executeSource: null,
115
+ registeredAt: Date.now(),
116
+ registrationMethod: 'provideContext',
117
+ pageUrl: window.location.href
118
+ };
119
+
120
+ if (typeof toolDef.execute === 'function') {
121
+ try {
122
+ captured.executeSource = toolDef.execute.toString();
123
+ } catch (e) {
124
+ captured.executeSource = '[Unable to serialize]';
125
+ }
126
+ }
127
+
128
+ window.__agentready_captured_tools.push(captured);
129
+ });
130
+ }
131
+
132
+ return originalProvide(context);
133
+ };
134
+ }
135
+
136
+ // ─────────────────────────────────────────────────────────────────
137
+ // Hook: unregisterTool()
138
+ // ─────────────────────────────────────────────────────────────────
139
+
140
+ if (typeof mc.unregisterTool === 'function') {
141
+ const originalUnregister = mc.unregisterTool.bind(mc);
142
+
143
+ mc.unregisterTool = function(name) {
144
+ window.__agentready_context_calls.push({
145
+ type: 'unregisterTool',
146
+ toolName: name,
147
+ timestamp: Date.now(),
148
+ pageUrl: window.location.href
149
+ });
150
+
151
+ return originalUnregister(name);
152
+ };
153
+ }
154
+
155
+ // ─────────────────────────────────────────────────────────────────
156
+ // Hook: clearContext()
157
+ // ─────────────────────────────────────────────────────────────────
158
+
159
+ if (typeof mc.clearContext === 'function') {
160
+ const originalClear = mc.clearContext.bind(mc);
161
+
162
+ mc.clearContext = function() {
163
+ window.__agentready_context_calls.push({
164
+ type: 'clearContext',
165
+ timestamp: Date.now(),
166
+ pageUrl: window.location.href
167
+ });
168
+
169
+ return originalClear();
170
+ };
171
+ }
172
+
173
+ window.__agentready_hooked = true;
174
+ return true;
175
+ }
176
+
177
+ // ═══════════════════════════════════════════════════════════════════
178
+ // Listen for WebMCP-specific events
179
+ // ═══════════════════════════════════════════════════════════════════
180
+
181
+ window.addEventListener('toolactivated', function(e) {
182
+ window.__agentready_events.push({
183
+ type: 'toolactivated',
184
+ toolName: e.toolName || e.detail?.toolName || null,
185
+ timestamp: Date.now(),
186
+ pageUrl: window.location.href
187
+ });
188
+ });
189
+
190
+ window.addEventListener('toolcancel', function(e) {
191
+ window.__agentready_events.push({
192
+ type: 'toolcancel',
193
+ toolName: e.toolName || e.detail?.toolName || null,
194
+ timestamp: Date.now(),
195
+ pageUrl: window.location.href
196
+ });
197
+ });
198
+
199
+ // ═══════════════════════════════════════════════════════════════════
200
+ // Try to hook immediately, then poll if not available yet
201
+ // ═══════════════════════════════════════════════════════════════════
202
+
203
+ if (!hookModelContext()) {
204
+ // navigator.modelContext doesn't exist yet
205
+ // Either WebMCP isn't enabled or it loads asynchronously
206
+ let attempts = 0;
207
+ const maxAttempts = 50;
208
+ const pollInterval = 100; // ms
209
+
210
+ const interval = setInterval(function() {
211
+ if (hookModelContext() || attempts++ >= maxAttempts) {
212
+ clearInterval(interval);
213
+ }
214
+ }, pollInterval);
215
+ }
216
+
217
+ // ═══════════════════════════════════════════════════════════════════
218
+ // Expose retrieval function for Playwright
219
+ // ═══════════════════════════════════════════════════════════════════
220
+
221
+ window.__agentready_getData = function() {
222
+ return {
223
+ hasModelContext: typeof navigator.modelContext !== 'undefined' && navigator.modelContext !== null,
224
+ hooked: window.__agentready_hooked,
225
+ tools: window.__agentready_captured_tools,
226
+ contextCalls: window.__agentready_context_calls,
227
+ events: window.__agentready_events
228
+ };
229
+ };
230
+
231
+ // ═══════════════════════════════════════════════════════════════════
232
+ // Expose function to check for feature detection patterns in scripts
233
+ // ═══════════════════════════════════════════════════════════════════
234
+
235
+ window.__agentready_checkFeatureDetection = function() {
236
+ const scripts = document.querySelectorAll('script');
237
+ let hasFeatureDetection = false;
238
+
239
+ scripts.forEach(function(script) {
240
+ const content = script.textContent || '';
241
+ // Check for common feature detection patterns
242
+ if (
243
+ content.includes('"modelContext" in navigator') ||
244
+ content.includes("'modelContext' in navigator") ||
245
+ content.includes('navigator.modelContext') ||
246
+ content.includes('typeof navigator.modelContext')
247
+ ) {
248
+ hasFeatureDetection = true;
249
+ }
250
+ });
251
+
252
+ return hasFeatureDetection;
253
+ };
254
+
255
+ })();
256
+ `;
257
+ //# sourceMappingURL=interceptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptor.js","sourceRoot":"","sources":["../../src/browser/interceptor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsP/B,CAAC"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Playwright Browser Setup
3
+ *
4
+ * Configures Chromium with WebMCP flag enabled and script injection.
5
+ */
6
+ import { type Browser, type BrowserContext, type Page } from 'playwright';
7
+ import { type InterceptedData } from './interceptor.js';
8
+ /**
9
+ * Options for creating an audit browser
10
+ */
11
+ export interface AuditBrowserOptions {
12
+ /**
13
+ * Run in visible (non-headless) mode
14
+ */
15
+ headless?: boolean;
16
+ /**
17
+ * Slow down operations by this many ms (for debugging)
18
+ */
19
+ slowMo?: number;
20
+ /**
21
+ * Timeout for page operations (ms)
22
+ */
23
+ timeout?: number;
24
+ /**
25
+ * User agent string override
26
+ */
27
+ userAgent?: string;
28
+ /**
29
+ * Viewport size
30
+ */
31
+ viewport?: {
32
+ width: number;
33
+ height: number;
34
+ };
35
+ }
36
+ /**
37
+ * Result of creating an audit browser
38
+ */
39
+ export interface AuditBrowser {
40
+ browser: Browser;
41
+ context: BrowserContext;
42
+ }
43
+ /**
44
+ * Create a browser configured for WebMCP auditing
45
+ *
46
+ * The browser is launched with the WebMCP flag enabled and has the
47
+ * interception script injected into every page.
48
+ */
49
+ export declare function createAuditBrowser(options?: AuditBrowserOptions): Promise<AuditBrowser>;
50
+ /**
51
+ * Navigate to a URL and wait for it to be ready
52
+ */
53
+ export declare function navigateAndWait(page: Page, url: string, options?: {
54
+ timeout?: number;
55
+ waitUntil?: 'load' | 'domcontentloaded' | 'networkidle' | 'commit';
56
+ extraWaitMs?: number;
57
+ }): Promise<void>;
58
+ /**
59
+ * Retrieve captured WebMCP data from the page
60
+ */
61
+ export declare function getCapturedData(page: Page): Promise<InterceptedData>;
62
+ /**
63
+ * Check if the page has feature detection for WebMCP
64
+ */
65
+ export declare function hasFeatureDetection(page: Page): Promise<boolean>;
66
+ /**
67
+ * Get the page's HTML content
68
+ */
69
+ export declare function getPageHTML(page: Page): Promise<string>;
70
+ /**
71
+ * Get the page's title
72
+ */
73
+ export declare function getPageTitle(page: Page): Promise<string>;
74
+ /**
75
+ * Take a screenshot of the page
76
+ */
77
+ export declare function takeScreenshot(page: Page, path: string, options?: {
78
+ fullPage?: boolean;
79
+ }): Promise<void>;
80
+ /**
81
+ * Close the browser and clean up
82
+ */
83
+ export declare function closeBrowser(browser: Browser): Promise<void>;
84
+ /**
85
+ * Audit a single page and return captured data
86
+ */
87
+ export declare function auditPage(context: BrowserContext, url: string, options?: {
88
+ timeout?: number;
89
+ waitUntil?: 'load' | 'domcontentloaded' | 'networkidle' | 'commit';
90
+ extraWaitMs?: number;
91
+ screenshot?: string;
92
+ }): Promise<{
93
+ page: Page;
94
+ data: InterceptedData;
95
+ html: string;
96
+ title: string;
97
+ hasFeatureDetection: boolean;
98
+ }>;
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Playwright Browser Setup
3
+ *
4
+ * Configures Chromium with WebMCP flag enabled and script injection.
5
+ */
6
+ import { chromium } from 'playwright';
7
+ import { INTERCEPT_SCRIPT } from './interceptor.js';
8
+ /**
9
+ * Default browser options
10
+ */
11
+ const DEFAULT_OPTIONS = {
12
+ headless: true,
13
+ slowMo: 0,
14
+ timeout: 30000,
15
+ userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 AgentReady/0.1.0',
16
+ viewport: { width: 1280, height: 720 },
17
+ };
18
+ /**
19
+ * Create a browser configured for WebMCP auditing
20
+ *
21
+ * The browser is launched with the WebMCP flag enabled and has the
22
+ * interception script injected into every page.
23
+ */
24
+ export async function createAuditBrowser(options = {}) {
25
+ const opts = { ...DEFAULT_OPTIONS, ...options };
26
+ const browser = await chromium.launch({
27
+ headless: opts.headless,
28
+ slowMo: opts.slowMo,
29
+ args: [
30
+ // Enable WebMCP experimental feature
31
+ '--enable-features=WebMCP',
32
+ // Disable various security features that can interfere with auditing
33
+ '--disable-web-security',
34
+ '--disable-features=IsolateOrigins,site-per-process',
35
+ // Performance optimizations for headless
36
+ '--disable-gpu',
37
+ '--no-sandbox',
38
+ '--disable-setuid-sandbox',
39
+ '--disable-dev-shm-usage',
40
+ ],
41
+ });
42
+ const context = await browser.newContext({
43
+ userAgent: opts.userAgent,
44
+ viewport: opts.viewport,
45
+ ignoreHTTPSErrors: true,
46
+ javaScriptEnabled: true,
47
+ });
48
+ // Set default timeout
49
+ context.setDefaultTimeout(opts.timeout);
50
+ // Inject the interception script into every page BEFORE any page scripts run
51
+ await context.addInitScript(INTERCEPT_SCRIPT);
52
+ return { browser, context };
53
+ }
54
+ /**
55
+ * Navigate to a URL and wait for it to be ready
56
+ */
57
+ export async function navigateAndWait(page, url, options = {}) {
58
+ const { timeout = 30000, waitUntil = 'networkidle', extraWaitMs = 2000 } = options;
59
+ await page.goto(url, {
60
+ timeout,
61
+ waitUntil,
62
+ });
63
+ // Wait a bit more for SPA hydration and lazy tool registration
64
+ // Many sites register tools after the initial load
65
+ if (extraWaitMs > 0) {
66
+ await page.waitForTimeout(extraWaitMs);
67
+ }
68
+ }
69
+ /**
70
+ * Retrieve captured WebMCP data from the page
71
+ */
72
+ export async function getCapturedData(page) {
73
+ const data = await page.evaluate(() => {
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
+ const win = window;
76
+ if (typeof win.__agentready_getData === 'function') {
77
+ return win.__agentready_getData();
78
+ }
79
+ return {
80
+ hasModelContext: false,
81
+ hooked: false,
82
+ tools: [],
83
+ contextCalls: [],
84
+ events: [],
85
+ };
86
+ });
87
+ return data;
88
+ }
89
+ /**
90
+ * Check if the page has feature detection for WebMCP
91
+ */
92
+ export async function hasFeatureDetection(page) {
93
+ return page.evaluate(() => {
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ const win = window;
96
+ if (typeof win.__agentready_checkFeatureDetection === 'function') {
97
+ return win.__agentready_checkFeatureDetection();
98
+ }
99
+ return false;
100
+ });
101
+ }
102
+ /**
103
+ * Get the page's HTML content
104
+ */
105
+ export async function getPageHTML(page) {
106
+ return page.content();
107
+ }
108
+ /**
109
+ * Get the page's title
110
+ */
111
+ export async function getPageTitle(page) {
112
+ return page.title();
113
+ }
114
+ /**
115
+ * Take a screenshot of the page
116
+ */
117
+ export async function takeScreenshot(page, path, options = {}) {
118
+ await page.screenshot({
119
+ path,
120
+ fullPage: options.fullPage ?? false,
121
+ });
122
+ }
123
+ /**
124
+ * Close the browser and clean up
125
+ */
126
+ export async function closeBrowser(browser) {
127
+ await browser.close();
128
+ }
129
+ /**
130
+ * Audit a single page and return captured data
131
+ */
132
+ export async function auditPage(context, url, options = {}) {
133
+ const page = await context.newPage();
134
+ try {
135
+ await navigateAndWait(page, url, options);
136
+ const [data, html, title, featureDetection] = await Promise.all([
137
+ getCapturedData(page),
138
+ getPageHTML(page),
139
+ getPageTitle(page),
140
+ hasFeatureDetection(page),
141
+ ]);
142
+ if (options.screenshot) {
143
+ await takeScreenshot(page, options.screenshot);
144
+ }
145
+ return {
146
+ page,
147
+ data,
148
+ html,
149
+ title,
150
+ hasFeatureDetection: featureDetection,
151
+ };
152
+ }
153
+ catch (error) {
154
+ await page.close();
155
+ throw error;
156
+ }
157
+ }
158
+ //# sourceMappingURL=playwright.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright.js","sourceRoot":"","sources":["../../src/browser/playwright.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Audit Command
3
+ *
4
+ * Run a full WebMCP audit on a website.
5
+ */
6
+ import type { AuditOptions } from '../../core/types/audit.js';
7
+ /**
8
+ * Run the audit command
9
+ */
10
+ export declare function runAudit(urlString: string, options: AuditOptions & {
11
+ animation?: boolean;
12
+ }): Promise<number>;