brave-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +802 -0
  3. package/build/src/DevToolsConnectionAdapter.js +69 -0
  4. package/build/src/DevtoolsUtils.js +294 -0
  5. package/build/src/McpContext.js +676 -0
  6. package/build/src/McpPage.js +108 -0
  7. package/build/src/McpResponse.js +718 -0
  8. package/build/src/Mutex.js +37 -0
  9. package/build/src/PageCollector.js +310 -0
  10. package/build/src/SlimMcpResponse.js +18 -0
  11. package/build/src/WaitForHelper.js +153 -0
  12. package/build/src/bin/brave-devtools-cli-options.js +651 -0
  13. package/build/src/bin/brave-devtools-mcp-cli-options.js +312 -0
  14. package/build/src/bin/brave-devtools-mcp-main.js +35 -0
  15. package/build/src/bin/brave-devtools-mcp.js +22 -0
  16. package/build/src/bin/brave-devtools.js +190 -0
  17. package/build/src/bin/check-latest-version.js +25 -0
  18. package/build/src/bin/cliDefinitions.js +615 -0
  19. package/build/src/browser.js +295 -0
  20. package/build/src/daemon/client.js +152 -0
  21. package/build/src/daemon/daemon.js +202 -0
  22. package/build/src/daemon/types.js +6 -0
  23. package/build/src/daemon/utils.js +109 -0
  24. package/build/src/formatters/ConsoleFormatter.js +241 -0
  25. package/build/src/formatters/IssueFormatter.js +192 -0
  26. package/build/src/formatters/NetworkFormatter.js +218 -0
  27. package/build/src/formatters/SnapshotFormatter.js +134 -0
  28. package/build/src/index.js +216 -0
  29. package/build/src/issue-descriptions.js +39 -0
  30. package/build/src/logger.js +36 -0
  31. package/build/src/polyfill.js +7 -0
  32. package/build/src/telemetry/ClearcutLogger.js +234 -0
  33. package/build/src/telemetry/WatchdogClient.js +60 -0
  34. package/build/src/telemetry/flagUtils.js +45 -0
  35. package/build/src/telemetry/metricUtils.js +14 -0
  36. package/build/src/telemetry/persistence.js +53 -0
  37. package/build/src/telemetry/toolMetricsUtils.js +88 -0
  38. package/build/src/telemetry/types.js +38 -0
  39. package/build/src/telemetry/watchdog/ClearcutSender.js +203 -0
  40. package/build/src/telemetry/watchdog/main.js +127 -0
  41. package/build/src/third_party/devtools-formatter-worker.js +7 -0
  42. package/build/src/third_party/index.js +28 -0
  43. package/build/src/third_party/issue-descriptions/CoepCoopSandboxedIframeCannotNavigateToCoopPage.md +4 -0
  44. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +8 -0
  45. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +18 -0
  46. package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +7 -0
  47. package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +10 -0
  48. package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +5 -0
  49. package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +5 -0
  50. package/build/src/third_party/issue-descriptions/LowTextContrast.md +5 -0
  51. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeRead.md +8 -0
  52. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeSet.md +8 -0
  53. package/build/src/third_party/issue-descriptions/SameSiteExcludeNavigationContextDowngrade.md +8 -0
  54. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +8 -0
  55. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +8 -0
  56. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +8 -0
  57. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +8 -0
  58. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +9 -0
  59. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +9 -0
  60. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeRead.md +8 -0
  61. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeSet.md +8 -0
  62. package/build/src/third_party/issue-descriptions/SameSiteWarnStrictLaxDowngradeStrict.md +8 -0
  63. package/build/src/third_party/issue-descriptions/arInsecureContext.md +7 -0
  64. package/build/src/third_party/issue-descriptions/arInvalidInfoHeader.md +5 -0
  65. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsSourceHeader.md +5 -0
  66. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsTriggerHeader.md +5 -0
  67. package/build/src/third_party/issue-descriptions/arInvalidRegisterSourceHeader.md +5 -0
  68. package/build/src/third_party/issue-descriptions/arInvalidRegisterTriggerHeader.md +5 -0
  69. package/build/src/third_party/issue-descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +5 -0
  70. package/build/src/third_party/issue-descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +6 -0
  71. package/build/src/third_party/issue-descriptions/arNoRegisterOsSourceHeader.md +5 -0
  72. package/build/src/third_party/issue-descriptions/arNoRegisterOsTriggerHeader.md +5 -0
  73. package/build/src/third_party/issue-descriptions/arNoRegisterSourceHeader.md +5 -0
  74. package/build/src/third_party/issue-descriptions/arNoRegisterTriggerHeader.md +5 -0
  75. package/build/src/third_party/issue-descriptions/arNoWebOrOsSupport.md +4 -0
  76. package/build/src/third_party/issue-descriptions/arOsSourceIgnored.md +18 -0
  77. package/build/src/third_party/issue-descriptions/arOsTriggerIgnored.md +19 -0
  78. package/build/src/third_party/issue-descriptions/arPermissionPolicyDisabled.md +8 -0
  79. package/build/src/third_party/issue-descriptions/arSourceAndTriggerHeaders.md +9 -0
  80. package/build/src/third_party/issue-descriptions/arSourceIgnored.md +13 -0
  81. package/build/src/third_party/issue-descriptions/arTriggerIgnored.md +12 -0
  82. package/build/src/third_party/issue-descriptions/arUntrustworthyReportingOrigin.md +10 -0
  83. package/build/src/third_party/issue-descriptions/arWebAndOsHeaders.md +11 -0
  84. package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +3 -0
  85. package/build/src/third_party/issue-descriptions/clientHintMetaTagAllowListInvalidOrigin.md +4 -0
  86. package/build/src/third_party/issue-descriptions/clientHintMetaTagModifiedHTML.md +4 -0
  87. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +12 -0
  88. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +12 -0
  89. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +8 -0
  90. package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +12 -0
  91. package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +7 -0
  92. package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +10 -0
  93. package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +12 -0
  94. package/build/src/third_party/issue-descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +4 -0
  95. package/build/src/third_party/issue-descriptions/cookieExcludeDomainNonAscii.md +11 -0
  96. package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +8 -0
  97. package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +7 -0
  98. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutRead.md +6 -0
  99. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +6 -0
  100. package/build/src/third_party/issue-descriptions/cookieWarnDomainNonAscii.md +11 -0
  101. package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantRead.md +4 -0
  102. package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantSet.md +4 -0
  103. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +6 -0
  104. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutSet.md +6 -0
  105. package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +6 -0
  106. package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +7 -0
  107. package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +7 -0
  108. package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +5 -0
  109. package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +7 -0
  110. package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +19 -0
  111. package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +5 -0
  112. package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +5 -0
  113. package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +6 -0
  114. package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +5 -0
  115. package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +5 -0
  116. package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +8 -0
  117. package/build/src/third_party/issue-descriptions/cspEvalViolation.md +9 -0
  118. package/build/src/third_party/issue-descriptions/cspInlineViolation.md +10 -0
  119. package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +5 -0
  120. package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +8 -0
  121. package/build/src/third_party/issue-descriptions/cspURLViolation.md +10 -0
  122. package/build/src/third_party/issue-descriptions/deprecation.md +3 -0
  123. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -0
  124. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -0
  125. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -0
  126. package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -0
  127. package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -0
  128. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -0
  129. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -0
  130. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -0
  131. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -0
  132. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -0
  133. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -0
  134. package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -0
  135. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -0
  136. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -0
  137. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -0
  138. package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -0
  139. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -0
  140. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -0
  141. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -0
  142. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -0
  143. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -0
  144. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -0
  145. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -0
  146. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -0
  147. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -0
  148. package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +7 -0
  149. package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +8 -0
  150. package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +5 -0
  151. package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +5 -0
  152. package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +5 -0
  153. package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +5 -0
  154. package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +5 -0
  155. package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +5 -0
  156. package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +5 -0
  157. package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +5 -0
  158. package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +5 -0
  159. package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
  160. package/build/src/third_party/issue-descriptions/genericResponseWasBlockedByORB.md +4 -0
  161. package/build/src/third_party/issue-descriptions/heavyAd.md +10 -0
  162. package/build/src/third_party/issue-descriptions/mixedContent.md +5 -0
  163. package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +5 -0
  164. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +7 -0
  165. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +9 -0
  166. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +9 -0
  167. package/build/src/third_party/issue-descriptions/permissionElementCspFrameAncestorsMissing.md +5 -0
  168. package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +5 -0
  169. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +5 -0
  170. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +5 -0
  171. package/build/src/third_party/issue-descriptions/permissionElementGeolocationDeprecated.md +5 -0
  172. package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +5 -0
  173. package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +5 -0
  174. package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +5 -0
  175. package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +5 -0
  176. package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +5 -0
  177. package/build/src/third_party/issue-descriptions/permissionElementLowContrast.md +5 -0
  178. package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +5 -0
  179. package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +6 -0
  180. package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +6 -0
  181. package/build/src/third_party/issue-descriptions/permissionElementPermissionsPolicyBlocked.md +5 -0
  182. package/build/src/third_party/issue-descriptions/permissionElementRegistrationFailed.md +5 -0
  183. package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +5 -0
  184. package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +5 -0
  185. package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +5 -0
  186. package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +7 -0
  187. package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +3 -0
  188. package/build/src/third_party/issue-descriptions/propertyRuleInvalidNameIssue.md +3 -0
  189. package/build/src/third_party/issue-descriptions/propertyRuleIssue.md +7 -0
  190. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +7 -0
  191. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +7 -0
  192. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +3 -0
  193. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +3 -0
  194. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +3 -0
  195. package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +3 -0
  196. package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +7 -0
  197. package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +7 -0
  198. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -0
  199. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorDictionaryLoadFailure.md +3 -0
  200. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +3 -0
  201. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -0
  202. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -0
  203. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -0
  204. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +3 -0
  205. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +3 -0
  206. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInsufficientResources.md +1 -0
  207. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidMatchField.md +1 -0
  208. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -0
  209. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidTTLField.md +1 -0
  210. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +3 -0
  211. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNoMatchField.md +1 -0
  212. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonIntegerTTLField.md +1 -0
  213. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonListMatchDestField.md +1 -0
  214. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonSecureContext.md +3 -0
  215. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringIdField.md +1 -0
  216. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringInMatchDestList.md +1 -0
  217. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringMatchField.md +1 -0
  218. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonTokenTypeField.md +1 -0
  219. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorRequestAborted.md +1 -0
  220. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorShuttingDown.md +1 -0
  221. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorTooLongIdField.md +3 -0
  222. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorUnsupportedType.md +3 -0
  223. package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +14 -0
  224. package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +15 -0
  225. package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +8 -0
  226. package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +7 -0
  227. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +11 -0
  228. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +14 -0
  229. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +15 -0
  230. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +8 -0
  231. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +13 -0
  232. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +4 -0
  233. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +5 -0
  234. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +11 -0
  235. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +12 -0
  236. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +6 -0
  237. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +8 -0
  238. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +11 -0
  239. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +11 -0
  240. package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +10 -0
  241. package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +5 -0
  242. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +6 -0
  243. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +11 -0
  244. package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +4 -0
  245. package/build/src/third_party/issue-descriptions/stylesheetRequestFailed.md +3 -0
  246. package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +3 -0
  247. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +12 -0
  248. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +17 -0
  249. package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +14 -0
  250. package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +15 -0
  251. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +59418 -0
  252. package/build/src/tools/ToolDefinition.js +72 -0
  253. package/build/src/tools/categories.js +26 -0
  254. package/build/src/tools/console.js +85 -0
  255. package/build/src/tools/emulation.js +55 -0
  256. package/build/src/tools/extensions.js +96 -0
  257. package/build/src/tools/inPage.js +105 -0
  258. package/build/src/tools/input.js +376 -0
  259. package/build/src/tools/lighthouse.js +123 -0
  260. package/build/src/tools/memory.js +28 -0
  261. package/build/src/tools/network.js +120 -0
  262. package/build/src/tools/pages.js +336 -0
  263. package/build/src/tools/performance.js +190 -0
  264. package/build/src/tools/screencast.js +79 -0
  265. package/build/src/tools/screenshot.js +84 -0
  266. package/build/src/tools/script.js +125 -0
  267. package/build/src/tools/slim/tools.js +81 -0
  268. package/build/src/tools/snapshot.js +56 -0
  269. package/build/src/tools/tools.js +53 -0
  270. package/build/src/trace-processing/parse.js +84 -0
  271. package/build/src/types.js +6 -0
  272. package/build/src/utils/ExtensionRegistry.js +35 -0
  273. package/build/src/utils/check-for-updates.js +72 -0
  274. package/build/src/utils/files.js +19 -0
  275. package/build/src/utils/keyboard.js +296 -0
  276. package/build/src/utils/pagination.js +49 -0
  277. package/build/src/utils/string.js +36 -0
  278. package/build/src/utils/types.js +6 -0
  279. package/build/src/version.js +6 -0
  280. package/package.json +87 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import fs from 'node:fs';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+ import process from 'node:process';
10
+ import { logger } from '../logger.js';
11
+ export const DAEMON_SCRIPT_PATH = path.join(import.meta.dirname, 'daemon.js');
12
+ export const INDEX_SCRIPT_PATH = path.join(import.meta.dirname, '..', 'bin', 'brave-devtools-mcp.js');
13
+ const APP_NAME = 'brave-devtools-mcp';
14
+ export const DAEMON_CLIENT_NAME = 'brave-devtools-cli-daemon';
15
+ // Using these paths due to strict limits on the POSIX socket path length.
16
+ export function getSocketPath() {
17
+ const uid = os.userInfo().uid;
18
+ if (IS_WINDOWS) {
19
+ // Windows uses Named Pipes, not file paths.
20
+ // This format is required for server.listen()
21
+ return path.join('\\\\.\\pipe', APP_NAME, 'server.sock');
22
+ }
23
+ // 1. Try XDG_RUNTIME_DIR (Linux standard, sometimes macOS)
24
+ if (process.env.XDG_RUNTIME_DIR) {
25
+ return path.join(process.env.XDG_RUNTIME_DIR, APP_NAME, 'server.sock');
26
+ }
27
+ // 2. macOS/Unix Fallback: Use /tmp/
28
+ // We use /tmp/ because it is much shorter than ~/Library/Application Support/
29
+ // and keeps us well under the 104-character limit.
30
+ return path.join('/tmp', `${APP_NAME}-${uid}.sock`);
31
+ }
32
+ export function getRuntimeHome() {
33
+ const platform = os.platform();
34
+ const uid = os.userInfo().uid;
35
+ // 1. Check for the modern Unix standard
36
+ if (process.env.XDG_RUNTIME_DIR) {
37
+ return path.join(process.env.XDG_RUNTIME_DIR, APP_NAME);
38
+ }
39
+ // 2. Fallback for macOS and older Linux
40
+ if (platform === 'darwin' || platform === 'linux') {
41
+ // /tmp is cleared on boot, making it perfect for PIDs
42
+ return path.join('/tmp', `${APP_NAME}-${uid}`);
43
+ }
44
+ // 3. Windows Fallback
45
+ return path.join(os.tmpdir(), APP_NAME);
46
+ }
47
+ export const IS_WINDOWS = os.platform() === 'win32';
48
+ export function getPidFilePath() {
49
+ const runtimeDir = getRuntimeHome();
50
+ return path.join(runtimeDir, 'daemon.pid');
51
+ }
52
+ export function getDaemonPid() {
53
+ try {
54
+ const pidFile = getPidFilePath();
55
+ logger(`Daemon pid file ${pidFile}`);
56
+ if (!fs.existsSync(pidFile)) {
57
+ return null;
58
+ }
59
+ const pidContent = fs.readFileSync(pidFile, 'utf-8');
60
+ const pid = parseInt(pidContent.trim(), 10);
61
+ logger(`Daemon pid: ${pid}`);
62
+ if (isNaN(pid)) {
63
+ return null;
64
+ }
65
+ return pid;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ export function isDaemonRunning(pid = getDaemonPid()) {
72
+ if (pid) {
73
+ try {
74
+ process.kill(pid, 0); // Throws if process doesn't exist
75
+ return true;
76
+ }
77
+ catch {
78
+ // Process is dead, stale PID file. Proceed with startup.
79
+ }
80
+ }
81
+ return false;
82
+ }
83
+ export function serializeArgs(options, argv) {
84
+ const args = [];
85
+ for (const key of Object.keys(options)) {
86
+ if (argv[key] === undefined || argv[key] === null) {
87
+ continue;
88
+ }
89
+ const value = argv[key];
90
+ const kebabKey = key.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`);
91
+ if (typeof value === 'boolean') {
92
+ if (value) {
93
+ args.push(`--${kebabKey}`);
94
+ }
95
+ else {
96
+ args.push(`--no-${kebabKey}`);
97
+ }
98
+ }
99
+ else if (Array.isArray(value)) {
100
+ for (const item of value) {
101
+ args.push(`--${kebabKey}`, String(item));
102
+ }
103
+ }
104
+ else {
105
+ args.push(`--${kebabKey}`, String(value));
106
+ }
107
+ }
108
+ return args;
109
+ }
@@ -0,0 +1,241 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { createStackTraceForConsoleMessage, SymbolizedError, } from '../DevtoolsUtils.js';
7
+ import { UncaughtError } from '../PageCollector.js';
8
+ import * as DevTools from '../third_party/index.js';
9
+ export class ConsoleFormatter {
10
+ #id;
11
+ #type;
12
+ #text;
13
+ #argCount;
14
+ #resolvedArgs;
15
+ #stack;
16
+ #cause;
17
+ isIgnored;
18
+ constructor(params) {
19
+ this.#id = params.id;
20
+ this.#type = params.type;
21
+ this.#text = params.text;
22
+ this.#argCount = params.argCount ?? 0;
23
+ this.#resolvedArgs = params.resolvedArgs ?? [];
24
+ this.#stack = params.stack;
25
+ this.#cause = params.cause;
26
+ this.isIgnored = params.isIgnored;
27
+ }
28
+ static async from(msg, options) {
29
+ const ignoreListManager = options?.devTools?.universe.context.get(DevTools.DevTools.IgnoreListManager);
30
+ const isIgnored = options.isIgnoredForTesting ||
31
+ (frame => {
32
+ if (!ignoreListManager) {
33
+ return false;
34
+ }
35
+ if (frame.uiSourceCode) {
36
+ return ignoreListManager.isUserOrSourceMapIgnoreListedUISourceCode(frame.uiSourceCode);
37
+ }
38
+ if (frame.url) {
39
+ return ignoreListManager.isUserIgnoreListedURL(frame.url);
40
+ }
41
+ return false;
42
+ });
43
+ if (msg instanceof UncaughtError) {
44
+ const error = await SymbolizedError.fromDetails({
45
+ devTools: options?.devTools,
46
+ details: msg.details,
47
+ targetId: msg.targetId,
48
+ includeStackAndCause: options?.fetchDetailedData,
49
+ resolvedStackTraceForTesting: options?.resolvedStackTraceForTesting,
50
+ resolvedCauseForTesting: options?.resolvedCauseForTesting,
51
+ });
52
+ return new ConsoleFormatter({
53
+ id: options.id,
54
+ type: 'error',
55
+ text: error.message,
56
+ stack: error.stackTrace,
57
+ cause: error.cause,
58
+ isIgnored,
59
+ });
60
+ }
61
+ let resolvedArgs = [];
62
+ if (options.resolvedArgsForTesting) {
63
+ resolvedArgs = options.resolvedArgsForTesting;
64
+ }
65
+ else if (options.fetchDetailedData) {
66
+ resolvedArgs = await Promise.all(msg.args().map(async (arg, i) => {
67
+ try {
68
+ const remoteObject = arg.remoteObject();
69
+ if (remoteObject.type === 'object' &&
70
+ remoteObject.subtype === 'error') {
71
+ return await SymbolizedError.fromError({
72
+ devTools: options.devTools,
73
+ error: remoteObject,
74
+ // @ts-expect-error Internal ConsoleMessage API
75
+ targetId: msg._targetId(),
76
+ });
77
+ }
78
+ return await arg.jsonValue();
79
+ }
80
+ catch {
81
+ return `<error: Argument ${i} is no longer available>`;
82
+ }
83
+ }));
84
+ }
85
+ let stack;
86
+ if (options.resolvedStackTraceForTesting) {
87
+ stack = options.resolvedStackTraceForTesting;
88
+ }
89
+ else if (options.fetchDetailedData && options.devTools) {
90
+ try {
91
+ stack = await createStackTraceForConsoleMessage(options.devTools, msg);
92
+ }
93
+ catch {
94
+ // ignore
95
+ }
96
+ }
97
+ return new ConsoleFormatter({
98
+ id: options.id,
99
+ type: msg.type(),
100
+ text: msg.text(),
101
+ argCount: resolvedArgs.length || msg.args().length,
102
+ resolvedArgs,
103
+ stack,
104
+ isIgnored,
105
+ });
106
+ }
107
+ // The short format for a console message.
108
+ toString() {
109
+ return convertConsoleMessageConciseToString(this.toJSON());
110
+ }
111
+ // The verbose format for a console message, including all details.
112
+ toStringDetailed() {
113
+ return convertConsoleMessageConciseDetailedToString(this.toJSONDetailed());
114
+ }
115
+ #getArgs() {
116
+ if (this.#resolvedArgs.length > 0) {
117
+ const args = [...this.#resolvedArgs];
118
+ // If there is no text, the first argument serves as text (see formatMessage).
119
+ if (!this.#text) {
120
+ args.shift();
121
+ }
122
+ return args;
123
+ }
124
+ return [];
125
+ }
126
+ toJSON() {
127
+ return {
128
+ type: this.#type,
129
+ text: this.#text,
130
+ argsCount: this.#argCount,
131
+ id: this.#id,
132
+ };
133
+ }
134
+ toJSONDetailed() {
135
+ return {
136
+ id: this.#id,
137
+ type: this.#type,
138
+ text: this.#text,
139
+ argsCount: this.#argCount,
140
+ args: this.#getArgs().map(arg => formatArg(arg, this)),
141
+ stackTrace: this.#stack
142
+ ? formatStackTrace(this.#stack, this.#cause, this)
143
+ : undefined,
144
+ };
145
+ }
146
+ }
147
+ function convertConsoleMessageConciseToString(msg) {
148
+ return `msgid=${msg.id} [${msg.type}] ${msg.text} (${msg.argsCount} args)`;
149
+ }
150
+ function convertConsoleMessageConciseDetailedToString(msg) {
151
+ const result = [
152
+ `ID: ${msg.id}`,
153
+ `Message: ${msg.type}> ${msg.text}`,
154
+ formatArgs(msg),
155
+ ...(msg.stackTrace ? ['### Stack trace', msg.stackTrace] : []),
156
+ ].filter(line => !!line);
157
+ return result.join('\n');
158
+ }
159
+ function formatArgs(msg) {
160
+ const args = msg.args;
161
+ if (!args.length) {
162
+ return '';
163
+ }
164
+ const result = ['### Arguments'];
165
+ for (const [key, arg] of args.entries()) {
166
+ result.push(`Arg #${key}: ${arg}`);
167
+ }
168
+ return result.join('\n');
169
+ }
170
+ function formatArg(arg, formatter) {
171
+ if (arg instanceof SymbolizedError) {
172
+ return [
173
+ arg.message,
174
+ arg.stackTrace
175
+ ? formatStackTrace(arg.stackTrace, arg.cause, formatter)
176
+ : undefined,
177
+ ]
178
+ .filter(line => !!line)
179
+ .join('\n');
180
+ }
181
+ return typeof arg === 'object' ? JSON.stringify(arg) : String(arg);
182
+ }
183
+ const STACK_TRACE_MAX_LINES = 50;
184
+ function formatStackTrace(stackTrace, cause, formatter) {
185
+ const lines = formatStackTraceInner(stackTrace, cause, formatter);
186
+ const includedLines = lines.slice(0, STACK_TRACE_MAX_LINES);
187
+ const reminderCount = lines.length - includedLines.length;
188
+ return [
189
+ ...includedLines,
190
+ reminderCount > 0 ? `... and ${reminderCount} more frames` : '',
191
+ 'Note: line and column numbers use 1-based indexing',
192
+ ]
193
+ .filter(line => !!line)
194
+ .join('\n');
195
+ }
196
+ function formatStackTraceInner(stackTrace, cause, formatter) {
197
+ if (!stackTrace) {
198
+ return [];
199
+ }
200
+ return [
201
+ ...formatFragment(stackTrace.syncFragment, formatter),
202
+ ...stackTrace.asyncFragments
203
+ .map(item => formatAsyncFragment(item, formatter))
204
+ .flat(),
205
+ ...formatCause(cause, formatter),
206
+ ];
207
+ }
208
+ function formatFragment(fragment, formatter) {
209
+ const frames = fragment.frames.filter(frame => !formatter.isIgnored(frame));
210
+ return frames.map(formatFrame);
211
+ }
212
+ function formatAsyncFragment(fragment, formatter) {
213
+ const formattedFrames = formatFragment(fragment, formatter);
214
+ if (formattedFrames.length === 0) {
215
+ return [];
216
+ }
217
+ const separatorLineLength = 40;
218
+ const prefix = `--- ${fragment.description || 'async'} `;
219
+ const separator = prefix + '-'.repeat(separatorLineLength - prefix.length);
220
+ return [separator, ...formattedFrames];
221
+ }
222
+ function formatFrame(frame) {
223
+ let result = `at ${frame.name ?? '<anonymous>'}`;
224
+ if (frame.uiSourceCode) {
225
+ const location = frame.uiSourceCode.uiLocation(frame.line, frame.column);
226
+ result += ` (${location.linkText(/* skipTrim */ false, /* showColumnNumber */ true)})`;
227
+ }
228
+ else if (frame.url) {
229
+ result += ` (${frame.url}:${frame.line}:${frame.column})`;
230
+ }
231
+ return result;
232
+ }
233
+ function formatCause(cause, formatter) {
234
+ if (!cause) {
235
+ return [];
236
+ }
237
+ return [
238
+ `Caused by: ${cause.message}`,
239
+ ...formatStackTraceInner(cause.stackTrace, cause.cause, formatter),
240
+ ];
241
+ }
@@ -0,0 +1,192 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ISSUE_UTILS } from '../issue-descriptions.js';
7
+ import { logger } from '../logger.js';
8
+ import { DevTools } from '../third_party/index.js';
9
+ export class IssueFormatter {
10
+ #issue;
11
+ #options;
12
+ constructor(issue, options) {
13
+ this.#issue = issue;
14
+ this.#options = options;
15
+ }
16
+ toString() {
17
+ return convertIssueConciseToString(this.toJSON());
18
+ }
19
+ toStringDetailed() {
20
+ return convertIssueDetailedToString(this.toJSONDetailed());
21
+ }
22
+ toJSON() {
23
+ return {
24
+ type: 'issue',
25
+ title: this.#getTitle(),
26
+ count: this.#issue.getAggregatedIssuesCount(),
27
+ id: this.#options.id,
28
+ };
29
+ }
30
+ toJSONDetailed() {
31
+ return {
32
+ id: this.#options.id,
33
+ type: 'issue',
34
+ count: this.#issue.getAggregatedIssuesCount(),
35
+ title: this.#getTitle(),
36
+ description: this.#getDescription(),
37
+ links: this.#issue.getDescription()?.links,
38
+ affectedResources: this.#getAffectedResources(),
39
+ };
40
+ }
41
+ #getAffectedResources() {
42
+ const issues = this.#issue.getAllIssues();
43
+ const affectedResources = [];
44
+ for (const singleIssue of issues) {
45
+ const details = singleIssue.details();
46
+ if (!details) {
47
+ continue;
48
+ }
49
+ // We send the remaining details as untyped JSON because the DevTools
50
+ // frontend code is currently not re-usable.
51
+ const data = structuredClone(details);
52
+ let uid;
53
+ let request;
54
+ if ('violatingNodeId' in details &&
55
+ details.violatingNodeId &&
56
+ this.#options.elementIdResolver) {
57
+ uid = this.#options.elementIdResolver(details.violatingNodeId);
58
+ delete data.violatingNodeId;
59
+ }
60
+ if ('nodeId' in details &&
61
+ details.nodeId &&
62
+ this.#options.elementIdResolver) {
63
+ uid = this.#options.elementIdResolver(details.nodeId);
64
+ delete data.nodeId;
65
+ }
66
+ if ('documentNodeId' in details &&
67
+ details.documentNodeId &&
68
+ this.#options.elementIdResolver) {
69
+ uid = this.#options.elementIdResolver(details.documentNodeId);
70
+ delete data.documentNodeId;
71
+ }
72
+ if ('request' in details && details.request) {
73
+ request = details.request.url;
74
+ if (details.request.requestId && this.#options.requestIdResolver) {
75
+ const resolvedId = this.#options.requestIdResolver(details.request.requestId);
76
+ if (resolvedId) {
77
+ request = resolvedId;
78
+ const requestData = data.request;
79
+ delete requestData.requestId;
80
+ }
81
+ }
82
+ }
83
+ // These fields has no use for the MCP client (redundant or irrelevant).
84
+ delete data.errorType;
85
+ delete data.frameId;
86
+ affectedResources.push({
87
+ uid,
88
+ data: data,
89
+ request,
90
+ });
91
+ }
92
+ return affectedResources;
93
+ }
94
+ isValid() {
95
+ return this.#getTitle() !== undefined;
96
+ }
97
+ // Helper to extract title
98
+ #getTitle() {
99
+ const markdownDescription = this.#issue.getDescription();
100
+ const filename = markdownDescription?.file;
101
+ if (!filename) {
102
+ logger(`no description found for issue:` + this.#issue.code());
103
+ return undefined;
104
+ }
105
+ // We already have the description logic in #getDescription, but title extraction is separate
106
+ // We can reuse the logic or cache it.
107
+ // Ideally we should process markdown once.
108
+ const rawMarkdown = ISSUE_UTILS.getIssueDescription(filename);
109
+ if (!rawMarkdown) {
110
+ logger(`no markdown ${filename} found for issue:` + this.#issue.code());
111
+ return undefined;
112
+ }
113
+ try {
114
+ const processedMarkdown = DevTools.MarkdownIssueDescription.substitutePlaceholders(rawMarkdown, markdownDescription?.substitutions);
115
+ const markdownAst = DevTools.Marked.Marked.lexer(processedMarkdown);
116
+ const title = DevTools.MarkdownIssueDescription.findTitleFromMarkdownAst(markdownAst);
117
+ if (!title) {
118
+ logger('cannot read issue title from ' + filename);
119
+ return undefined;
120
+ }
121
+ return title;
122
+ }
123
+ catch {
124
+ logger('error parsing markdown for issue ' + this.#issue.code());
125
+ return undefined;
126
+ }
127
+ }
128
+ #getDescription() {
129
+ const markdownDescription = this.#issue.getDescription();
130
+ const filename = markdownDescription?.file;
131
+ if (!filename) {
132
+ return undefined;
133
+ }
134
+ const rawMarkdown = ISSUE_UTILS.getIssueDescription(filename);
135
+ if (!rawMarkdown) {
136
+ return undefined;
137
+ }
138
+ try {
139
+ return DevTools.MarkdownIssueDescription.substitutePlaceholders(rawMarkdown, markdownDescription?.substitutions);
140
+ }
141
+ catch {
142
+ return undefined;
143
+ }
144
+ }
145
+ }
146
+ function convertIssueConciseToString(issue) {
147
+ return `msgid=${issue.id} [issue] ${issue.title} (count: ${issue.count})`;
148
+ }
149
+ function convertIssueDetailedToString(issue) {
150
+ const result = [];
151
+ result.push(`ID: ${issue.id}`);
152
+ const bodyParts = [];
153
+ const description = issue.description;
154
+ let processedMarkdown = description?.trim();
155
+ // Remove heading in order not to conflict with the whole console message response markdown
156
+ if (processedMarkdown?.startsWith('# ')) {
157
+ processedMarkdown = processedMarkdown.substring(2).trimStart();
158
+ }
159
+ if (processedMarkdown) {
160
+ bodyParts.push(processedMarkdown);
161
+ }
162
+ else {
163
+ bodyParts.push(issue.title ?? 'Unknown Issue');
164
+ }
165
+ const links = issue.links;
166
+ if (links && links.length > 0) {
167
+ bodyParts.push('Learn more:');
168
+ for (const link of links) {
169
+ bodyParts.push(`[${link.linkTitle}](${link.link})`);
170
+ }
171
+ }
172
+ const affectedResources = issue.affectedResources;
173
+ if (affectedResources.length) {
174
+ bodyParts.push('### Affected resources');
175
+ bodyParts.push(...affectedResources.map(item => {
176
+ const details = [];
177
+ if (item.uid) {
178
+ details.push(`uid=${item.uid}`);
179
+ }
180
+ if (item.request) {
181
+ details.push((typeof item.request === 'number' ? `reqid=` : 'url=') +
182
+ item.request);
183
+ }
184
+ if (item.data) {
185
+ details.push(`data=${JSON.stringify(item.data)}`);
186
+ }
187
+ return details.join(' ');
188
+ }));
189
+ }
190
+ result.push(`Message: issue> ${bodyParts.join('\n')}`);
191
+ return result.join('\n');
192
+ }