opera-devtools-mcp 0.2.4 → 0.4.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 (330) hide show
  1. package/README.md +108 -8
  2. package/build/src/McpContext.js +365 -365
  3. package/build/src/McpPage.js +475 -48
  4. package/build/src/McpResponse.js +462 -288
  5. package/build/src/SlimMcpResponse.js +1 -1
  6. package/build/src/TextSnapshot.js +101 -22
  7. package/build/src/ToolHandler.js +142 -20
  8. package/build/src/bin/check-latest-version.js +27 -1
  9. package/build/src/bin/chrome-devtools-cli-options.js +614 -10
  10. package/build/src/bin/chrome-devtools-mcp-cli-options.js +119 -32
  11. package/build/src/bin/chrome-devtools-mcp-main.js +50 -7
  12. package/build/src/bin/chrome-devtools-mcp.js +7 -4
  13. package/build/src/bin/chrome-devtools.js +57 -14
  14. package/build/src/bin/opera-devtools-cli-options.js +3 -829
  15. package/build/src/bin/opera-devtools-mcp-cli-options.js +3 -348
  16. package/build/src/bin/opera-devtools-mcp-main.js +3 -37
  17. package/build/src/bin/opera-devtools-mcp.js +4 -19
  18. package/build/src/bin/opera-devtools.js +4 -185
  19. package/build/src/browser.js +45 -5
  20. package/build/src/{PageCollector.js → collectors/PageCollector.js} +64 -133
  21. package/build/src/collectors/ServiceWorkerCollector.js +171 -0
  22. package/build/src/daemon/client.js +75 -17
  23. package/build/src/daemon/daemon.js +92 -30
  24. package/build/src/daemon/utils.js +24 -8
  25. package/build/src/{DevtoolsUtils.js → devtools/DevtoolsUtils.js} +94 -88
  26. package/build/src/devtools/McpHostBindingAdapter.js +165 -0
  27. package/build/src/{issue-descriptions.js → devtools/issueDescriptions.js} +8 -6
  28. package/build/src/formatters/ConsoleFormatter.js +44 -11
  29. package/build/src/formatters/HeapSnapshotFormatter.js +140 -9
  30. package/build/src/formatters/IssueFormatter.js +7 -7
  31. package/build/src/formatters/NetworkFormatter.js +10 -8
  32. package/build/src/index.js +101 -232
  33. package/build/src/opera/branding.js +34 -0
  34. package/build/src/opera/browserFlags.js +85 -0
  35. package/build/src/opera/browserLaunch.js +52 -0
  36. package/build/src/opera/policy.js +50 -0
  37. package/build/src/opera/serviceWorkerRetry.js +37 -0
  38. package/build/src/opera/toolHandlerHooks.js +39 -0
  39. package/build/src/{tools → opera/tools}/opera.js +116 -21
  40. package/build/src/processors/HeapSnapshotManager.js +258 -0
  41. package/build/src/{trace-processing/parse.js → processors/PerformanceTrace.js} +9 -9
  42. package/build/src/telemetry/ClearcutLogger.js +12 -119
  43. package/build/src/telemetry/WatchdogClient.js +5 -5
  44. package/build/src/telemetry/errors.js +1 -1
  45. package/build/src/telemetry/flagUtils.js +6 -6
  46. package/build/src/telemetry/{toolMetricsUtils.js → metricsRegistry.js} +4 -11
  47. package/build/src/telemetry/persistence.js +3 -3
  48. package/build/src/telemetry/transformation.js +193 -0
  49. package/build/src/telemetry/watchdog/ClearcutSender.js +11 -11
  50. package/build/src/telemetry/watchdog/main.js +6 -6
  51. package/build/src/third_party/THIRD_PARTY_NOTICES +232 -1061
  52. package/build/src/third_party/bundled-packages.json +7 -8
  53. package/build/src/third_party/devtools-formatter-worker.js +63 -22
  54. package/build/src/third_party/devtools-heap-snapshot-worker.js +809 -182
  55. package/build/src/third_party/index.js +69558 -74691
  56. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +2 -2
  57. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +3 -3
  58. package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +2 -2
  59. package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +1 -1
  60. package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +1 -1
  61. package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +2 -2
  62. package/build/src/third_party/issue-descriptions/LowTextContrast.md +1 -1
  63. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +1 -1
  64. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +1 -1
  65. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +1 -1
  66. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +1 -1
  67. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +3 -3
  68. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +3 -3
  69. package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +1 -1
  70. package/build/src/third_party/issue-descriptions/connectionAllowlistEmbeddingRequirementNotSatisfied.md +26 -0
  71. package/build/src/third_party/issue-descriptions/connectionAllowlistIFrameAttributeLoosensEmbeddingRequirement.md +19 -0
  72. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowConnectionAllowlistFrom.md +21 -0
  73. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +2 -2
  74. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +2 -2
  75. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +3 -3
  76. package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +2 -2
  77. package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +2 -2
  78. package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +1 -1
  79. package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +3 -3
  80. package/build/src/third_party/issue-descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +1 -1
  81. package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +1 -1
  82. package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +1 -1
  83. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +1 -1
  84. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +1 -1
  85. package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +1 -1
  86. package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +2 -2
  87. package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +2 -2
  88. package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +1 -1
  89. package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +3 -3
  90. package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +1 -1
  91. package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +1 -1
  92. package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +1 -1
  93. package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +3 -3
  94. package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +2 -2
  95. package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +3 -3
  96. package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +4 -3
  97. package/build/src/third_party/issue-descriptions/cspEvalViolation.md +4 -4
  98. package/build/src/third_party/issue-descriptions/cspInlineViolation.md +2 -2
  99. package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +2 -2
  100. package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +4 -4
  101. package/build/src/third_party/issue-descriptions/cspURLViolation.md +4 -4
  102. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsEmptyList.md +1 -0
  103. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsHttpNotFound.md +1 -0
  104. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidContentType.md +1 -0
  105. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidResponse.md +1 -0
  106. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsNoResponse.md +1 -0
  107. package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsFetchFailed.md +1 -0
  108. package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsInvalidRecord.md +1 -0
  109. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownHttpNotFound.md +1 -0
  110. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidContentType.md +1 -0
  111. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidResponse.md +1 -0
  112. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownNoResponse.md +1 -0
  113. package/build/src/third_party/issue-descriptions/emailVerificationRequestInvalidEmail.md +1 -0
  114. package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksHttpNotFound.md +1 -0
  115. package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksInvalidResponse.md +1 -0
  116. package/build/src/third_party/issue-descriptions/emailVerificationRequestKeyBindingSigningFailed.md +1 -0
  117. package/build/src/third_party/issue-descriptions/emailVerificationRequestRpOriginIsOpaque.md +1 -0
  118. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenHttpNotFound.md +1 -0
  119. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidContentType.md +1 -0
  120. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidResponse.md +1 -0
  121. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidSdJwt.md +1 -0
  122. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenMalformedSdJwt.md +1 -0
  123. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenNoResponse.md +1 -0
  124. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidAudience.md +1 -0
  125. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidIssuedAt.md +1 -0
  126. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidNonce.md +1 -0
  127. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidSdHash.md +1 -0
  128. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidTyp.md +1 -0
  129. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingAud.md +1 -0
  130. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingCnf.md +1 -0
  131. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingIat.md +1 -0
  132. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingNonce.md +1 -0
  133. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingSdHash.md +1 -0
  134. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbSignatureFailed.md +1 -0
  135. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmail.md +1 -0
  136. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmailVerified.md +1 -0
  137. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidHolderKey.md +1 -0
  138. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuedAt.md +1 -0
  139. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuer.md +1 -0
  140. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtJwksMissingKeys.md +1 -0
  141. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingCnf.md +1 -0
  142. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingEmail.md +1 -0
  143. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIat.md +1 -0
  144. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIss.md +1 -0
  145. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtSignatureFailed.md +1 -0
  146. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtUnsupportedHeaderAlg.md +1 -0
  147. package/build/src/third_party/issue-descriptions/emailVerificationRequestUserLoggedOut.md +1 -0
  148. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownAccountsEndpointCrossOrigin.md +1 -0
  149. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownHttpNotFound.md +1 -0
  150. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidContentType.md +1 -0
  151. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidResponse.md +1 -0
  152. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownIssuanceEndpointCrossOrigin.md +1 -0
  153. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownListEmpty.md +1 -0
  154. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingAccountsEndpoint.md +1 -0
  155. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingIssuanceEndpoint.md +1 -0
  156. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownNoResponse.md +1 -0
  157. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownUnsupportedSigningAlgorithm.md +1 -0
  158. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -1
  159. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -1
  160. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -1
  161. package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -1
  162. package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -1
  163. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -1
  164. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -1
  165. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -1
  166. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -1
  167. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -1
  168. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -1
  169. package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -1
  170. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -1
  171. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -1
  172. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -1
  173. package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -1
  174. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -1
  175. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -1
  176. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -1
  177. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -1
  178. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -1
  179. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -1
  180. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -1
  181. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -1
  182. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -1
  183. package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +2 -2
  184. package/build/src/third_party/issue-descriptions/genericBackUINavigationWouldSkipAd.md +4 -0
  185. package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +2 -2
  186. package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +1 -1
  187. package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +1 -1
  188. package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +2 -2
  189. package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +2 -2
  190. package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +1 -1
  191. package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +1 -1
  192. package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +2 -2
  193. package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +1 -1
  194. package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +1 -1
  195. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +1 -1
  196. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +1 -1
  197. package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +1 -1
  198. package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +2 -2
  199. package/build/src/third_party/issue-descriptions/heavyAd.md +1 -1
  200. package/build/src/third_party/issue-descriptions/lazyLoadImageZeroSize.md +7 -0
  201. package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +3 -3
  202. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +1 -1
  203. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +1 -1
  204. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +1 -1
  205. package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +2 -2
  206. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +2 -2
  207. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +2 -2
  208. package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +1 -1
  209. package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +2 -2
  210. package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +2 -2
  211. package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +2 -2
  212. package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +2 -2
  213. package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +1 -1
  214. package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +2 -2
  215. package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +2 -2
  216. package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +2 -2
  217. package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +1 -1
  218. package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +2 -2
  219. package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +1 -1
  220. package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +1 -1
  221. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +1 -1
  222. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +1 -1
  223. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +1 -1
  224. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +1 -1
  225. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +1 -1
  226. package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +1 -1
  227. package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +3 -3
  228. package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +1 -1
  229. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -1
  230. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +1 -1
  231. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -1
  232. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -1
  233. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -1
  234. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +1 -1
  235. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +2 -2
  236. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -1
  237. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +2 -2
  238. package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +4 -4
  239. package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +4 -4
  240. package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +1 -1
  241. package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +2 -2
  242. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +2 -2
  243. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +4 -4
  244. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +4 -4
  245. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +1 -1
  246. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +2 -2
  247. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +1 -1
  248. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +1 -1
  249. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +2 -2
  250. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +5 -5
  251. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +3 -3
  252. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +2 -2
  253. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +2 -2
  254. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +2 -2
  255. package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +4 -4
  256. package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +3 -3
  257. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +2 -2
  258. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +2 -2
  259. package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +1 -1
  260. package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +1 -1
  261. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +2 -2
  262. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +3 -3
  263. package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +2 -2
  264. package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +1 -1
  265. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +3177 -6340
  266. package/build/src/tools/ToolDefinition.js +2 -2
  267. package/build/src/tools/categories.js +3 -0
  268. package/build/src/tools/console.js +13 -0
  269. package/build/src/tools/emulation.js +30 -3
  270. package/build/src/tools/extensions.js +8 -1
  271. package/build/src/tools/input.js +246 -128
  272. package/build/src/tools/lighthouse.js +14 -7
  273. package/build/src/tools/memory.js +289 -25
  274. package/build/src/tools/network.js +10 -7
  275. package/build/src/tools/pages.js +33 -92
  276. package/build/src/tools/performance.js +67 -52
  277. package/build/src/tools/pwa.js +128 -0
  278. package/build/src/tools/screencast.js +35 -12
  279. package/build/src/tools/screenshot.js +234 -75
  280. package/build/src/tools/script.js +130 -45
  281. package/build/src/tools/slim/tools.js +3 -0
  282. package/build/src/tools/snapshot.js +7 -4
  283. package/build/src/tools/thirdPartyDeveloper.js +19 -9
  284. package/build/src/tools/tools.js +3 -1
  285. package/build/src/tools/webmcp.js +3 -1
  286. package/build/src/utils/WaitForHelper.js +299 -0
  287. package/build/src/utils/check-for-updates.js +8 -2
  288. package/build/src/utils/files.js +42 -3
  289. package/build/src/utils/logger.js +51 -0
  290. package/build/src/utils/polyfill.js +11 -0
  291. package/build/src/utils/url.js +43 -0
  292. package/build/src/version.js +1 -4
  293. package/package.json +43 -33
  294. package/build/src/DevToolsConnectionAdapter.js +0 -70
  295. package/build/src/HeapSnapshotManager.js +0 -110
  296. package/build/src/Mutex.js +0 -38
  297. package/build/src/WaitForHelper.js +0 -195
  298. package/build/src/bin/cliDefinitions.js +0 -616
  299. package/build/src/logger.js +0 -37
  300. package/build/src/polyfill.js +0 -8
  301. package/build/src/telemetry/metricUtils.js +0 -15
  302. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeRead.md +0 -8
  303. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeSet.md +0 -8
  304. package/build/src/third_party/issue-descriptions/SameSiteExcludeNavigationContextDowngrade.md +0 -8
  305. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeRead.md +0 -8
  306. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeSet.md +0 -8
  307. package/build/src/third_party/issue-descriptions/SameSiteWarnStrictLaxDowngradeStrict.md +0 -8
  308. package/build/src/third_party/issue-descriptions/arInsecureContext.md +0 -7
  309. package/build/src/third_party/issue-descriptions/arInvalidInfoHeader.md +0 -5
  310. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
  311. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
  312. package/build/src/third_party/issue-descriptions/arInvalidRegisterSourceHeader.md +0 -5
  313. package/build/src/third_party/issue-descriptions/arInvalidRegisterTriggerHeader.md +0 -5
  314. package/build/src/third_party/issue-descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
  315. package/build/src/third_party/issue-descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
  316. package/build/src/third_party/issue-descriptions/arNoRegisterOsSourceHeader.md +0 -5
  317. package/build/src/third_party/issue-descriptions/arNoRegisterOsTriggerHeader.md +0 -5
  318. package/build/src/third_party/issue-descriptions/arNoRegisterSourceHeader.md +0 -5
  319. package/build/src/third_party/issue-descriptions/arNoRegisterTriggerHeader.md +0 -5
  320. package/build/src/third_party/issue-descriptions/arNoWebOrOsSupport.md +0 -4
  321. package/build/src/third_party/issue-descriptions/arOsSourceIgnored.md +0 -18
  322. package/build/src/third_party/issue-descriptions/arOsTriggerIgnored.md +0 -19
  323. package/build/src/third_party/issue-descriptions/arPermissionPolicyDisabled.md +0 -8
  324. package/build/src/third_party/issue-descriptions/arSourceAndTriggerHeaders.md +0 -9
  325. package/build/src/third_party/issue-descriptions/arSourceIgnored.md +0 -13
  326. package/build/src/third_party/issue-descriptions/arTriggerIgnored.md +0 -12
  327. package/build/src/third_party/issue-descriptions/arUntrustworthyReportingOrigin.md +0 -10
  328. package/build/src/third_party/issue-descriptions/arWebAndOsHeaders.md +0 -11
  329. package/build/src/utils/string.js +0 -37
  330. package/build/src/utils/types.js +0 -7
@@ -2,7 +2,11 @@
2
2
  * @license
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Modified by Opera Software AS.
5
7
  */
8
+ import { CACHE_DIR_NAME, ENV_NO_USAGE_STATISTICS, MCP_BIN_NAME, PACKAGE_NAME, REPO_URL, } from '../opera/branding.js';
9
+ import { PERFORMANCE_CRUX_DEFAULT, PERFORMANCE_CRUX_DESCRIPTION, USAGE_STATISTICS_DEFAULT, USAGE_STATISTICS_DESCRIPTION, } from '../opera/policy.js';
6
10
  import { yargs, hideBin } from '../third_party/index.js';
7
11
  export const cliOptions = {
8
12
  autoConnect: {
@@ -19,7 +23,7 @@ export const cliOptions = {
19
23
  },
20
24
  browserUrl: {
21
25
  type: 'string',
22
- description: 'Connect to a running, debuggable Chrome instance (e.g. `http://127.0.0.1:9222`). For more details see: https://github.com/ChromeDevTools/chrome-devtools-mcp#connecting-to-a-running-chrome-instance.',
26
+ description: `Connect to a running, debuggable Chrome instance (e.g. \`http://127.0.0.1:9222\`). For more details see: ${REPO_URL}#connecting-to-a-running-chrome-instance.`,
23
27
  alias: 'u',
24
28
  conflicts: ['wsEndpoint'],
25
29
  coerce: (url) => {
@@ -96,7 +100,7 @@ export const cliOptions = {
96
100
  },
97
101
  userDataDir: {
98
102
  type: 'string',
99
- description: 'Path to the user data directory for Chrome. Default is $HOME/.cache/chrome-devtools-mcp/chrome-profile$CHANNEL_SUFFIX_IF_NON_STABLE',
103
+ description: `Path to the user data directory for Chrome. Default is $HOME/.cache/${CACHE_DIR_NAME}/chrome-profile$CHANNEL_SUFFIX_IF_NON_STABLE`,
100
104
  conflicts: ['browserUrl', 'wsEndpoint', 'isolated'],
101
105
  },
102
106
  channel: {
@@ -136,39 +140,40 @@ export const cliOptions = {
136
140
  },
137
141
  experimentalPageIdRouting: {
138
142
  type: 'boolean',
139
- describe: 'Whether to expose pageId on page-scoped tools and route requests by page ID.',
140
- hidden: true,
143
+ describe: 'Whether to expose pageId on page-scoped tools and route requests by page ID (useful for concurrent agent sessions).',
141
144
  },
142
145
  experimentalDevtools: {
143
146
  type: 'boolean',
144
147
  describe: 'Whether to enable automation over DevTools targets',
145
- hidden: true,
146
148
  },
147
149
  experimentalVision: {
148
150
  type: 'boolean',
149
151
  describe: 'Whether to enable coordinate-based tools such as click_at(x,y). Usually requires a computer-use model able to produce accurate coordinates by looking at screenshots.',
150
- hidden: false,
151
152
  },
152
- experimentalMemory: {
153
+ memoryDebugging: {
153
154
  type: 'boolean',
154
- describe: 'Whether to enable experimental memory tools.',
155
- hidden: true,
155
+ describe: 'Whether to enable memory debugging tools.',
156
+ alias: 'experimentalMemory',
156
157
  },
157
158
  experimentalStructuredContent: {
158
159
  type: 'boolean',
159
160
  describe: 'Whether to output structured formatted content.',
160
- hidden: true,
161
161
  },
162
- experimentalIncludeAllPages: {
162
+ experimentalToonFormat: {
163
163
  type: 'boolean',
164
- describe: 'Whether to include all kinds of pages such as webviews or background pages as pages.',
164
+ describe: 'Deprecated: use --experimentalDataFormat=toon instead. Whether to format structured data using TOON (requires @toon-format/toon).',
165
165
  hidden: true,
166
166
  },
167
- experimentalNavigationAllowlist: {
168
- type: 'boolean',
169
- describe: 'Whether to enable navigation allowlist tool parameter.',
167
+ experimentalDataFormat: {
168
+ type: 'string',
169
+ describe: 'Override format for structured data in text responses. Default uses built-in formatters. "toon" (requires @toon-format/toon) or "gcf" (requires @blackwell-systems/gcf) replace structured content with the specified encoding.',
170
+ choices: ['default', 'toon', 'gcf'],
170
171
  hidden: true,
171
172
  },
173
+ experimentalIncludeAllPages: {
174
+ type: 'boolean',
175
+ describe: 'Whether to include all kinds of pages such as webviews or background pages as pages.',
176
+ },
172
177
  experimentalInteropTools: {
173
178
  type: 'boolean',
174
179
  describe: 'Whether to enable interoperability tools',
@@ -185,15 +190,25 @@ export const cliOptions = {
185
190
  },
186
191
  categoryExperimentalWebmcp: {
187
192
  type: 'boolean',
188
- describe: 'Set to true to enable debugging WebMCP tools. Requires Chrome 149+ with the following flags: `--enable-features=WebMCPTesting,DevToolsWebMCPSupport`',
193
+ describe: 'Set to true to enable debugging WebMCP tools. Requires Chrome 150+ with the following flag: `--enable-features=WebMCP`',
189
194
  },
190
195
  chromeArg: {
191
196
  type: 'array',
192
- describe: 'Additional arguments for Chrome. Only applies when Chrome is launched by chrome-devtools-mcp.',
197
+ describe: `Additional arguments for Chrome. Only applies when Chrome is launched by ${MCP_BIN_NAME}.`,
198
+ },
199
+ blockedUrlPattern: {
200
+ type: 'array',
201
+ describe: "Restricts browser's network access by blocking specified URL patterns (uses https://urlpattern.spec.whatwg.org/). Silently detaches from targets with blocked URLs upon connection, and blocks runtime requests (including navigations and subresources). Accepts an array of patterns.",
202
+ conflicts: ['allowedUrlPattern'],
203
+ },
204
+ allowedUrlPattern: {
205
+ type: 'array',
206
+ describe: "Restricts browser's network access by allowing only specified URL patterns (uses https://urlpattern.spec.whatwg.org/). Requires Chrome 149+. Silently detaches from targets with unallowed URLs upon connection, and blocks runtime requests (including navigations and subresources). Accepts an array of patterns.",
207
+ conflicts: ['blockedUrlPattern'],
193
208
  },
194
209
  ignoreDefaultChromeArg: {
195
210
  type: 'array',
196
- describe: 'Explicitly disable default arguments for Chrome. Only applies when Chrome is launched by chrome-devtools-mcp.',
211
+ describe: `Explicitly disable default arguments for Chrome. Only applies when Chrome is launched by ${MCP_BIN_NAME}.`,
197
212
  },
198
213
  categoryEmulation: {
199
214
  type: 'boolean',
@@ -221,15 +236,21 @@ export const cliOptions = {
221
236
  default: false,
222
237
  describe: 'Set to true to enable third-party developer tools exposed by the inspected page itself',
223
238
  },
239
+ categoryPwa: {
240
+ type: 'boolean',
241
+ hidden: false,
242
+ conflicts: ['autoConnect', 'browserUrl', 'wsEndpoint'],
243
+ describe: 'Set to true to include tools for automating Progressive Web Apps (install, launch, uninstall, and OS state). This feature is only supported with a pipe connection; autoConnect, browserUrl, and wsEndpoint are not supported.',
244
+ },
224
245
  performanceCrux: {
225
246
  type: 'boolean',
226
- default: true,
227
- describe: 'Set to false to disable sending URLs from performance traces to CrUX API to get field performance data.',
247
+ default: PERFORMANCE_CRUX_DEFAULT,
248
+ describe: PERFORMANCE_CRUX_DESCRIPTION,
228
249
  },
229
250
  usageStatistics: {
230
251
  type: 'boolean',
231
- default: true,
232
- describe: 'Set to false to opt-out of usage statistics collection. Google collects usage data to improve the tool, handled under the Google Privacy Policy (https://policies.google.com/privacy). This is independent from Chrome browser metrics. Disabled if `CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS` or `CI` env variables are set.',
252
+ default: USAGE_STATISTICS_DEFAULT,
253
+ describe: USAGE_STATISTICS_DESCRIPTION,
233
254
  },
234
255
  clearcutEndpoint: {
235
256
  type: 'string',
@@ -246,6 +267,50 @@ export const cliOptions = {
246
267
  hidden: true,
247
268
  describe: 'Include watchdog PID in Clearcut request headers (for testing).',
248
269
  },
270
+ screenshotFormat: {
271
+ type: 'string',
272
+ description: 'Override the default output format used by take_screenshot when the caller does not specify one. JPEG and WebP are ~3-5x smaller than PNG, which helps reduce context size in AI conversations. Unset preserves the existing default ("png").',
273
+ choices: ['jpeg', 'png', 'webp'],
274
+ },
275
+ screenshotQuality: {
276
+ type: 'number',
277
+ description: 'Override the default compression quality (0-100) used by take_screenshot for JPEG and WebP when the caller does not specify one. Lower values mean smaller files. Ignored for PNG. Unset preserves the Puppeteer default.',
278
+ coerce: (value) => {
279
+ if (value === undefined) {
280
+ return;
281
+ }
282
+ if (!Number.isInteger(value) || value < 0 || value > 100) {
283
+ throw new Error(`Invalid screenshotQuality ${value}. Expected an integer between 0 and 100.`);
284
+ }
285
+ return value;
286
+ },
287
+ },
288
+ screenshotMaxWidth: {
289
+ type: 'number',
290
+ description: 'Maximum width in pixels for screenshots. If the captured image is wider, it is downscaled (preserving aspect ratio) before being returned. Reduces context size in AI conversations. Unset means no resize.',
291
+ coerce: (value) => {
292
+ if (value === undefined) {
293
+ return;
294
+ }
295
+ if (!Number.isInteger(value) || value <= 0) {
296
+ throw new Error(`Invalid screenshotMaxWidth ${value}. Expected a positive integer.`);
297
+ }
298
+ return value;
299
+ },
300
+ },
301
+ screenshotMaxHeight: {
302
+ type: 'number',
303
+ description: 'Maximum height in pixels for screenshots. If the captured image is taller, it is downscaled (preserving aspect ratio) before being returned. Can be combined with --screenshot-max-width; the smaller scale factor wins. Unset means no resize.',
304
+ coerce: (value) => {
305
+ if (value === undefined) {
306
+ return;
307
+ }
308
+ if (!Number.isInteger(value) || value <= 0) {
309
+ throw new Error(`Invalid screenshotMaxHeight ${value}. Expected a positive integer.`);
310
+ }
311
+ return value;
312
+ },
313
+ },
249
314
  slim: {
250
315
  type: 'boolean',
251
316
  describe: 'Exposes a "slim" set of 3 tools covering navigation, script execution and screenshots only. Useful for basic browser tasks.',
@@ -257,15 +322,36 @@ export const cliOptions = {
257
322
  },
258
323
  redactNetworkHeaders: {
259
324
  type: 'boolean',
260
- describe: 'If true, redacts some of the network headers considered senstive before returning to the client.',
325
+ describe: 'If true, redacts some of the network headers considered sensitive before returning to the client.',
326
+ default: false,
327
+ },
328
+ allowUnrestrictedPaths: {
329
+ type: 'boolean',
261
330
  default: false,
331
+ describe: 'If set, disables the default path restriction that applies when the MCP client does not negotiate ' +
332
+ 'the roots capability. By default, file-writing tools are restricted to the OS temp directory when ' +
333
+ 'no roots are configured. Use this only when connecting a trusted local client that does not implement ' +
334
+ 'MCP roots and requires access to paths outside the temp directory.',
262
335
  },
263
336
  };
264
- export function parseArguments(version, argv = process.argv, env = process.env) {
337
+ /**
338
+ * Exported only for testing to not trigger process exit.
339
+ */
340
+ export function parser(version, argv = process.argv, env = process.env) {
341
+ // Preserve yargs' mixed camel/kebab-case expansion under strict validation.
342
+ const kebabCaseAliases = {};
343
+ for (const option of Object.keys(cliOptions)) {
344
+ const alias = option.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);
345
+ if (alias !== option) {
346
+ kebabCaseAliases[option] = alias;
347
+ }
348
+ }
265
349
  const yargsInstance = yargs(hideBin(argv))
266
- .scriptName('npx chrome-devtools-mcp@latest')
350
+ .scriptName(`npx ${PACKAGE_NAME}@latest`)
267
351
  .options(cliOptions)
268
- .check(args => {
352
+ .alias(kebabCaseAliases)
353
+ .strictOptions()
354
+ .middleware(args => {
269
355
  // We can't set default in the options else
270
356
  // Yargs will complain
271
357
  if (!args.channel &&
@@ -274,11 +360,10 @@ export function parseArguments(version, argv = process.argv, env = process.env)
274
360
  !args.executablePath) {
275
361
  args.channel = 'stable';
276
362
  }
277
- if (env['CI'] || env['CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS']) {
278
- console.error("turning off usage statistics. process.env['CI'] || process.env['CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS'] is set.");
363
+ if (env['CI'] || env[ENV_NO_USAGE_STATISTICS]) {
364
+ console.error(`turning off usage statistics. process.env['CI'] || process.env['${ENV_NO_USAGE_STATISTICS}'] is set.`);
279
365
  args.usageStatistics = false;
280
366
  }
281
- return true;
282
367
  })
283
368
  .example([
284
369
  [
@@ -331,7 +416,7 @@ export function parseArguments(version, argv = process.argv, env = process.env)
331
416
  ],
332
417
  [
333
418
  '$0 --no-usage-statistics',
334
- 'Do not send usage statistics https://github.com/ChromeDevTools/chrome-devtools-mcp#usage-statistics.',
419
+ `Do not send usage statistics ${REPO_URL}#usage-statistics.`,
335
420
  ],
336
421
  [
337
422
  '$0 --no-performance-crux',
@@ -345,7 +430,9 @@ export function parseArguments(version, argv = process.argv, env = process.env)
345
430
  return yargsInstance
346
431
  .wrap(Math.min(120, yargsInstance.terminalWidth()))
347
432
  .help()
348
- .version(version)
349
- .parseSync();
433
+ .version(version);
434
+ }
435
+ export function parseArguments(version, argv = process.argv, env = process.env) {
436
+ return parser(version, argv, env).parseSync();
350
437
  }
351
438
  //# sourceMappingURL=chrome-devtools-mcp-cli-options.js.map
@@ -2,32 +2,75 @@
2
2
  * @license
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Modified by Opera Software AS.
5
7
  */
6
- import '../polyfill.js';
8
+ import '../utils/polyfill.js';
7
9
  import process from 'node:process';
10
+ import { closeBrowser } from '../browser.js';
8
11
  import { createMcpServer, logDisclaimers } from '../index.js';
9
- import { logger, saveLogsToFile } from '../logger.js';
12
+ import { ENV_CRASH_ON_UNCAUGHT, PACKAGE_NAME, PRODUCT_NAME, } from '../opera/branding.js';
13
+ import { enforceTelemetryPolicy } from '../opera/policy.js';
10
14
  import { ClearcutLogger } from '../telemetry/ClearcutLogger.js';
11
15
  import { computeFlagUsage } from '../telemetry/flagUtils.js';
12
16
  import { StdioServerTransport } from '../third_party/index.js';
13
17
  import { checkForUpdates } from '../utils/check-for-updates.js';
18
+ import { logger, saveLogsToFile } from '../utils/logger.js';
14
19
  import { VERSION } from '../version.js';
15
20
  import { cliOptions, parseArguments } from './chrome-devtools-mcp-cli-options.js';
16
- await checkForUpdates('Run `npm install chrome-devtools-mcp@latest` to update.');
21
+ await checkForUpdates(`Run \`npm install ${PACKAGE_NAME}@latest\` to update.`);
17
22
  export const args = parseArguments(VERSION);
18
23
  const logFile = args.logFile ? saveLogsToFile(args.logFile) : undefined;
19
- if (process.env['CHROME_DEVTOOLS_MCP_CRASH_ON_UNCAUGHT'] !== 'true') {
24
+ enforceTelemetryPolicy(args);
25
+ if (process.env[ENV_CRASH_ON_UNCAUGHT] !== 'true') {
20
26
  process.on('unhandledRejection', (reason, promise) => {
21
- logger('Unhandled promise rejection', promise, reason);
27
+ logger?.('Unhandled promise rejection', promise, reason);
22
28
  });
23
29
  }
24
- logger(`Starting Chrome DevTools MCP Server v${VERSION}`);
30
+ logger?.(`Starting ${PRODUCT_NAME} v${VERSION}`);
31
+ // Shutdown on stdin EOF (stdio MCP convention — the client closes the
32
+ // transport to signal exit) and on standard termination signals. Without
33
+ // this, an active Chrome subprocess keeps the Node event loop ref'd after
34
+ // stdin closes and the server hangs until something else kills it.
35
+ let shuttingDown = false;
36
+ async function shutdown(reason) {
37
+ if (shuttingDown) {
38
+ return;
39
+ }
40
+ shuttingDown = true;
41
+ logger?.(`Shutting down (${reason})`);
42
+ // Backstop in case browser teardown hangs (e.g. unresponsive Chrome,
43
+ // slow beforeunload handlers, many tabs). Exits 0 because we still
44
+ // honored the shutdown request; the log line preserves observability.
45
+ // Unref'd so it doesn't keep the loop alive on the clean path.
46
+ setTimeout(() => {
47
+ logger?.('Shutdown timeout exceeded, forcing exit');
48
+ process.exit(0);
49
+ }, 5000).unref();
50
+ await closeBrowser();
51
+ process.exit(0);
52
+ }
53
+ process.stdin.on('end', () => {
54
+ void shutdown('stdin end');
55
+ });
56
+ process.stdin.on('close', () => {
57
+ void shutdown('stdin close');
58
+ });
59
+ process.on('SIGTERM', () => {
60
+ void shutdown('SIGTERM');
61
+ });
62
+ process.on('SIGINT', () => {
63
+ void shutdown('SIGINT');
64
+ });
65
+ process.on('SIGHUP', () => {
66
+ void shutdown('SIGHUP');
67
+ });
25
68
  const { server } = await createMcpServer(args, {
26
69
  logFile,
27
70
  });
28
71
  const transport = new StdioServerTransport();
29
72
  await server.connect(transport);
30
- logger('Chrome DevTools MCP Server connected');
73
+ logger?.(`${PRODUCT_NAME} connected`);
31
74
  logDisclaimers(args);
32
75
  void ClearcutLogger.get()?.logDailyActiveIfNeeded();
33
76
  void ClearcutLogger.get()?.logServerStart(computeFlagUsage(args, cliOptions));
@@ -3,20 +3,23 @@
3
3
  * @license
4
4
  * Copyright 2025 Google LLC
5
5
  * SPDX-License-Identifier: Apache-2.0
6
+ *
7
+ * Modified by Opera Software AS.
6
8
  */
7
- process.title = 'chrome-devtools-mcp';
8
9
  import { version } from 'node:process';
10
+ import { MCP_BIN_NAME } from '../opera/branding.js';
11
+ process.title = MCP_BIN_NAME;
9
12
  const [major, minor] = version.substring(1).split('.').map(Number);
10
13
  if (major === 20 && minor < 19) {
11
- console.error(`ERROR: \`chrome-devtools-mcp\` does not support Node ${process.version}. Please upgrade to Node 20.19.0 LTS or a newer LTS.`);
14
+ console.error(`ERROR: \`${MCP_BIN_NAME}\` does not support Node ${process.version}. Please upgrade to Node 20.19.0 LTS or a newer LTS.`);
12
15
  process.exit(1);
13
16
  }
14
17
  if (major === 22 && minor < 12) {
15
- console.error(`ERROR: \`chrome-devtools-mcp\` does not support Node ${process.version}. Please upgrade to Node 22.12.0 LTS or a newer LTS.`);
18
+ console.error(`ERROR: \`${MCP_BIN_NAME}\` does not support Node ${process.version}. Please upgrade to Node 22.12.0 LTS or a newer LTS.`);
16
19
  process.exit(1);
17
20
  }
18
21
  if (major < 20) {
19
- console.error(`ERROR: \`chrome-devtools-mcp\` does not support Node ${process.version}. Please upgrade to Node 20.19.0 LTS or a newer LTS.`);
22
+ console.error(`ERROR: \`${MCP_BIN_NAME}\` does not support Node ${process.version}. Please upgrade to Node 20.19.0 LTS or a newer LTS.`);
20
23
  process.exit(1);
21
24
  }
22
25
  await import('./chrome-devtools-mcp-main.js');
@@ -3,18 +3,21 @@
3
3
  * @license
4
4
  * Copyright 2026 Google LLC
5
5
  * SPDX-License-Identifier: Apache-2.0
6
+ *
7
+ * Modified by Opera Software AS.
6
8
  */
7
- process.title = 'chrome-devtools';
8
9
  import process from 'node:process';
9
- import { startDaemon, stopDaemon, sendCommand, handleResponse, } from '../daemon/client.js';
10
- import { isDaemonRunning, serializeArgs } from '../daemon/utils.js';
10
+ import { startDaemon, stopDaemon, sendCommand, handleResponse, verifyDaemonVersion, } from '../daemon/client.js';
11
+ import { isDaemonRunning, serializeArgs, assertValidSessionId, } from '../daemon/utils.js';
11
12
  import { logDisclaimers } from '../index.js';
13
+ import { CLI_BIN_NAME, MCP_BIN_NAME, PACKAGE_NAME } from '../opera/branding.js';
12
14
  import { hideBin, yargs } from '../third_party/index.js';
13
15
  import { checkForUpdates } from '../utils/check-for-updates.js';
14
16
  import { VERSION } from '../version.js';
15
17
  import { commands } from './chrome-devtools-cli-options.js';
16
18
  import { cliOptions, parseArguments } from './chrome-devtools-mcp-cli-options.js';
17
- await checkForUpdates('Run `npm install -g chrome-devtools-mcp@latest` and `chrome-devtools start` to update and restart the daemon.');
19
+ process.title = CLI_BIN_NAME;
20
+ await checkForUpdates(`Run \`npm install -g ${PACKAGE_NAME}@latest\` and \`${CLI_BIN_NAME} start\` to update and restart the daemon.`);
18
21
  async function start(args, sessionId) {
19
22
  const combinedArgs = [...args, ...defaultArgs];
20
23
  await startDaemon(combinedArgs, sessionId);
@@ -41,22 +44,50 @@ startCliOptions.isolated.description =
41
44
  'If specified, creates a temporary user-data-dir that is automatically cleaned up after the browser is closed. Defaults to true unless userDataDir is provided.';
42
45
  startCliOptions.categoryExtensions.default = true;
43
46
  const y = yargs(hideBin(process.argv))
44
- .scriptName('chrome-devtools')
47
+ .locale('en') // Force English to ensure error string matching works in .fail, all custom messages we output are in English anyways
48
+ .scriptName(CLI_BIN_NAME)
45
49
  .showHelpOnFail(true)
46
- .usage('chrome-devtools <command> [...args] --flags')
47
- .usage(`Run 'chrome-devtools <command> --help' for help on the specific command.`)
50
+ .usage(`${CLI_BIN_NAME} <command> [...args] --flags`)
51
+ .usage(`Run '${CLI_BIN_NAME} <command> --help' for help on the specific command.`)
48
52
  .option('sessionId', {
49
53
  type: 'string',
50
54
  description: 'Session ID for daemon scoping',
51
55
  default: '',
52
56
  hidden: true,
57
+ coerce: (sessionId) => {
58
+ assertValidSessionId(sessionId);
59
+ return sessionId;
60
+ },
53
61
  })
54
62
  .demandCommand()
55
63
  .version(VERSION)
56
64
  .strict()
57
65
  .help(true)
58
- .wrap(120);
59
- y.command('start', 'Start or restart chrome-devtools-mcp', y => y
66
+ .wrap(120)
67
+ .fail((msg, err) => {
68
+ if (msg) {
69
+ console.error('Error:', msg);
70
+ if (msg.includes('Not enough non-option arguments') ||
71
+ msg.includes('Unknown argument') ||
72
+ msg.includes('Unknown arguments')) {
73
+ console.error('\n=========================================');
74
+ console.error('💡 TIP FOR AI AGENT / DEVELOPER:');
75
+ console.error('In the `chrome-devtools` CLI:');
76
+ console.error('1. Required parameters MUST be passed as positional arguments (without flags).');
77
+ console.error(' - INCORRECT: chrome-devtools evaluate_script --expression "() => document.title"');
78
+ console.error(' - CORRECT: chrome-devtools evaluate_script "() => document.title"');
79
+ console.error('2. Optional parameters are passed as double-dash options/flags (e.g. --pageId 1).');
80
+ console.error('3. Make sure to escape quotes properly for your shell environment.');
81
+ console.error('Run `chrome-devtools <command> --help` to see exact positional and optional parameters.');
82
+ console.error('=========================================');
83
+ }
84
+ }
85
+ else if (err) {
86
+ console.error(err);
87
+ }
88
+ process.exit(1);
89
+ });
90
+ y.command('start', `Start or restart ${MCP_BIN_NAME}`, y => y
60
91
  .options(startCliOptions)
61
92
  .example('$0 start --browserUrl http://localhost:9222', 'Start the server connecting to an existing browser')
62
93
  .strict(), async (argv) => {
@@ -74,9 +105,9 @@ y.command('start', 'Start or restart chrome-devtools-mcp', y => y
74
105
  await start(args, argv.sessionId);
75
106
  process.exit(0);
76
107
  }).strict(); // Re-enable strict validation for other commands; this is applied to the yargs instance itself
77
- y.command('status', 'Checks if chrome-devtools-mcp is running', y => y, async (argv) => {
108
+ y.command('status', `Checks if ${MCP_BIN_NAME} is running`, y => y, async (argv) => {
78
109
  if (isDaemonRunning(argv.sessionId)) {
79
- console.log('chrome-devtools-mcp daemon is running.');
110
+ console.log(`${MCP_BIN_NAME} daemon is running.`);
80
111
  const response = await sendCommand({
81
112
  method: 'status',
82
113
  }, argv.sessionId);
@@ -84,6 +115,9 @@ y.command('status', 'Checks if chrome-devtools-mcp is running', y => y, async (a
84
115
  const data = JSON.parse(response.result);
85
116
  console.log(`pid=${data.pid} socket=${data.socketPath} start-date=${data.startDate} version=${data.version}`);
86
117
  console.log(`args=${JSON.stringify(data.args)}`);
118
+ if (data.version !== VERSION) {
119
+ console.warn(`Warning: Daemon server version (${data.version}) does not match CLI version (${VERSION}). Run 'chrome-devtools start' to update and restart the daemon.`);
120
+ }
87
121
  }
88
122
  else {
89
123
  console.error('Error:', response.error);
@@ -91,11 +125,11 @@ y.command('status', 'Checks if chrome-devtools-mcp is running', y => y, async (a
91
125
  }
92
126
  }
93
127
  else {
94
- console.log('chrome-devtools-mcp daemon is not running.');
128
+ console.log(`${MCP_BIN_NAME} daemon is not running.`);
95
129
  }
96
130
  process.exit(0);
97
131
  });
98
- y.command('stop', 'Stop chrome-devtools-mcp if any', y => y, async (argv) => {
132
+ y.command('stop', `Stop ${MCP_BIN_NAME} if any`, y => y, async (argv) => {
99
133
  const sessionId = argv.sessionId;
100
134
  if (!isDaemonRunning(sessionId)) {
101
135
  process.exit(0);
@@ -157,8 +191,11 @@ for (const [commandName, commandDef] of Object.entries(commands)) {
157
191
  }, async (argv) => {
158
192
  const sessionId = argv.sessionId;
159
193
  try {
194
+ const versionWarningPromise = isDaemonRunning(sessionId)
195
+ ? verifyDaemonVersion(sessionId, VERSION)
196
+ : Promise.resolve(undefined);
160
197
  if (!isDaemonRunning(sessionId)) {
161
- await start([], sessionId);
198
+ await start(serializeArgs(cliOptions, argv), sessionId);
162
199
  }
163
200
  const commandArgs = {};
164
201
  for (const argName of Object.keys(args)) {
@@ -176,6 +213,12 @@ for (const [commandName, commandDef] of Object.entries(commands)) {
176
213
  }
177
214
  else {
178
215
  console.error('Error:', response.error);
216
+ }
217
+ const versionWarning = await versionWarningPromise;
218
+ if (versionWarning) {
219
+ console.warn(versionWarning);
220
+ }
221
+ if (!response.success) {
179
222
  process.exit(1);
180
223
  }
181
224
  }