opera-devtools-mcp 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -7
- package/build/src/McpContext.js +365 -365
- package/build/src/McpPage.js +475 -48
- package/build/src/McpResponse.js +462 -288
- package/build/src/SlimMcpResponse.js +1 -1
- package/build/src/TextSnapshot.js +101 -22
- package/build/src/ToolHandler.js +142 -20
- package/build/src/bin/check-latest-version.js +27 -1
- package/build/src/bin/chrome-devtools-cli-options.js +573 -10
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +119 -32
- package/build/src/bin/chrome-devtools-mcp-main.js +50 -7
- package/build/src/bin/chrome-devtools-mcp.js +7 -4
- package/build/src/bin/chrome-devtools.js +57 -14
- package/build/src/bin/opera-devtools-cli-options.js +3 -829
- package/build/src/bin/opera-devtools-mcp-cli-options.js +3 -348
- package/build/src/bin/opera-devtools-mcp-main.js +3 -37
- package/build/src/bin/opera-devtools-mcp.js +4 -19
- package/build/src/bin/opera-devtools.js +4 -185
- package/build/src/browser.js +45 -5
- package/build/src/{PageCollector.js → collectors/PageCollector.js} +64 -133
- package/build/src/collectors/ServiceWorkerCollector.js +171 -0
- package/build/src/daemon/client.js +75 -17
- package/build/src/daemon/daemon.js +92 -30
- package/build/src/daemon/utils.js +24 -8
- package/build/src/{DevtoolsUtils.js → devtools/DevtoolsUtils.js} +94 -88
- package/build/src/devtools/McpHostBindingAdapter.js +165 -0
- package/build/src/{issue-descriptions.js → devtools/issueDescriptions.js} +8 -6
- package/build/src/formatters/ConsoleFormatter.js +44 -11
- package/build/src/formatters/HeapSnapshotFormatter.js +140 -9
- package/build/src/formatters/IssueFormatter.js +7 -7
- package/build/src/formatters/NetworkFormatter.js +10 -8
- package/build/src/index.js +101 -232
- package/build/src/opera/branding.js +34 -0
- package/build/src/opera/browserFlags.js +85 -0
- package/build/src/opera/browserLaunch.js +52 -0
- package/build/src/opera/policy.js +50 -0
- package/build/src/opera/serviceWorkerRetry.js +37 -0
- package/build/src/opera/toolHandlerHooks.js +39 -0
- package/build/src/{tools → opera/tools}/opera.js +9 -21
- package/build/src/processors/HeapSnapshotManager.js +258 -0
- package/build/src/{trace-processing/parse.js → processors/PerformanceTrace.js} +9 -9
- package/build/src/telemetry/ClearcutLogger.js +12 -119
- package/build/src/telemetry/WatchdogClient.js +5 -5
- package/build/src/telemetry/errors.js +1 -1
- package/build/src/telemetry/flagUtils.js +6 -6
- package/build/src/telemetry/{toolMetricsUtils.js → metricsRegistry.js} +4 -11
- package/build/src/telemetry/persistence.js +3 -3
- package/build/src/telemetry/transformation.js +184 -0
- package/build/src/telemetry/watchdog/ClearcutSender.js +11 -11
- package/build/src/telemetry/watchdog/main.js +6 -6
- package/build/src/third_party/THIRD_PARTY_NOTICES +3493 -0
- package/build/src/third_party/bundled-packages.json +9 -0
- package/build/src/third_party/devtools-formatter-worker.js +15340 -7
- package/build/src/third_party/devtools-heap-snapshot-worker.js +10337 -7
- package/build/src/third_party/index.js +179960 -26
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +2 -2
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +3 -3
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +2 -2
- package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +1 -1
- package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +1 -1
- package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +2 -2
- package/build/src/third_party/issue-descriptions/LowTextContrast.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +3 -3
- package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +3 -3
- package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +1 -1
- package/build/src/third_party/issue-descriptions/connectionAllowlistEmbeddingRequirementNotSatisfied.md +26 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistIFrameAttributeLoosensEmbeddingRequirement.md +19 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowConnectionAllowlistFrom.md +21 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +2 -2
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +2 -2
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +3 -3
- package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +2 -2
- package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +2 -2
- package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +3 -3
- package/build/src/third_party/issue-descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +1 -1
- package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +1 -1
- package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +2 -2
- package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +2 -2
- package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +3 -3
- package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +1 -1
- package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +1 -1
- package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +3 -3
- package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +2 -2
- package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +3 -3
- package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +4 -3
- package/build/src/third_party/issue-descriptions/cspEvalViolation.md +4 -4
- package/build/src/third_party/issue-descriptions/cspInlineViolation.md +2 -2
- package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +2 -2
- package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +4 -4
- package/build/src/third_party/issue-descriptions/cspURLViolation.md +4 -4
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsEmptyList.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsFetchFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsInvalidRecord.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestInvalidEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestKeyBindingSigningFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestRpOriginIsOpaque.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidSdJwt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenMalformedSdJwt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidAudience.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidIssuedAt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidNonce.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidSdHash.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidTyp.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingAud.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingCnf.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingIat.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingNonce.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingSdHash.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbSignatureFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmailVerified.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidHolderKey.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuedAt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuer.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtJwksMissingKeys.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingCnf.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIat.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIss.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtSignatureFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtUnsupportedHeaderAlg.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestUserLoggedOut.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownAccountsEndpointCrossOrigin.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownIssuanceEndpointCrossOrigin.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownListEmpty.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingAccountsEndpoint.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingIssuanceEndpoint.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownUnsupportedSigningAlgorithm.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -1
- package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +2 -2
- package/build/src/third_party/issue-descriptions/genericBackUINavigationWouldSkipAd.md +4 -0
- package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +2 -2
- package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +2 -2
- package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +2 -2
- package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +2 -2
- package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +1 -1
- package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +2 -2
- package/build/src/third_party/issue-descriptions/heavyAd.md +1 -1
- package/build/src/third_party/issue-descriptions/lazyLoadImageZeroSize.md +7 -0
- package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +3 -3
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +1 -1
- package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +3 -3
- package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +2 -2
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +2 -2
- package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +4 -4
- package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +4 -4
- package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +1 -1
- package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +4 -4
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +4 -4
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +1 -1
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +1 -1
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +1 -1
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +5 -5
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +3 -3
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +2 -2
- package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +4 -4
- package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +3 -3
- package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +2 -2
- package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +2 -2
- package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +1 -1
- package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +1 -1
- package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +2 -2
- package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +3 -3
- package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +2 -2
- package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +1 -1
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +3177 -6340
- package/build/src/tools/ToolDefinition.js +2 -2
- package/build/src/tools/categories.js +3 -0
- package/build/src/tools/console.js +13 -0
- package/build/src/tools/emulation.js +30 -3
- package/build/src/tools/extensions.js +8 -1
- package/build/src/tools/input.js +246 -128
- package/build/src/tools/lighthouse.js +14 -7
- package/build/src/tools/memory.js +289 -25
- package/build/src/tools/network.js +10 -7
- package/build/src/tools/pages.js +33 -92
- package/build/src/tools/performance.js +67 -52
- package/build/src/tools/pwa.js +128 -0
- package/build/src/tools/screencast.js +35 -12
- package/build/src/tools/screenshot.js +234 -75
- package/build/src/tools/script.js +130 -45
- package/build/src/tools/slim/tools.js +3 -0
- package/build/src/tools/snapshot.js +7 -4
- package/build/src/tools/thirdPartyDeveloper.js +19 -9
- package/build/src/tools/tools.js +3 -1
- package/build/src/tools/webmcp.js +3 -1
- package/build/src/utils/WaitForHelper.js +299 -0
- package/build/src/utils/check-for-updates.js +8 -2
- package/build/src/utils/files.js +42 -3
- package/build/src/utils/logger.js +51 -0
- package/build/src/utils/polyfill.js +11 -0
- package/build/src/utils/url.js +43 -0
- package/build/src/version.js +1 -1
- package/package.json +42 -33
- package/build/src/DevToolsConnectionAdapter.js +0 -70
- package/build/src/HeapSnapshotManager.js +0 -110
- package/build/src/Mutex.js +0 -38
- package/build/src/WaitForHelper.js +0 -195
- package/build/src/bin/cliDefinitions.js +0 -616
- package/build/src/logger.js +0 -37
- package/build/src/polyfill.js +0 -8
- package/build/src/telemetry/metricUtils.js +0 -15
- package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeRead.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeSet.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteExcludeNavigationContextDowngrade.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeRead.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeSet.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteWarnStrictLaxDowngradeStrict.md +0 -8
- package/build/src/third_party/issue-descriptions/arInsecureContext.md +0 -7
- package/build/src/third_party/issue-descriptions/arInvalidInfoHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arInvalidRegisterSourceHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arInvalidRegisterTriggerHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
- package/build/src/third_party/issue-descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
- package/build/src/third_party/issue-descriptions/arNoRegisterOsSourceHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNoRegisterOsTriggerHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNoRegisterSourceHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNoRegisterTriggerHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNoWebOrOsSupport.md +0 -4
- package/build/src/third_party/issue-descriptions/arOsSourceIgnored.md +0 -18
- package/build/src/third_party/issue-descriptions/arOsTriggerIgnored.md +0 -19
- package/build/src/third_party/issue-descriptions/arPermissionPolicyDisabled.md +0 -8
- package/build/src/third_party/issue-descriptions/arSourceAndTriggerHeaders.md +0 -9
- package/build/src/third_party/issue-descriptions/arSourceIgnored.md +0 -13
- package/build/src/third_party/issue-descriptions/arTriggerIgnored.md +0 -12
- package/build/src/third_party/issue-descriptions/arUntrustworthyReportingOrigin.md +0 -10
- package/build/src/third_party/issue-descriptions/arWebAndOsHeaders.md +0 -11
- package/build/src/utils/string.js +0 -37
- 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:
|
|
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:
|
|
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
|
-
|
|
153
|
+
memoryDebugging: {
|
|
153
154
|
type: 'boolean',
|
|
154
|
-
describe: 'Whether to enable
|
|
155
|
-
|
|
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
|
-
|
|
162
|
+
experimentalToonFormat: {
|
|
163
163
|
type: 'boolean',
|
|
164
|
-
describe: '
|
|
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
|
-
|
|
168
|
-
type: '
|
|
169
|
-
describe: '
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
227
|
-
describe:
|
|
247
|
+
default: PERFORMANCE_CRUX_DEFAULT,
|
|
248
|
+
describe: PERFORMANCE_CRUX_DESCRIPTION,
|
|
228
249
|
},
|
|
229
250
|
usageStatistics: {
|
|
230
251
|
type: 'boolean',
|
|
231
|
-
default:
|
|
232
|
-
describe:
|
|
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
|
|
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
|
-
|
|
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(
|
|
350
|
+
.scriptName(`npx ${PACKAGE_NAME}@latest`)
|
|
267
351
|
.options(cliOptions)
|
|
268
|
-
.
|
|
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[
|
|
278
|
-
console.error(
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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(
|
|
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
|
-
|
|
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
|
|
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(
|
|
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: \`
|
|
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: \`
|
|
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: \`
|
|
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
|
-
|
|
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
|
-
.
|
|
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(
|
|
47
|
-
.usage(`Run '
|
|
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
|
-
|
|
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',
|
|
108
|
+
y.command('status', `Checks if ${MCP_BIN_NAME} is running`, y => y, async (argv) => {
|
|
78
109
|
if (isDaemonRunning(argv.sessionId)) {
|
|
79
|
-
console.log(
|
|
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(
|
|
128
|
+
console.log(`${MCP_BIN_NAME} daemon is not running.`);
|
|
95
129
|
}
|
|
96
130
|
process.exit(0);
|
|
97
131
|
});
|
|
98
|
-
y.command('stop',
|
|
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(
|
|
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
|
}
|