machine-bridge-mcp 2.0.0 → 3.0.0-beta.102
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/CHANGELOG.md +1142 -0
- package/CONTRIBUTING.md +23 -25
- package/GOVERNANCE.md +2 -2
- package/README.md +58 -20
- package/SECURITY.md +161 -120
- package/SUPPORT.md +1 -1
- package/browser-extension/broker-auth.js +83 -0
- package/browser-extension/broker-liveness.js +35 -0
- package/browser-extension/browser-error-boundary.js +96 -0
- package/browser-extension/browser-operations.js +1456 -101
- package/browser-extension/devtools-input.js +195 -34
- package/browser-extension/devtools-observation.js +429 -0
- package/browser-extension/devtools-session.js +48 -0
- package/browser-extension/manifest.json +4 -3
- package/browser-extension/page-automation.js +578 -118
- package/browser-extension/pairing-bootstrap.js +42 -0
- package/browser-extension/pairing.js +28 -12
- package/browser-extension/service-worker.js +126 -106
- package/docs/AGENT_CONTEXT.md +13 -10
- package/docs/ARCHITECTURE.md +159 -67
- package/docs/AUDIT.md +1302 -4
- package/docs/CLIENTS.md +19 -6
- package/docs/COMPUTER_USE.md +297 -0
- package/docs/ENGINEERING.md +72 -13
- package/docs/GETTING_STARTED.md +18 -20
- package/docs/LOCAL_AUTHORIZATION.md +115 -72
- package/docs/LOCAL_AUTOMATION.md +27 -21
- package/docs/LOGGING.md +40 -19
- package/docs/MANAGED_JOBS.md +37 -34
- package/docs/MULTI_ACCOUNT.md +98 -37
- package/docs/OPERATIONS.md +145 -51
- package/docs/OVERVIEW.md +14 -11
- package/docs/POLICY_REFERENCE.md +71 -3
- package/docs/PRIVACY.md +41 -2
- package/docs/PROJECT_STANDARDS.md +29 -6
- package/docs/RELEASING.md +238 -64
- package/docs/TESTING.md +150 -39
- package/docs/THREAT_MODEL.md +164 -67
- package/docs/TOOL_REFERENCE.md +653 -60
- package/docs/UPGRADING.md +78 -18
- package/native/macos/MachineBridgeBackgroundInput.swift +1051 -0
- package/native/macos/MachineBridgeBackgroundInputSmokeFixture.swift +295 -0
- package/native/macos/MachineBridgeTrustBroker.swift +233 -0
- package/package.json +94 -16
- package/scripts/accepted-candidate-tarball.mjs +77 -0
- package/scripts/candidate-runtime-store.mjs +93 -0
- package/scripts/check-plan.mjs +73 -3
- package/scripts/check-runner.mjs +129 -17
- package/scripts/commit-message-check.mjs +5 -2
- package/scripts/consumer-package-security.mjs +293 -0
- package/scripts/coverage-check.mjs +251 -15
- package/scripts/coverage-generation.mjs +41 -0
- package/scripts/coverage-range-merge.mjs +41 -0
- package/scripts/foreground-daemon-recovery.mjs +88 -0
- package/scripts/generate-policy-reference.mjs +28 -5
- package/scripts/generate-tool-reference.mjs +1 -1
- package/scripts/generate-worker-types.mjs +21 -11
- package/scripts/github-backlog.mjs +11 -10
- package/scripts/github-push.mjs +62 -16
- package/scripts/github-release-asset.mjs +58 -0
- package/scripts/github-release.mjs +241 -132
- package/scripts/global-package-installation.mjs +68 -0
- package/scripts/hardened-npm-session.mjs +42 -0
- package/scripts/install-published-prerelease.mjs +198 -0
- package/scripts/local-release-acceptance.mjs +103 -45
- package/scripts/macos-background-input-smoke.mjs +515 -0
- package/scripts/network-retry.mjs +8 -1
- package/scripts/npm-global-prefix.mjs +27 -0
- package/scripts/npm-publication-policy.mjs +17 -0
- package/scripts/official-mcp-conformance.mjs +267 -0
- package/scripts/persistent-activation-process.mjs +101 -0
- package/scripts/prepare-pinned-npm.mjs +12 -69
- package/scripts/prerelease-activation.mjs +160 -0
- package/scripts/privacy-check.mjs +14 -6
- package/scripts/promotion-digest.mjs +128 -0
- package/scripts/publish-npm.mjs +260 -0
- package/scripts/published-release.mjs +132 -0
- package/scripts/release-acceptance.mjs +62 -54
- package/scripts/release-browser-extension-store.mjs +172 -0
- package/scripts/release-candidate-manifest.mjs +52 -0
- package/scripts/release-channel.mjs +106 -0
- package/scripts/release-diagnostic.mjs +41 -0
- package/scripts/release-impact-check.mjs +12 -22
- package/scripts/release-oauth-canary-core.mjs +325 -0
- package/scripts/release-oauth-canary-evidence.mjs +100 -0
- package/scripts/release-oauth-canary.mjs +127 -0
- package/scripts/release-publication-guard.mjs +67 -0
- package/scripts/release-soak.mjs +284 -0
- package/scripts/release-state.mjs +1 -1
- package/scripts/run-checks.mjs +44 -7
- package/scripts/run-worker-dry-run.mjs +21 -0
- package/scripts/sarif-security-gate.mjs +2 -1
- package/scripts/sbom-check.mjs +106 -0
- package/scripts/start-release-candidate.mjs +267 -44
- package/scripts/syntax-check.mjs +36 -14
- package/scripts/verification-generation-guard.mjs +15 -0
- package/scripts/verification-idle-sleep-guard.mjs +37 -0
- package/scripts/verification-state.mjs +108 -0
- package/scripts/wrangler-command-lifecycle.mjs +115 -0
- package/src/local/account-access.mjs +13 -1
- package/src/local/account-admin-response.mjs +92 -0
- package/src/local/account-admin.mjs +52 -19
- package/src/local/agent-context-projection.mjs +26 -7
- package/src/local/agent-context.mjs +88 -49
- package/src/local/agent-skill-discovery.mjs +16 -5
- package/src/local/app-automation-macos-jxa.mjs +350 -0
- package/src/local/app-automation.mjs +873 -163
- package/src/local/application-capability-projection.mjs +24 -0
- package/src/local/authority-context.mjs +106 -0
- package/src/local/autostart-log-maintenance.mjs +36 -0
- package/src/local/browser-bridge-http.mjs +5 -3
- package/src/local/browser-bridge.mjs +109 -31
- package/src/local/browser-broker-auth-http.mjs +67 -0
- package/src/local/browser-broker-auth.mjs +98 -0
- package/src/local/browser-broker-routes.mjs +63 -20
- package/src/local/browser-broker-server.mjs +17 -7
- package/src/local/browser-command.mjs +79 -30
- package/src/local/browser-computer-observation-service.mjs +266 -0
- package/src/local/browser-extension-identity.mjs +50 -0
- package/src/local/browser-extension-path.mjs +22 -0
- package/src/local/browser-extension-protocol.mjs +50 -11
- package/src/local/browser-operation-service.mjs +147 -117
- package/src/local/browser-pairing-grant.mjs +109 -0
- package/src/local/browser-pairing-http.mjs +36 -0
- package/src/local/browser-pairing-launch.mjs +58 -0
- package/src/local/browser-pairing-store.mjs +85 -48
- package/src/local/browser-request-registry.mjs +40 -14
- package/src/local/browser-request-settlement.mjs +78 -0
- package/src/local/browser-resource-input.mjs +74 -0
- package/src/local/browser-trusted-input-health.mjs +63 -0
- package/src/local/call-authority.mjs +21 -0
- package/src/local/call-capacity.mjs +45 -0
- package/src/local/call-registry-drain.mjs +54 -0
- package/src/local/call-registry.mjs +30 -15
- package/src/local/capability-observer.mjs +5 -0
- package/src/local/capability-ranking.mjs +3 -2
- package/src/local/child-process-settlement.mjs +132 -0
- package/src/local/cli-account-admin.mjs +40 -6
- package/src/local/cli-activate.mjs +162 -0
- package/src/local/cli-local-admin.mjs +20 -45
- package/src/local/cli-options.mjs +12 -13
- package/src/local/cli-ready-output.mjs +52 -0
- package/src/local/cli-service.mjs +91 -11
- package/src/local/cli.mjs +232 -150
- package/src/local/computer-use-application-observation.mjs +224 -0
- package/src/local/computer-use-arguments.mjs +270 -0
- package/src/local/computer-use-deadline.mjs +50 -0
- package/src/local/computer-use-dispatch-settlement.mjs +40 -0
- package/src/local/computer-use-expectation.mjs +171 -0
- package/src/local/computer-use-observation.mjs +769 -0
- package/src/local/computer-use-recovery.mjs +82 -0
- package/src/local/computer-use-result-budget.mjs +145 -0
- package/src/local/computer-use-snapshot-store.mjs +67 -0
- package/src/local/computer-use.mjs +2255 -0
- package/src/local/daemon-http-relay-auth.mjs +26 -0
- package/src/local/daemon-http-relay-connection.mjs +298 -0
- package/src/local/daemon-http-relay-request.mjs +64 -0
- package/src/local/daemon-http-relay-sequence.mjs +49 -0
- package/src/local/daemon-process.mjs +40 -7
- package/src/local/delegated-process-sandbox.mjs +148 -0
- package/src/local/device-identity.mjs +156 -49
- package/src/local/device-root-provider.mjs +81 -0
- package/src/local/directory-metadata.mjs +47 -0
- package/src/local/doctor-reporting.mjs +23 -0
- package/src/local/durable-process-spec.mjs +80 -0
- package/src/local/errors.mjs +25 -15
- package/src/local/exclusive-file.mjs +74 -26
- package/src/local/execution-limits.mjs +9 -0
- package/src/local/execution-routing.mjs +276 -0
- package/src/local/execution-surface.mjs +23 -0
- package/src/local/file-mutation-coordinator.mjs +47 -0
- package/src/local/file-snapshot-preservation.mjs +24 -0
- package/src/local/filesystem-identity.mjs +54 -0
- package/src/local/fixed-process-environment.mjs +21 -0
- package/src/local/full-access-test.mjs +31 -13
- package/src/local/git-commit.mjs +69 -0
- package/src/local/git-config-safety.mjs +55 -0
- package/src/local/git-log-parser.mjs +41 -0
- package/src/local/git-metadata-boundary.mjs +77 -0
- package/src/local/git-metadata-tree-safety.mjs +59 -0
- package/src/local/git-operation-state.mjs +19 -0
- package/src/local/git-service.mjs +165 -30
- package/src/local/hardened-npm-download-timeout.mjs +46 -0
- package/src/local/hardened-npm-download.mjs +109 -0
- package/src/local/hardened-npm-extract.mjs +20 -0
- package/src/local/hardened-npm-verification.mjs +104 -0
- package/src/local/hardened-npm.mjs +199 -0
- package/src/local/job-runner.mjs +244 -89
- package/src/local/lifecycle.mjs +6 -0
- package/src/local/log.mjs +19 -45
- package/src/local/macos-background-input.mjs +398 -0
- package/src/local/macos-idle-sleep-assertion.mjs +65 -0
- package/src/local/macos-trust-broker.mjs +404 -0
- package/src/local/managed-job-cancellation.mjs +42 -0
- package/src/local/managed-job-capacity.mjs +16 -0
- package/src/local/managed-job-directory-generation.mjs +60 -0
- package/src/local/managed-job-directory.mjs +75 -0
- package/src/local/managed-job-durable-process.mjs +49 -0
- package/src/local/managed-job-lock.mjs +46 -14
- package/src/local/managed-job-plan.mjs +38 -14
- package/src/local/managed-job-projection.mjs +23 -15
- package/src/local/managed-job-retention.mjs +128 -0
- package/src/local/managed-job-runner-claim.mjs +70 -0
- package/src/local/managed-job-runner.mjs +35 -10
- package/src/local/managed-job-storage.mjs +22 -6
- package/src/local/managed-job-terminal-maintenance.mjs +40 -0
- package/src/local/managed-job-terminal.mjs +150 -0
- package/src/local/managed-jobs.mjs +424 -287
- package/src/local/npm-cli.mjs +42 -0
- package/src/local/npm-environment.mjs +37 -0
- package/src/local/operation-authorization.mjs +68 -324
- package/src/local/operation-risk.mjs +51 -4
- package/src/local/owner-state-lock.mjs +118 -0
- package/src/local/package-identity.mjs +9 -0
- package/src/local/patch.mjs +20 -18
- package/src/local/path-inspection.mjs +23 -0
- package/src/local/policy.mjs +19 -0
- package/src/local/private-toolchain-integrity.mjs +54 -0
- package/src/local/process-execution.mjs +87 -75
- package/src/local/process-foreground-timeout.mjs +50 -0
- package/src/local/process-identity.mjs +41 -7
- package/src/local/process-nonreplayable-settlement.mjs +50 -0
- package/src/local/process-result-projection.mjs +22 -0
- package/src/local/process-session-events.mjs +47 -0
- package/src/local/process-session-remote-activity.mjs +10 -0
- package/src/local/process-session-termination.mjs +73 -0
- package/src/local/process-sessions.mjs +144 -112
- package/src/local/process-tracker.mjs +140 -13
- package/src/local/process-tree-ownership-types.d.ts +37 -0
- package/src/local/process-tree-ownership.mjs +57 -0
- package/src/local/process-tree-signal.mjs +34 -0
- package/src/local/process-tree-snapshot.mjs +77 -0
- package/src/local/process-tree-supervisor.mjs +69 -0
- package/src/local/process-tree.mjs +11 -53
- package/src/local/project-metadata.mjs +19 -6
- package/src/local/relay-call-recovery.mjs +58 -38
- package/src/local/relay-connection-classification.mjs +131 -0
- package/src/local/relay-connection-support.mjs +91 -0
- package/src/local/relay-connection.mjs +179 -272
- package/src/local/relay-diagnostics.mjs +91 -0
- package/src/local/relay-heartbeat.mjs +119 -0
- package/src/local/relay-liveness.mjs +109 -0
- package/src/local/relay-peer-diagnostics.mjs +29 -0
- package/src/local/release-runtime-lock.mjs +18 -0
- package/src/local/remote-activity-idle-sleep-guard.mjs +77 -0
- package/src/local/remote-configuration.mjs +48 -0
- package/src/local/resilient-relay-connection.mjs +178 -0
- package/src/local/resource-admission-diagnostics.mjs +52 -0
- package/src/local/resource-admission-policy.mjs +115 -0
- package/src/local/resource-admission.mjs +339 -0
- package/src/local/resource-build-root.mjs +83 -0
- package/src/local/resource-cargo-concurrency.mjs +38 -0
- package/src/local/resource-cmake-concurrency.mjs +42 -0
- package/src/local/resource-command-concurrency.mjs +37 -0
- package/src/local/resource-command-profile.mjs +176 -0
- package/src/local/resource-coordinator-accounting.mjs +21 -0
- package/src/local/resource-cpu-window.mjs +20 -0
- package/src/local/resource-disk-headroom.mjs +13 -0
- package/src/local/resource-elastic-memory.mjs +19 -0
- package/src/local/resource-elastic-request.mjs +36 -0
- package/src/local/resource-foreground-wait.mjs +29 -0
- package/src/local/resource-go-concurrency.mjs +43 -0
- package/src/local/resource-gradle-concurrency.mjs +57 -0
- package/src/local/resource-host-cache.mjs +39 -0
- package/src/local/resource-host-darwin.mjs +54 -0
- package/src/local/resource-host-linux.mjs +35 -0
- package/src/local/resource-host-sample-file.mjs +23 -0
- package/src/local/resource-host-snapshot.mjs +99 -0
- package/src/local/resource-lease-accounting.mjs +119 -0
- package/src/local/resource-light-command.mjs +6 -0
- package/src/local/resource-make-concurrency.mjs +42 -0
- package/src/local/resource-maven-concurrency.mjs +38 -0
- package/src/local/resource-ninja-command-concurrency.mjs +20 -0
- package/src/local/resource-ninja-concurrency.mjs +28 -0
- package/src/local/resource-operations.mjs +26 -10
- package/src/local/resource-pressure.mjs +67 -0
- package/src/local/resource-probe-command.mjs +35 -0
- package/src/local/resource-process-admission.mjs +59 -0
- package/src/local/resource-process-ancestry-cache.mjs +43 -0
- package/src/local/resource-process-ancestry.mjs +32 -0
- package/src/local/resource-process-priority.mjs +15 -0
- package/src/local/resource-project-key.mjs +53 -0
- package/src/local/resource-pytest-concurrency.mjs +33 -0
- package/src/local/resource-release-control-classification.mjs +14 -0
- package/src/local/resource-release-control-executable.mjs +70 -0
- package/src/local/resource-release-control-workspace.mjs +41 -0
- package/src/local/resource-request-contract.mjs +30 -0
- package/src/local/resource-script-classification.mjs +44 -0
- package/src/local/resource-shell-analysis.mjs +58 -0
- package/src/local/resource-staging-recovery.mjs +97 -0
- package/src/local/resource-swift-concurrency.mjs +31 -0
- package/src/local/resource-transaction-lock.mjs +189 -0
- package/src/local/resource-wait.mjs +48 -0
- package/src/local/resource-waiters.mjs +139 -0
- package/src/local/resource-xcode-command.mjs +7 -0
- package/src/local/resource-xcode-concurrency.mjs +34 -0
- package/src/local/resource-xcode-non-build.mjs +19 -0
- package/src/local/runtime-activation.mjs +700 -0
- package/src/local/runtime-activity-projection.mjs +48 -0
- package/src/local/runtime-capabilities.mjs +48 -15
- package/src/local/runtime-diagnostic-state.mjs +14 -0
- package/src/local/runtime-diagnostics.mjs +40 -13
- package/src/local/runtime-info-projection.mjs +60 -0
- package/src/local/runtime-info-relay-projection.mjs +21 -0
- package/src/local/runtime-paths.mjs +2 -1
- package/src/local/runtime-process-routing.mjs +33 -0
- package/src/local/runtime-relay-connection-options.mjs +44 -0
- package/src/local/runtime-relay-control.mjs +98 -0
- package/src/local/runtime-relay.mjs +26 -50
- package/src/local/runtime-reporting.mjs +37 -21
- package/src/local/runtime-resource-service.mjs +77 -0
- package/src/local/runtime-tool-handlers.mjs +13 -10
- package/src/local/runtime.mjs +244 -208
- package/src/local/secure-file.mjs +73 -20
- package/src/local/security-audit-dispatch.mjs +35 -0
- package/src/local/security-audit-log.mjs +215 -0
- package/src/local/security-audit-state.mjs +139 -0
- package/src/local/security-audit-storage.mjs +135 -0
- package/src/local/security-audit-warning.mjs +31 -0
- package/src/local/security-audit-worker.mjs +87 -0
- package/src/local/service-convergence.mjs +42 -1
- package/src/local/service-definition.mjs +24 -0
- package/src/local/service-environment.mjs +18 -10
- package/src/local/service-owner.mjs +146 -0
- package/src/local/service-ownership.mjs +17 -0
- package/src/local/service-restart-handoff.mjs +64 -0
- package/src/local/service-restart-scheduler.mjs +49 -0
- package/src/local/service-runtime-convergence.mjs +52 -0
- package/src/local/service-runtime.mjs +105 -0
- package/src/local/service-status.mjs +60 -0
- package/src/local/service.mjs +385 -92
- package/src/local/shell.mjs +39 -19
- package/src/local/ssh-key.mjs +158 -42
- package/src/local/state-inventory.mjs +50 -24
- package/src/local/state-owner-lock-inventory.mjs +23 -0
- package/src/local/state-root-owned-namespaces.mjs +83 -0
- package/src/local/state-root-retirement.mjs +89 -0
- package/src/local/state.mjs +386 -96
- package/src/local/stdio.mjs +96 -66
- package/src/local/support-state-projection.mjs +30 -0
- package/src/local/system-network-route.mjs +76 -0
- package/src/local/systemd-removal.mjs +20 -0
- package/src/local/tool-executor.mjs +85 -20
- package/src/local/tool-result-boundary.mjs +51 -0
- package/src/local/toolchain-operation-lock.mjs +41 -0
- package/src/local/tools.mjs +7 -5
- package/src/local/trusted-executable.mjs +53 -0
- package/src/local/trusted-git-executable.mjs +34 -0
- package/src/local/trusted-github-cli.mjs +24 -0
- package/src/local/windows-service-convergence.mjs +49 -0
- package/src/local/windows-service.mjs +52 -45
- package/src/local/worker-deployment-fingerprint.mjs +102 -0
- package/src/local/worker-deployment.mjs +48 -60
- package/src/local/worker-health.mjs +12 -4
- package/src/local/worker-secret-file.mjs +37 -17
- package/src/local/workspace-file-service.mjs +156 -239
- package/src/local/workspace-file-transaction.mjs +189 -0
- package/src/local/workspace-search.mjs +55 -0
- package/src/local/wrangler-toolchain/package-lock.json +1505 -0
- package/src/local/wrangler-toolchain/package.json +23 -0
- package/src/local/wrangler-toolchain-verification.mjs +135 -0
- package/src/local/wrangler-toolchain.mjs +188 -0
- package/src/shared/access-contract.json +7 -1
- package/src/shared/activation-recovery.mjs +49 -0
- package/src/shared/admin-auth.d.mts +2 -1
- package/src/shared/admin-auth.mjs +3 -3
- package/src/shared/authority-revocation.d.mts +9 -0
- package/src/shared/authority-revocation.mjs +28 -0
- package/src/shared/daemon-auth.d.mts +11 -0
- package/src/shared/daemon-auth.mjs +17 -0
- package/src/shared/device-session-auth.d.mts +20 -0
- package/src/shared/device-session-auth.mjs +51 -0
- package/src/shared/foreground-timeout.d.mts +15 -0
- package/src/shared/foreground-timeout.mjs +70 -0
- package/src/shared/log-redaction.d.mts +9 -0
- package/src/shared/log-redaction.mjs +51 -0
- package/src/shared/mcp-protocol.d.mts +27 -0
- package/src/shared/mcp-protocol.mjs +275 -0
- package/src/shared/project-overview-projection.d.mts +4 -0
- package/src/shared/project-overview-projection.mjs +96 -0
- package/src/shared/relay-contract.json +28 -0
- package/src/shared/result-projection.d.mts +2 -1
- package/src/shared/result-projection.mjs +13 -2
- package/src/shared/server-metadata.json +15 -9
- package/src/shared/tool-argument-validation.d.mts +17 -0
- package/src/shared/tool-argument-validation.mjs +325 -0
- package/src/shared/tool-call-capacity.d.mts +41 -0
- package/src/shared/tool-call-capacity.mjs +59 -0
- package/src/shared/tool-catalog.json +626 -57
- package/src/worker/access.ts +12 -0
- package/src/worker/account-admin.ts +55 -33
- package/src/worker/authority-revocations.ts +174 -0
- package/src/worker/authority.ts +52 -6
- package/src/worker/daemon-auth.ts +49 -68
- package/src/worker/daemon-channel.ts +36 -0
- package/src/worker/daemon-http-auth.ts +63 -0
- package/src/worker/daemon-http-channel.ts +120 -0
- package/src/worker/daemon-http-controller.ts +163 -0
- package/src/worker/daemon-http-protocol.ts +62 -0
- package/src/worker/daemon-http-registry.ts +82 -0
- package/src/worker/daemon-last-observation.ts +30 -0
- package/src/worker/daemon-liveness.ts +8 -6
- package/src/worker/daemon-ready-dispatch.ts +17 -0
- package/src/worker/daemon-ready-messages.ts +73 -0
- package/src/worker/daemon-ready-waiters.ts +79 -0
- package/src/worker/daemon-recovery-budget.ts +13 -0
- package/src/worker/daemon-registry.ts +58 -0
- package/src/worker/daemon-relay-diagnostics.ts +127 -0
- package/src/worker/daemon-socket-attachment.ts +55 -0
- package/src/worker/daemon-sockets.ts +72 -62
- package/src/worker/daemon-status.ts +38 -0
- package/src/worker/device-session-verifier.ts +129 -0
- package/src/worker/dpop.ts +157 -0
- package/src/worker/durable-process-timeout.ts +29 -0
- package/src/worker/errors.ts +57 -0
- package/src/worker/http.ts +112 -26
- package/src/worker/index.ts +446 -440
- package/src/worker/mcp-access.ts +57 -0
- package/src/worker/mcp-controller.ts +188 -0
- package/src/worker/mcp-http-accept.ts +11 -0
- package/src/worker/mcp-http-contract.ts +322 -0
- package/src/worker/mcp-initialization-compat.ts +141 -0
- package/src/worker/mcp-jsonrpc.ts +11 -29
- package/src/worker/mcp-removed-protocol.ts +17 -0
- package/src/worker/mcp-response-proxy.ts +135 -0
- package/src/worker/mcp-response-stream.ts +65 -0
- package/src/worker/mcp-stale-schema-compat.ts +57 -0
- package/src/worker/mcp-stream-proxy-contract.ts +48 -0
- package/src/worker/mcp-tool-call-input.ts +23 -0
- package/src/worker/nonce-store.ts +33 -35
- package/src/worker/oauth-authorization-page.ts +21 -1
- package/src/worker/oauth-client-admin.ts +52 -0
- package/src/worker/oauth-client-contract.ts +38 -0
- package/src/worker/oauth-controller.ts +107 -47
- package/src/worker/oauth-field-contract.ts +31 -0
- package/src/worker/oauth-record-contract.ts +7 -0
- package/src/worker/oauth-refresh-authority.ts +27 -0
- package/src/worker/oauth-refresh-exchange.ts +162 -0
- package/src/worker/oauth-refresh-families.ts +130 -27
- package/src/worker/oauth-refresh-persistence.ts +116 -0
- package/src/worker/oauth-state.ts +33 -18
- package/src/worker/oauth-store-validation.ts +131 -0
- package/src/worker/oauth-token-derivation.ts +33 -0
- package/src/worker/oauth-token-issuance.ts +119 -0
- package/src/worker/oauth-tokens.ts +56 -190
- package/src/worker/observability.ts +38 -5
- package/src/worker/pending-admission.ts +15 -0
- package/src/worker/pending-call-capacity.ts +108 -0
- package/src/worker/pending-call-contract.ts +42 -5
- package/src/worker/pending-call-deadlines.ts +75 -0
- package/src/worker/pending-calls.ts +131 -125
- package/src/worker/runtime-alarm-storage.ts +37 -0
- package/src/worker/runtime-alarm.ts +136 -0
- package/src/worker/server-info-activity.ts +36 -0
- package/src/worker/server-info-tool-delivery.ts +15 -0
- package/src/worker/server-info.ts +168 -0
- package/src/worker/tool-catalog.ts +47 -1
- package/src/worker/tool-timeout.ts +75 -14
- package/src/worker/websocket-protocol.ts +26 -2
- package/src/worker/worker-edge-guard.ts +90 -0
- package/src/worker/worker-edge-log.ts +65 -0
- package/src/worker/worker-entry.ts +52 -0
- package/src/worker/worker-mcp-config.ts +23 -0
- package/src/worker/worker-metadata.ts +48 -0
- package/src/worker/worker-rate-limit-key.ts +30 -0
- package/src/worker/worker-runtime-config.ts +20 -0
- package/src/worker/worker-static-routes.ts +54 -0
- package/src/worker/worker-task-lifetime.ts +18 -0
- package/tsconfig.local.json +17 -1
- package/wrangler.jsonc +13 -0
- package/src/local/cli-approval.mjs +0 -117
- package/src/local/operation-state-lock.mjs +0 -92
- package/src/worker/mcp-session.ts +0 -72
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import relayContract from "./relay-contract.json" with { type: "json" };
|
|
2
|
+
|
|
3
|
+
const CONFIGURABLE_FOREGROUND_TOOLS = new Set([
|
|
4
|
+
"exec_command", "run_process", "run_local_command", "open_local_application",
|
|
5
|
+
"inspect_local_application", "operate_local_application", "browser_list_tabs",
|
|
6
|
+
"browser_manage_tabs", "browser_wait", "browser_get_source", "browser_inspect_page",
|
|
7
|
+
"browser_action", "browser_fill_form", "browser_screenshot", "browser_upload_files",
|
|
8
|
+
"computer_observe", "computer_act",
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
const REMOTE_DURABLE_PROCESS_TOOLS = new Set([
|
|
12
|
+
"exec_command", "run_process", "run_local_command",
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
const REMOTE_FOREGROUND_DEFAULT_SECONDS_BY_TOOL = new Map([
|
|
16
|
+
["computer_observe", 30],
|
|
17
|
+
["computer_act", 30],
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
export const REMOTE_FOREGROUND_TIMEOUT_SECONDS = Math.floor(
|
|
21
|
+
relayContract.maximumInteractiveExecutionTimeoutMs / 1000,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export const REMOTE_DURABLE_PROCESS_MAXIMUM_TIMEOUT_SECONDS = Math.floor(
|
|
25
|
+
relayContract.maximumDurableProcessExecutionTimeoutMs / 1000,
|
|
26
|
+
);
|
|
27
|
+
export const REMOTE_DURABLE_PROCESS_DEFAULT_TIMEOUT_SECONDS = REMOTE_DURABLE_PROCESS_MAXIMUM_TIMEOUT_SECONDS;
|
|
28
|
+
|
|
29
|
+
export function isRemoteDurableProcessTool(name) {
|
|
30
|
+
return REMOTE_DURABLE_PROCESS_TOOLS.has(name);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function remoteDurableProcessTimeoutSeconds(value) {
|
|
34
|
+
const parsed = value === undefined ? REMOTE_DURABLE_PROCESS_DEFAULT_TIMEOUT_SECONDS : value;
|
|
35
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > REMOTE_DURABLE_PROCESS_MAXIMUM_TIMEOUT_SECONDS) {
|
|
36
|
+
throw new RangeError(`durable process timeout must be an integer from 1 to ${REMOTE_DURABLE_PROCESS_MAXIMUM_TIMEOUT_SECONDS}`);
|
|
37
|
+
}
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function isConfigurableForegroundTool(name) {
|
|
42
|
+
return CONFIGURABLE_FOREGROUND_TOOLS.has(name);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function remoteForegroundDefaultSeconds(name) {
|
|
46
|
+
if (CONFIGURABLE_FOREGROUND_TOOLS.has(name)) {
|
|
47
|
+
return REMOTE_FOREGROUND_DEFAULT_SECONDS_BY_TOOL.get(name) ?? 20;
|
|
48
|
+
}
|
|
49
|
+
return Math.min(60, remoteForegroundMaximumSeconds(name));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function remoteForegroundMaximumSeconds(_name) {
|
|
53
|
+
return REMOTE_FOREGROUND_TIMEOUT_SECONDS;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function effectiveForegroundTimeoutSeconds({
|
|
57
|
+
tool,
|
|
58
|
+
value,
|
|
59
|
+
remote,
|
|
60
|
+
localDefault,
|
|
61
|
+
localMaximum,
|
|
62
|
+
}) {
|
|
63
|
+
const fallback = remote ? remoteForegroundDefaultSeconds(tool) : localDefault;
|
|
64
|
+
const maximum = remote ? remoteForegroundMaximumSeconds(tool) : localMaximum;
|
|
65
|
+
const parsed = value === undefined ? fallback : Number(value);
|
|
66
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > maximum) {
|
|
67
|
+
throw new RangeError(`foreground timeout must be an integer from 1 to ${maximum}`);
|
|
68
|
+
}
|
|
69
|
+
return parsed;
|
|
70
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const SECRET_VALUE = /\b(?:account_admin|account_password|daemon_secret|token_version|mcp_at|mcp_code)_[A-Za-z0-9_-]+\b/g;
|
|
2
|
+
const BEARER_VALUE = /\bBearer\s+[A-Za-z0-9._~+\/-]+=*\b/gi;
|
|
3
|
+
const EMAIL_VALUE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
|
|
4
|
+
const AWS_ACCESS_KEY = /\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g;
|
|
5
|
+
const GITHUB_TOKEN = /\bgh[pousr]_[A-Za-z0-9_]{30,}\b/g;
|
|
6
|
+
const GITLAB_TOKEN = /\bglpat-[A-Za-z0-9_-]{20,}\b/g;
|
|
7
|
+
const NPM_TOKEN = /\bnpm_[A-Za-z0-9]{30,}\b/g;
|
|
8
|
+
const SLACK_TOKEN = /\bxox[aboprs]-[A-Za-z0-9-]{10,}\b/g;
|
|
9
|
+
const GOOGLE_API_KEY = /\bAIza[A-Za-z0-9_-]{30,}\b/g;
|
|
10
|
+
const PAYMENT_API_KEY = /\b(?:sk|rk|pk)_live_[A-Za-z0-9]{16,}\b/g;
|
|
11
|
+
const JWT_VALUE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
|
|
12
|
+
const URL_CREDENTIALS = /https?:\/\/[^\s/@:"'<>]+:[^\s/@"'<>]+@[^\s/"'<>]+/gi;
|
|
13
|
+
const API_SECRET = /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/g;
|
|
14
|
+
const PRIVATE_KEY_HEADER = /-----BEGIN\s+(?:(?:OPENSSH|RSA|EC|DSA)\s+|ENCRYPTED\s+)?PRIVATE\s+KEY-----/g;
|
|
15
|
+
|
|
16
|
+
export function sanitizePortableLogText(value, options = {}) {
|
|
17
|
+
let raw;
|
|
18
|
+
try { raw = String(value ?? ""); } catch { raw = "<unprintable>"; }
|
|
19
|
+
let sanitized = raw
|
|
20
|
+
.replace(SECRET_VALUE, "<redacted-secret>")
|
|
21
|
+
.replace(BEARER_VALUE, "Bearer <redacted>")
|
|
22
|
+
.replace(AWS_ACCESS_KEY, "<redacted-cloud-key>")
|
|
23
|
+
.replace(GITHUB_TOKEN, "<redacted-access-token>")
|
|
24
|
+
.replace(GITLAB_TOKEN, "<redacted-access-token>")
|
|
25
|
+
.replace(NPM_TOKEN, "<redacted-access-token>")
|
|
26
|
+
.replace(SLACK_TOKEN, "<redacted-access-token>")
|
|
27
|
+
.replace(GOOGLE_API_KEY, "<redacted-cloud-key>")
|
|
28
|
+
.replace(PAYMENT_API_KEY, "<redacted-api-secret>")
|
|
29
|
+
.replace(JWT_VALUE, "<redacted-bearer-token>")
|
|
30
|
+
.replace(URL_CREDENTIALS, "<redacted-credential-url>")
|
|
31
|
+
.replace(API_SECRET, "<redacted-api-secret>")
|
|
32
|
+
.replace(PRIVATE_KEY_HEADER, "<redacted-private-key-header>")
|
|
33
|
+
.replace(EMAIL_VALUE, "<redacted-email>");
|
|
34
|
+
|
|
35
|
+
const homePaths = Array.isArray(options.homePaths) ? options.homePaths : [];
|
|
36
|
+
for (const home of [...new Set(homePaths.filter(item => typeof item === "string" && item.length > 1))]
|
|
37
|
+
.sort((left, right) => right.length - left.length)) {
|
|
38
|
+
sanitized = sanitized.split(home).join("<home>");
|
|
39
|
+
}
|
|
40
|
+
sanitized = sanitized
|
|
41
|
+
.replace(/\/(?:Users|home)\/[^/\s"'<>]+(?=\/|$)/g, "<home>")
|
|
42
|
+
.replace(/\b[A-Za-z]:\\Users\\[^\\\s"'<>]+(?=\\|$)/g, "<home>")
|
|
43
|
+
.replace(/[\u200B-\u200F\u202A-\u202E\u2066-\u2069\uFEFF]/g, "")
|
|
44
|
+
.replace(/[\r\n\t]/g, match => match === "\t" ? "\\t" : "\\n")
|
|
45
|
+
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, "?");
|
|
46
|
+
|
|
47
|
+
const numericLimit = Number(options.maxChars);
|
|
48
|
+
if (!Number.isFinite(numericLimit) || numericLimit <= 0) return "";
|
|
49
|
+
const limit = Math.max(16, numericLimit);
|
|
50
|
+
return sanitized.length > limit ? `${sanitized.slice(0, limit - 1)}…` : sanitized;
|
|
51
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const MCP_PROTOCOL_VERSION: "2026-07-28";
|
|
2
|
+
export const MCP_PROTOCOL_VERSIONS: readonly string[];
|
|
3
|
+
export const MCP_HEADER_MISMATCH: -32020;
|
|
4
|
+
export const MCP_UNSUPPORTED_PROTOCOL_VERSION: -32022;
|
|
5
|
+
export const MCP_REMOVED_PROTOCOL_MESSAGE: "MCP session protocol was removed; upgrade the client and use request-scoped metadata/server/discover";
|
|
6
|
+
export class McpProtocolError extends Error {
|
|
7
|
+
code: number;
|
|
8
|
+
data?: unknown;
|
|
9
|
+
constructor(code: number, message: string, data?: unknown);
|
|
10
|
+
}
|
|
11
|
+
export function asMcpObject(value: unknown): Record<string, unknown>;
|
|
12
|
+
export function requestProtocolVersion(value: unknown): string;
|
|
13
|
+
export function assertBoundedMcpJsonStructure(value: unknown, label?: string): void;
|
|
14
|
+
export function validateRequestMetadata(value: unknown, supportedVersions?: readonly string[]): {
|
|
15
|
+
version: string;
|
|
16
|
+
clientCapabilities: Record<string, unknown>;
|
|
17
|
+
clientInfo: Record<string, unknown> | null;
|
|
18
|
+
progressToken: unknown;
|
|
19
|
+
logLevel: unknown;
|
|
20
|
+
};
|
|
21
|
+
export function serverImplementation(input: { name: unknown; version: unknown; title?: unknown; description?: unknown }): Record<string, unknown>;
|
|
22
|
+
export function completeResult(fields?: Record<string, unknown>, serverInfo?: Record<string, unknown>): Record<string, unknown>;
|
|
23
|
+
export function cacheableResult(fields: Record<string, unknown>, options: { ttlMs: number; cacheScope: "public" | "private"; serverInfo?: Record<string, unknown> }): Record<string, unknown>;
|
|
24
|
+
export function discoverResult(input: { supportedVersions: readonly string[]; capabilities: Record<string, unknown>; instructions?: string; ttlMs?: number; serverInfo?: Record<string, unknown> }): Record<string, unknown>;
|
|
25
|
+
export function validateSubscriptionRequest(value: unknown): void;
|
|
26
|
+
export function emptySubscriptionAcknowledgement(requestId: string | number): Record<string, unknown>;
|
|
27
|
+
export function subscriptionCompleteResult(requestId: string | number, serverInfo?: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
export const MCP_PROTOCOL_VERSION = "2026-07-28";
|
|
2
|
+
export const MCP_PROTOCOL_VERSIONS = Object.freeze([MCP_PROTOCOL_VERSION]);
|
|
3
|
+
export const MCP_HEADER_MISMATCH = -32020;
|
|
4
|
+
export const MCP_UNSUPPORTED_PROTOCOL_VERSION = -32022;
|
|
5
|
+
export const MCP_REMOVED_PROTOCOL_MESSAGE = "MCP session protocol was removed; upgrade the client and use request-scoped metadata/server/discover";
|
|
6
|
+
const MCP_RESULT_COMPLETE = "complete";
|
|
7
|
+
|
|
8
|
+
const PROTOCOL_VERSION_KEY = "io.modelcontextprotocol/protocolVersion";
|
|
9
|
+
const CLIENT_INFO_KEY = "io.modelcontextprotocol/clientInfo";
|
|
10
|
+
const CLIENT_CAPABILITIES_KEY = "io.modelcontextprotocol/clientCapabilities";
|
|
11
|
+
const SERVER_INFO_KEY = "io.modelcontextprotocol/serverInfo";
|
|
12
|
+
const SUBSCRIPTION_ID_KEY = "io.modelcontextprotocol/subscriptionId";
|
|
13
|
+
const LOG_LEVELS = new Set(["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"]);
|
|
14
|
+
const META_KEY = /^(?:(?:[A-Za-z](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)*[A-Za-z](?:[A-Za-z0-9-]*[A-Za-z0-9])?\/)?(?:[A-Za-z0-9](?:[A-Za-z0-9_.-]*[A-Za-z0-9])?)?$/;
|
|
15
|
+
const MAX_MCP_JSON_DEPTH = 32;
|
|
16
|
+
const MAX_MCP_JSON_NODES = 4096;
|
|
17
|
+
const MAX_MCP_JSON_KEY_LENGTH = 256;
|
|
18
|
+
const MAX_RESOURCE_SUBSCRIPTIONS = 128;
|
|
19
|
+
const MAX_RESOURCE_SUBSCRIPTION_URI_LENGTH = 4096;
|
|
20
|
+
|
|
21
|
+
export class McpProtocolError extends Error {
|
|
22
|
+
constructor(code, message, data) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "McpProtocolError";
|
|
25
|
+
this.code = code;
|
|
26
|
+
this.data = data;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function asMcpObject(value) {
|
|
31
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function requestMeta(value) {
|
|
35
|
+
return asMcpObject(asMcpObject(value).params)._meta;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function requestProtocolVersion(value) {
|
|
39
|
+
const version = asMcpObject(requestMeta(value))[PROTOCOL_VERSION_KEY];
|
|
40
|
+
return typeof version === "string" ? version : "";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function validateRequestMetadata(value, supportedVersions = MCP_PROTOCOL_VERSIONS) {
|
|
44
|
+
const params = asMcpObject(asMcpObject(value).params);
|
|
45
|
+
const meta = asMcpObject(params._meta);
|
|
46
|
+
assertBoundedMcpJsonStructure(meta, "request metadata");
|
|
47
|
+
const version = meta[PROTOCOL_VERSION_KEY];
|
|
48
|
+
if (typeof version !== "string" || !version) {
|
|
49
|
+
throw new McpProtocolError(-32602, `Missing required request metadata: ${PROTOCOL_VERSION_KEY}`);
|
|
50
|
+
}
|
|
51
|
+
if (!supportedVersions.includes(version)) {
|
|
52
|
+
throw new McpProtocolError(MCP_UNSUPPORTED_PROTOCOL_VERSION, "Unsupported protocol version", {
|
|
53
|
+
supported: [...supportedVersions],
|
|
54
|
+
requested: boundedProtocolVersion(version),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
validateMetaKeys(meta);
|
|
58
|
+
const clientCapabilities = meta[CLIENT_CAPABILITIES_KEY];
|
|
59
|
+
if (!isPlainObject(clientCapabilities)) {
|
|
60
|
+
throw new McpProtocolError(-32602, `Missing required request metadata: ${CLIENT_CAPABILITIES_KEY}`);
|
|
61
|
+
}
|
|
62
|
+
validateClientCapabilities(clientCapabilities);
|
|
63
|
+
const clientInfo = meta[CLIENT_INFO_KEY];
|
|
64
|
+
if (clientInfo !== undefined && !isImplementation(clientInfo)) {
|
|
65
|
+
throw new McpProtocolError(-32602, `Invalid request metadata: ${CLIENT_INFO_KEY}`);
|
|
66
|
+
}
|
|
67
|
+
const progressToken = meta.progressToken;
|
|
68
|
+
if (progressToken !== undefined && !isProgressToken(progressToken)) {
|
|
69
|
+
throw new McpProtocolError(-32602, "Invalid request metadata: progressToken");
|
|
70
|
+
}
|
|
71
|
+
const logLevel = meta["io.modelcontextprotocol/logLevel"];
|
|
72
|
+
if (logLevel !== undefined && !LOG_LEVELS.has(logLevel)) {
|
|
73
|
+
throw new McpProtocolError(-32602, "Invalid request metadata: io.modelcontextprotocol/logLevel");
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
version,
|
|
77
|
+
clientCapabilities,
|
|
78
|
+
clientInfo: clientInfo ?? null,
|
|
79
|
+
progressToken,
|
|
80
|
+
logLevel,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function serverImplementation({ name, version, title, description }) {
|
|
85
|
+
const implementation = { name: String(name), version: String(version) };
|
|
86
|
+
if (title) implementation.title = String(title);
|
|
87
|
+
if (description) implementation.description = String(description);
|
|
88
|
+
return implementation;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function completeResult(fields = {}, serverInfo) {
|
|
92
|
+
return result(MCP_RESULT_COMPLETE, fields, serverInfo);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function cacheableResult(fields, { ttlMs, cacheScope, serverInfo }) {
|
|
96
|
+
const normalizedTtl = Number(ttlMs);
|
|
97
|
+
if (!Number.isFinite(normalizedTtl) || normalizedTtl < 0) throw new Error("ttlMs must be a non-negative number");
|
|
98
|
+
if (cacheScope !== "public" && cacheScope !== "private") throw new Error("cacheScope must be public or private");
|
|
99
|
+
return completeResult({ ...fields, ttlMs: normalizedTtl, cacheScope }, serverInfo);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function discoverResult({ supportedVersions, capabilities, instructions, ttlMs = 0, serverInfo }) {
|
|
103
|
+
const fields = {
|
|
104
|
+
supportedVersions: [...supportedVersions],
|
|
105
|
+
capabilities: structuredClone(capabilities),
|
|
106
|
+
};
|
|
107
|
+
if (instructions) fields.instructions = String(instructions);
|
|
108
|
+
return cacheableResult(fields, { ttlMs, cacheScope: "public", serverInfo });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function validateSubscriptionRequest(value) {
|
|
112
|
+
const notifications = asMcpObject(asMcpObject(value).params).notifications;
|
|
113
|
+
if (!isPlainObject(notifications)) {
|
|
114
|
+
throw new McpProtocolError(-32602, "subscriptions/listen requires a notifications object");
|
|
115
|
+
}
|
|
116
|
+
assertBoundedMcpJsonStructure(notifications, "subscription filter");
|
|
117
|
+
for (const key of ["toolsListChanged", "promptsListChanged", "resourcesListChanged"]) {
|
|
118
|
+
if (notifications[key] !== undefined && typeof notifications[key] !== "boolean") {
|
|
119
|
+
throw new McpProtocolError(-32602, `Invalid subscriptions/listen notification filter: ${key}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const resources = notifications.resourceSubscriptions;
|
|
123
|
+
if (resources === undefined) return;
|
|
124
|
+
if (!Array.isArray(resources) || resources.length > MAX_RESOURCE_SUBSCRIPTIONS
|
|
125
|
+
|| resources.some((uri) => typeof uri !== "string" || !uri || uri.length > MAX_RESOURCE_SUBSCRIPTION_URI_LENGTH)) {
|
|
126
|
+
throw new McpProtocolError(-32602, "Invalid subscriptions/listen notification filter: resourceSubscriptions");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function emptySubscriptionAcknowledgement(requestId) {
|
|
131
|
+
return {
|
|
132
|
+
jsonrpc: "2.0",
|
|
133
|
+
method: "notifications/subscriptions/acknowledged",
|
|
134
|
+
params: {
|
|
135
|
+
notifications: {},
|
|
136
|
+
_meta: { [SUBSCRIPTION_ID_KEY]: requestId },
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function subscriptionCompleteResult(requestId, serverInfo) {
|
|
142
|
+
const output = completeResult({}, serverInfo);
|
|
143
|
+
output._meta = { ...asMcpObject(output._meta), [SUBSCRIPTION_ID_KEY]: requestId };
|
|
144
|
+
return output;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function serverInfoMeta(serverInfo) {
|
|
148
|
+
return serverInfo ? { [SERVER_INFO_KEY]: structuredClone(serverInfo) } : undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function result(resultType, fields, serverInfo) {
|
|
152
|
+
const output = { ...structuredClone(fields), resultType };
|
|
153
|
+
const meta = serverInfoMeta(serverInfo);
|
|
154
|
+
if (meta) output._meta = { ...asMcpObject(output._meta), ...meta };
|
|
155
|
+
return output;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function assertBoundedMcpJsonStructure(value, label = "MCP value") {
|
|
159
|
+
const stack = [{ value, depth: 0 }];
|
|
160
|
+
let nodes = 0;
|
|
161
|
+
while (stack.length > 0) {
|
|
162
|
+
const current = stack.pop();
|
|
163
|
+
nodes += 1;
|
|
164
|
+
if (nodes > MAX_MCP_JSON_NODES || current.depth > MAX_MCP_JSON_DEPTH) {
|
|
165
|
+
throw new McpProtocolError(-32602, `${label} exceeds bounded structural limits`);
|
|
166
|
+
}
|
|
167
|
+
if (Array.isArray(current.value)) {
|
|
168
|
+
if (current.value.length > MAX_MCP_JSON_NODES - nodes - stack.length) {
|
|
169
|
+
throw new McpProtocolError(-32602, `${label} exceeds bounded structural limits`);
|
|
170
|
+
}
|
|
171
|
+
for (let index = 0; index < current.value.length; index += 1) {
|
|
172
|
+
stack.push({ value: current.value[index], depth: current.depth + 1 });
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (!current.value || typeof current.value !== "object") continue;
|
|
177
|
+
if (!isPlainObject(current.value)) throw new McpProtocolError(-32602, `${label} contains a non-JSON object`);
|
|
178
|
+
for (const key in current.value) {
|
|
179
|
+
if (!Object.hasOwn(current.value, key)) continue;
|
|
180
|
+
if (key.length > MAX_MCP_JSON_KEY_LENGTH || stack.length + nodes >= MAX_MCP_JSON_NODES) {
|
|
181
|
+
throw new McpProtocolError(-32602, `${label} exceeds bounded structural limits`);
|
|
182
|
+
}
|
|
183
|
+
stack.push({ value: current.value[key], depth: current.depth + 1 });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function validateMetaKeys(meta) {
|
|
189
|
+
for (const key in meta) {
|
|
190
|
+
if (!Object.hasOwn(meta, key)) continue;
|
|
191
|
+
if (key.length > MAX_MCP_JSON_KEY_LENGTH || !META_KEY.test(key)) {
|
|
192
|
+
throw new McpProtocolError(-32602, "Invalid request metadata key");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function validateClientCapabilities(value) {
|
|
198
|
+
validateCapabilityObject(value, "roots");
|
|
199
|
+
validateCapabilityMap(value, "experimental");
|
|
200
|
+
validateCapabilityFields(value, "sampling", ["context", "tools"]);
|
|
201
|
+
validateCapabilityFields(value, "elicitation", ["form", "url"]);
|
|
202
|
+
const extensions = value.extensions;
|
|
203
|
+
if (extensions === undefined) return;
|
|
204
|
+
if (!isPlainObject(extensions)) throw new McpProtocolError(-32602, "Invalid client capability: extensions");
|
|
205
|
+
for (const key in extensions) {
|
|
206
|
+
if (!Object.hasOwn(extensions, key)) continue;
|
|
207
|
+
const settings = extensions[key];
|
|
208
|
+
if (key.length > MAX_MCP_JSON_KEY_LENGTH || !key.includes("/") || !META_KEY.test(key) || !isPlainObject(settings)) {
|
|
209
|
+
throw new McpProtocolError(-32602, "Invalid client extension capability");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function validateCapabilityObject(value, key) {
|
|
215
|
+
if (value[key] !== undefined && !isPlainObject(value[key])) {
|
|
216
|
+
throw new McpProtocolError(-32602, `Invalid client capability: ${key}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function validateCapabilityMap(value, key) {
|
|
221
|
+
validateCapabilityObject(value, key);
|
|
222
|
+
if (value[key] === undefined) return;
|
|
223
|
+
for (const name in value[key]) {
|
|
224
|
+
if (!Object.hasOwn(value[key], name)) continue;
|
|
225
|
+
if (name.length > MAX_MCP_JSON_KEY_LENGTH || !isPlainObject(value[key][name])) {
|
|
226
|
+
throw new McpProtocolError(-32602, `Invalid client capability: ${key}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function validateCapabilityFields(value, key, fields) {
|
|
232
|
+
validateCapabilityObject(value, key);
|
|
233
|
+
if (value[key] === undefined) return;
|
|
234
|
+
for (const field of fields) {
|
|
235
|
+
if (value[key][field] !== undefined && !isPlainObject(value[key][field])) {
|
|
236
|
+
throw new McpProtocolError(-32602, `Invalid client capability: ${key}.${field}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function boundedProtocolVersion(value) {
|
|
242
|
+
return value.length <= 128 ? value : "<invalid-length>";
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function isProgressToken(value) {
|
|
246
|
+
return typeof value === "string" || (typeof value === "number" && Number.isFinite(value));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function isImplementation(value) {
|
|
250
|
+
if (!isPlainObject(value) || typeof value.name !== "string" || typeof value.version !== "string") return false;
|
|
251
|
+
for (const field of ["title", "description"]) {
|
|
252
|
+
if (value[field] !== undefined && typeof value[field] !== "string") return false;
|
|
253
|
+
}
|
|
254
|
+
if (value.websiteUrl !== undefined && !isAbsoluteUri(value.websiteUrl)) return false;
|
|
255
|
+
if (value.icons !== undefined && (!Array.isArray(value.icons) || !value.icons.every(isIcon))) return false;
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function isIcon(value) {
|
|
260
|
+
if (!isPlainObject(value) || !isAbsoluteUri(value.src)) return false;
|
|
261
|
+
if (value.mimeType !== undefined && typeof value.mimeType !== "string") return false;
|
|
262
|
+
if (value.sizes !== undefined && (!Array.isArray(value.sizes) || !value.sizes.every((size) => typeof size === "string"))) return false;
|
|
263
|
+
return value.theme === undefined || value.theme === "light" || value.theme === "dark";
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function isAbsoluteUri(value) {
|
|
267
|
+
if (typeof value !== "string" || !value) return false;
|
|
268
|
+
try { return Boolean(new URL(value).protocol); } catch { return false; }
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function isPlainObject(value) {
|
|
272
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
273
|
+
const prototype = Object.getPrototypeOf(value);
|
|
274
|
+
return prototype === Object.prototype || prototype === null;
|
|
275
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
export function projectOverviewDetail(args = {}) {
|
|
4
|
+
return args?.detail === "summary" ? "summary" : "full";
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function projectProjectOverview(value, detail = "full") {
|
|
8
|
+
if (detail !== "summary" || !isRecord(value)) return value;
|
|
9
|
+
const authorization = record(value.authorization);
|
|
10
|
+
const summary = /** @type {Record<string, unknown>} */ ({
|
|
11
|
+
detail: "summary",
|
|
12
|
+
workspace: value.workspace ?? null,
|
|
13
|
+
workspaceName: value.workspaceName ?? null,
|
|
14
|
+
gitRoot: value.gitRoot ?? "",
|
|
15
|
+
policy: value.policy ?? null,
|
|
16
|
+
effectiveToolCount: numberOrLength(authorization.effective_tool_count, value.tools),
|
|
17
|
+
daemonPolicy: value.daemonPolicy ?? null,
|
|
18
|
+
daemonToolCount: numberOr(value.daemonToolCount, arrayLength(value.daemonTools)),
|
|
19
|
+
...(value.daemonToolsHiddenByAuthority === true ? { daemonToolsHiddenByAuthority: true } : {}),
|
|
20
|
+
capabilityRouting: compactCapabilityRouting(value.capabilityRouting),
|
|
21
|
+
topLevel: compactTopLevel(value.topLevel),
|
|
22
|
+
topLevelTotal: numberOr(value.topLevelTotal, 0),
|
|
23
|
+
topLevelTruncated: value.topLevelTruncated === true,
|
|
24
|
+
});
|
|
25
|
+
if (typeof value.policyScope === "string") summary.policyScope = value.policyScope;
|
|
26
|
+
if (typeof value.toolsScope === "string") summary.toolsScope = value.toolsScope;
|
|
27
|
+
if (Object.keys(authorization).length) summary.authorization = compactAuthorization(authorization);
|
|
28
|
+
return summary;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function compactAuthorization(value) {
|
|
32
|
+
const account = record(value.account);
|
|
33
|
+
const execution = record(value.execution_model);
|
|
34
|
+
return {
|
|
35
|
+
account: Object.keys(account).length ? { role: account.role ?? null, version: account.version ?? null } : null,
|
|
36
|
+
effective_policy: value.effective_policy ?? null,
|
|
37
|
+
effective_tool_count: numberOr(value.effective_tool_count, 0),
|
|
38
|
+
account_role_is_owner: value.account_role_is_owner === true,
|
|
39
|
+
effective_profile_is_full: value.effective_profile_is_full === true,
|
|
40
|
+
execution_model: Object.keys(execution).length ? {
|
|
41
|
+
within_effective_authority: execution.within_effective_authority ?? null,
|
|
42
|
+
owner_ambient_authority: execution.owner_ambient_authority ?? null,
|
|
43
|
+
} : null,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function compactCapabilityRouting(value) {
|
|
48
|
+
const source = record(value);
|
|
49
|
+
if (source.activity_hidden_by_authority === true) return { activity_hidden_by_authority: true };
|
|
50
|
+
const last = record(source.last_task_resolution);
|
|
51
|
+
return {
|
|
52
|
+
bootstrap_observed: source.bootstrap_observed === true,
|
|
53
|
+
bootstrap_count: numberOr(source.bootstrap_count, 0),
|
|
54
|
+
task_resolution_observed: source.task_resolution_observed === true,
|
|
55
|
+
task_resolution_count: numberOr(source.task_resolution_count, 0),
|
|
56
|
+
last_task_resolution: Object.keys(last).length ? {
|
|
57
|
+
observed_at: last.observed_at ?? null,
|
|
58
|
+
selected_skill: last.selected_skill ?? null,
|
|
59
|
+
matched_skills: numberOr(last.matched_skills, 0),
|
|
60
|
+
matched_commands: numberOr(last.matched_commands, 0),
|
|
61
|
+
matched_applications: numberOr(last.matched_applications, 0),
|
|
62
|
+
recommended_tool_count: arrayLength(last.recommended_tools),
|
|
63
|
+
primary_route: last.primary_route ?? null,
|
|
64
|
+
routing_ambiguity: last.routing_ambiguity ?? "none",
|
|
65
|
+
routing_score_gap: numberOr(last.routing_score_gap, 0),
|
|
66
|
+
} : null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function compactTopLevel(value) {
|
|
71
|
+
if (!Array.isArray(value)) return [];
|
|
72
|
+
return value.map((item) => {
|
|
73
|
+
const entry = record(item);
|
|
74
|
+
return { name: entry.name ?? "", type: entry.type ?? "other" };
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function arrayLength(value) {
|
|
79
|
+
return Array.isArray(value) ? value.length : 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function numberOr(value, fallback) {
|
|
83
|
+
return Number.isFinite(Number(value)) ? Number(value) : fallback;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function numberOrLength(value, array) {
|
|
87
|
+
return Number.isFinite(Number(value)) ? Number(value) : arrayLength(array);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isRecord(value) {
|
|
91
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function record(value) {
|
|
95
|
+
return isRecord(value) ? value : {};
|
|
96
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reconnectGraceMs": 120000,
|
|
3
|
+
"newCallReconnectGraceMs": 15000,
|
|
4
|
+
"transportPingIntervalMs": 5000,
|
|
5
|
+
"transportPongTimeoutMs": 10000,
|
|
6
|
+
"daemonApplicationHeartbeatIntervalMs": 25000,
|
|
7
|
+
"daemonApplicationHeartbeatTimeoutMs": 75000,
|
|
8
|
+
"httpFallbackPollIntervalMs": 1000,
|
|
9
|
+
"httpFallbackMinimumRequestIntervalMs": 750,
|
|
10
|
+
"httpFallbackActivationDelayMs": 1500,
|
|
11
|
+
"httpFallbackRequestTimeoutMs": 7000,
|
|
12
|
+
"httpFallbackLivenessTimeoutMs": 12000,
|
|
13
|
+
"httpFallbackMaximumQueuedMessages": 64,
|
|
14
|
+
"httpFallbackMaximumQueuedBytes": 16777216,
|
|
15
|
+
"httpFallbackMaximumMessageBytes": 8388608,
|
|
16
|
+
"httpFallbackMaximumEnvelopeBytes": 8454144,
|
|
17
|
+
"streamHeartbeatMs": 5000,
|
|
18
|
+
"maximumExecutionTimeoutMs": 45000,
|
|
19
|
+
"defaultRemoteToolExecutionTimeoutMs": 20000,
|
|
20
|
+
"maximumInteractiveExecutionTimeoutMs": 45000,
|
|
21
|
+
"processSessionStartExecutionTimeoutMs": 10000,
|
|
22
|
+
"durableProcessAcceptanceTimeoutMs": 10000,
|
|
23
|
+
"maximumDurableProcessExecutionTimeoutMs": 600000,
|
|
24
|
+
"maximumManagedJobResourceAdmissionWaitMs": 1800000,
|
|
25
|
+
"maximumProcessReadWaitMs": 5000,
|
|
26
|
+
"workerSettlementOverheadMs": 5000,
|
|
27
|
+
"maximumRelayToolTimeoutMs": 50000
|
|
28
|
+
}
|
|
@@ -2,5 +2,6 @@ export const MCP_TEXT_PROJECTION_KEY: "$mcpText";
|
|
|
2
2
|
export function mirroredResultText(value: unknown): string;
|
|
3
3
|
export function projectMcpResult(value: unknown): {
|
|
4
4
|
text: string;
|
|
5
|
-
|
|
5
|
+
hasStructuredContent: boolean;
|
|
6
|
+
structuredContent: unknown;
|
|
6
7
|
};
|
|
@@ -35,14 +35,25 @@ export function projectMcpResult(value) {
|
|
|
35
35
|
const structuredContent = { ...object };
|
|
36
36
|
const text = String(structuredContent[MCP_TEXT_PROJECTION_KEY]).slice(0, 4096);
|
|
37
37
|
delete structuredContent[MCP_TEXT_PROJECTION_KEY];
|
|
38
|
-
return { text, structuredContent };
|
|
38
|
+
return { text, hasStructuredContent: true, structuredContent };
|
|
39
39
|
}
|
|
40
40
|
return {
|
|
41
41
|
text: mirroredResultText(value),
|
|
42
|
-
|
|
42
|
+
hasStructuredContent: isJsonValue(value),
|
|
43
|
+
structuredContent: value,
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
/** @param {unknown} value */
|
|
48
|
+
function isJsonValue(value) {
|
|
49
|
+
return value === null
|
|
50
|
+
|| typeof value === "string"
|
|
51
|
+
|| typeof value === "boolean"
|
|
52
|
+
|| (typeof value === "number" && Number.isFinite(value))
|
|
53
|
+
|| Array.isArray(value)
|
|
54
|
+
|| (value && typeof value === "object");
|
|
55
|
+
}
|
|
56
|
+
|
|
46
57
|
/** @param {unknown} value */
|
|
47
58
|
function asObject(value) {
|
|
48
59
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|