@wardby/cli 0.6.0 → 0.8.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/.env.example +5 -5
- package/README.md +6 -1
- package/deploy/local/docker-compose.quickstart-coding.yml +19 -0
- package/dist/claude-coding-worker/driver.d.ts +33 -3
- package/dist/claude-coding-worker/driver.js +151 -21
- package/dist/claude-coding-worker/main.js +38 -6
- package/dist/claude-coding-worker/sdk.js +29 -2
- package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
- package/dist/claude-coding-worker/tool-socket.js +111 -0
- package/dist/claude-coding-worker/transcript.d.ts +18 -0
- package/dist/claude-coding-worker/transcript.js +77 -0
- package/dist/claude-plugin/command.d.ts +61 -0
- package/dist/claude-plugin/command.js +376 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +3 -1
- package/dist/cli.js +71 -13
- package/dist/coding/code-host.d.ts +16 -0
- package/dist/coding/code-host.js +60 -0
- package/dist/coding/continuation-wording.d.ts +35 -0
- package/dist/coding/continuation-wording.js +73 -0
- package/dist/coding/linked-issue-note.d.ts +23 -0
- package/dist/coding/linked-issue-note.js +47 -0
- package/dist/coding/mcp-token.d.ts +12 -0
- package/dist/coding/mcp-token.js +26 -0
- package/dist/coding/merge-wording.d.ts +28 -0
- package/dist/coding/merge-wording.js +78 -0
- package/dist/coding/pr-description-note.d.ts +9 -0
- package/dist/coding/pr-description-note.js +32 -0
- package/dist/coding/profile.d.ts +46 -126
- package/dist/coding/profile.js +45 -4
- package/dist/coding/protected-path-wording.d.ts +8 -0
- package/dist/coding/protected-path-wording.js +1 -1
- package/dist/coding/protocol.d.ts +264 -346
- package/dist/coding/protocol.js +237 -12
- package/dist/coding/redact.d.ts +3 -0
- package/dist/coding/redact.js +17 -0
- package/dist/coding/registry/allowlist.d.ts +12 -0
- package/dist/coding/registry/allowlist.js +14 -1
- package/dist/coding/registry/audit-mode.d.ts +153 -0
- package/dist/coding/registry/audit-mode.js +304 -0
- package/dist/coding/registry/lockfile-shared.d.ts +36 -0
- package/dist/coding/registry/lockfile-shared.js +128 -0
- package/dist/coding/registry/lockfiles.js +1 -1
- package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
- package/dist/coding/registry/npm-lockfile-formats.js +41 -0
- package/dist/coding/registry/npm-lockfile.d.ts +8 -4
- package/dist/coding/registry/npm-lockfile.js +4 -6
- package/dist/coding/registry/npm.js +78 -8
- package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
- package/dist/coding/registry/pnpm-lockfile.js +189 -0
- package/dist/coding/registry/pypi-plan.d.ts +50 -0
- package/dist/coding/registry/pypi-plan.js +406 -0
- package/dist/coding/registry/pypi-requirements.d.ts +58 -0
- package/dist/coding/registry/pypi-requirements.js +155 -0
- package/dist/coding/registry/pypi.d.ts +3 -27
- package/dist/coding/registry/pypi.js +40 -154
- package/dist/coding/registry/refusal-hints.d.ts +20 -0
- package/dist/coding/registry/refusal-hints.js +61 -0
- package/dist/coding/registry/refusal-wording.d.ts +11 -0
- package/dist/coding/registry/refusal-wording.js +56 -0
- package/dist/coding/registry/report.d.ts +70 -8
- package/dist/coding/registry/report.js +112 -5
- package/dist/coding/registry/types.d.ts +58 -8
- package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
- package/dist/coding/registry/yarn-lockfile.js +367 -0
- package/dist/coding/services/catalog.d.ts +37 -351
- package/dist/coding/transcript/claude-code.d.ts +13 -0
- package/dist/coding/transcript/claude-code.js +273 -0
- package/dist/coding/transcript/download-protocol.d.ts +30 -0
- package/dist/coding/transcript/download-protocol.js +18 -0
- package/dist/coding/transcript/format.d.ts +20 -0
- package/dist/coding/transcript/format.js +32 -0
- package/dist/coding/transcript/recorder.d.ts +52 -0
- package/dist/coding/transcript/recorder.js +225 -0
- package/dist/coding/transcript/resume/checkout.d.ts +31 -0
- package/dist/coding/transcript/resume/checkout.js +203 -0
- package/dist/coding/transcript/resume/command.d.ts +17 -0
- package/dist/coding/transcript/resume/command.js +176 -0
- package/dist/coding/transcript/resume/download.d.ts +20 -0
- package/dist/coding/transcript/resume/download.js +153 -0
- package/dist/coding/transcript/resume/launch.d.ts +38 -0
- package/dist/coding/transcript/resume/launch.js +128 -0
- package/dist/coding/transcript/resume/session-file.d.ts +13 -0
- package/dist/coding/transcript/resume/session-file.js +79 -0
- package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
- package/dist/coding/transcript/resume/stand-in.js +49 -0
- package/dist/coding-worker/artifact.d.ts +8 -3
- package/dist/coding-worker/artifact.js +3 -1
- package/dist/coding-worker/debug-trace.d.ts +9 -6
- package/dist/coding-worker/debug-trace.js +16 -19
- package/dist/coding-worker/dependency-cache.d.mts +229 -0
- package/dist/coding-worker/dependency-cache.mjs +2123 -0
- package/dist/coding-worker/driver.d.ts +4 -3
- package/dist/coding-worker/driver.js +124 -39
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -0
- package/dist/coding-worker/main.js +5 -1
- package/dist/coding-worker/mcp-config.d.ts +27 -0
- package/dist/coding-worker/mcp-config.js +32 -0
- package/dist/coding-worker/sdk.d.ts +36 -0
- package/dist/coding-worker/sdk.js +28 -1
- package/dist/coding-worker/task-note.d.ts +11 -0
- package/dist/coding-worker/task-note.js +13 -0
- package/dist/coding-worker/types.d.ts +15 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/mcp-call-limit.d.ts +8 -0
- package/dist/config/mcp-call-limit.js +18 -0
- package/dist/config/mcp-servers.d.ts +8 -0
- package/dist/config/mcp-servers.js +12 -0
- package/dist/config/providers.d.ts +12 -3
- package/dist/config/providers.js +55 -5
- package/dist/config/test-simulators.d.ts +92 -0
- package/dist/config/test-simulators.js +333 -0
- package/dist/config/tool-timeout.d.ts +1 -0
- package/dist/config/tool-timeout.js +18 -0
- package/dist/core/async-context.d.ts +2 -0
- package/dist/core/async-context.js +12 -0
- package/dist/core/budget-events.d.ts +108 -0
- package/dist/core/budget-events.js +346 -0
- package/dist/core/budget-groups.d.ts +50 -1
- package/dist/core/budget-groups.js +236 -27
- package/dist/core/budget-stopped-head.d.ts +46 -0
- package/dist/core/budget-stopped-head.js +81 -0
- package/dist/core/budget-topup.d.ts +51 -0
- package/dist/core/budget-topup.js +156 -0
- package/dist/core/budget-wording.d.ts +16 -2
- package/dist/core/budget-wording.js +40 -2
- package/dist/core/coding-mcp.d.ts +36 -0
- package/dist/core/coding-mcp.js +253 -0
- package/dist/core/coding-queue.d.ts +2 -1
- package/dist/core/coding-queue.js +7 -0
- package/dist/core/coding-repository.d.ts +46 -0
- package/dist/core/coding-repository.js +92 -0
- package/dist/core/cron.d.ts +19 -1
- package/dist/core/cron.js +17 -0
- package/dist/core/datastores.js +1 -1
- package/dist/core/deferred-coding.d.ts +14 -0
- package/dist/core/deferred-coding.js +62 -0
- package/dist/core/delegation-child.d.ts +25 -0
- package/dist/core/delegation-child.js +37 -0
- package/dist/core/delegation-slots.d.ts +27 -0
- package/dist/core/delegation-slots.js +44 -0
- package/dist/core/dispatch.d.ts +48 -2
- package/dist/core/dispatch.js +166 -66
- package/dist/core/engine-native.js +1 -1
- package/dist/core/error-code.d.ts +38 -0
- package/dist/core/error-code.js +169 -0
- package/dist/core/grants.d.ts +46 -8
- package/dist/core/grants.js +99 -8
- package/dist/core/host-events.d.ts +18 -2
- package/dist/core/host-events.js +291 -27
- package/dist/core/host-status.d.ts +85 -3
- package/dist/core/host-status.js +300 -22
- package/dist/core/issue-bridge.d.ts +50 -6
- package/dist/core/issue-bridge.js +124 -33
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +4 -10
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +58 -29
- package/dist/core/logger.d.ts +5 -0
- package/dist/core/logger.js +14 -1
- package/dist/core/lost-run-children.d.ts +6 -0
- package/dist/core/lost-run-children.js +32 -0
- package/dist/core/mark-ready.d.ts +34 -0
- package/dist/core/mark-ready.js +152 -0
- package/dist/core/markdown-code.d.ts +8 -0
- package/dist/core/markdown-code.js +107 -0
- package/dist/core/mcp-client/client.d.ts +47 -0
- package/dist/core/mcp-client/client.js +141 -0
- package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
- package/dist/core/mcp-client/jsonrpc.js +54 -0
- package/dist/core/mcp-client/results.d.ts +13 -0
- package/dist/core/mcp-client/results.js +42 -0
- package/dist/core/mcp-servers.d.ts +90 -0
- package/dist/core/mcp-servers.js +230 -0
- package/dist/core/mcp-tools.d.ts +108 -0
- package/dist/core/mcp-tools.js +287 -0
- package/dist/core/memory-tools.js +7 -0
- package/dist/core/merge-order-check.d.ts +2 -1
- package/dist/core/merge-order-check.js +44 -18
- package/dist/core/notification-dispatcher.js +2 -1
- package/dist/core/notification-templates.d.ts +1 -7
- package/dist/core/notification-templates.js +36 -2
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +4 -3
- package/dist/core/reconciler.js +8 -1
- package/dist/core/related-pull-requests.d.ts +11 -3
- package/dist/core/related-pull-requests.js +49 -20
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/review-fix.d.ts +1 -1
- package/dist/core/review-fix.js +4 -3
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +3 -0
- package/dist/core/review-host-tools.js +102 -14
- package/dist/core/review-reads.d.ts +55 -0
- package/dist/core/review-reads.js +233 -0
- package/dist/core/run-status.d.ts +12 -0
- package/dist/core/run-status.js +12 -0
- package/dist/core/runner.d.ts +145 -49
- package/dist/core/runner.js +719 -216
- package/dist/core/schedule-start.d.ts +12 -0
- package/dist/core/schedule-start.js +14 -0
- package/dist/core/secret-broker-config.d.ts +12 -74
- package/dist/core/secret-broker-config.js +1 -1
- package/dist/core/secret-guard.d.ts +49 -0
- package/dist/core/secret-guard.js +119 -0
- package/dist/core/secret-guarded-stores.d.ts +12 -0
- package/dist/core/secret-guarded-stores.js +41 -0
- package/dist/core/secret-spans.d.ts +50 -0
- package/dist/core/secret-spans.js +94 -0
- package/dist/core/secrets.d.ts +11 -1
- package/dist/core/secrets.js +27 -1
- package/dist/core/serializable-retry.d.ts +18 -0
- package/dist/core/serializable-retry.js +43 -0
- package/dist/core/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/tool-admin.d.ts +5 -1
- package/dist/core/tool-admin.js +7 -2
- package/dist/core/tool-names.d.ts +13 -0
- package/dist/core/tool-names.js +20 -0
- package/dist/core/webhooks.d.ts +4 -0
- package/dist/core/webhooks.js +68 -49
- package/dist/core/workflow-events.d.ts +14 -2
- package/dist/core/workflow-events.js +4 -0
- package/dist/core/workflow-run-events.d.ts +5 -3
- package/dist/core/workflow-run-events.js +45 -9
- package/dist/core/zod-json-schema.d.ts +4 -0
- package/dist/core/zod-json-schema.js +39 -0
- package/dist/core/zod3-window.d.ts +35 -0
- package/dist/core/zod3-window.js +124 -0
- package/dist/generated/prisma/browser.d.ts +65 -3
- package/dist/generated/prisma/client.d.ts +65 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +266 -106
- package/dist/generated/prisma/enums.d.ts +10 -0
- package/dist/generated/prisma/enums.js +8 -0
- package/dist/generated/prisma/internal/class.d.ts +110 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +957 -9
- package/dist/generated/prisma/internal/prismaNamespace.js +166 -2
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +174 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +166 -2
- package/dist/generated/prisma/models/Agent.d.ts +377 -8
- package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
- package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
- package/dist/generated/prisma/models/AgentRepository.d.ts +81 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +228 -7
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
- package/dist/generated/prisma/models/CodingProxySession.d.ts +232 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1712 -1
- package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
- package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
- package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
- package/dist/generated/prisma/models/HostProvider.js +1 -0
- package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
- package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
- package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
- package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
- package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
- package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
- package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
- package/dist/generated/prisma/models/McpServer.js +1 -0
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +77 -1
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
- package/dist/generated/prisma/models/Principal.d.ts +167 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
- package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
- package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
- package/dist/generated/prisma/models/Run.d.ts +738 -2
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
- package/dist/generated/prisma/models/RunTranscript.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +387 -0
- package/dist/generated/prisma/models/Tool.d.ts +223 -1
- package/dist/generated/prisma/models.d.ts +10 -0
- package/dist/help/search.js +12 -3
- package/dist/help-index.json +2033 -110
- package/dist/import/create.js +48 -4
- package/dist/import/neutral-schema.d.ts +51 -281
- package/dist/import/neutral-schema.js +7 -4
- package/dist/knowledge/check.d.ts +1 -1
- package/dist/knowledge/cli.d.ts +11 -1
- package/dist/knowledge/cli.js +37 -4
- package/dist/knowledge/concept.d.ts +3 -19
- package/dist/knowledge/location.d.ts +31 -0
- package/dist/knowledge/location.js +78 -0
- package/dist/mcp/auth/access.d.ts +10 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/grants-cli.d.ts +6 -4
- package/dist/mcp/auth/grants-cli.js +42 -3
- package/dist/mcp/auth/ownership.d.ts +7 -7
- package/dist/mcp/auth/resource-server.d.ts +3 -1
- package/dist/mcp/auth/resource-server.js +17 -2
- package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
- package/dist/mcp/context.d.ts +3 -0
- package/dist/mcp/host-events/github-ingress.d.ts +2 -0
- package/dist/mcp/host-events/github-ingress.js +2 -1
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +69 -10
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +33 -14
- package/dist/mcp/tools/agents.d.ts +4 -0
- package/dist/mcp/tools/agents.js +295 -28
- package/dist/mcp/tools/datastore.js +17 -8
- package/dist/mcp/tools/grants.js +73 -29
- package/dist/mcp/tools/host-providers.d.ts +2 -0
- package/dist/mcp/tools/host-providers.js +215 -0
- package/dist/mcp/tools/mcp-servers.d.ts +26 -0
- package/dist/mcp/tools/mcp-servers.js +481 -0
- package/dist/mcp/tools/memory.js +11 -1
- package/dist/mcp/tools/notification-channels.js +2 -2
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -0
- package/dist/mcp/tools/repositories.js +65 -12
- package/dist/mcp/tools/run-access.d.ts +16 -0
- package/dist/mcp/tools/run-access.js +25 -0
- package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
- package/dist/mcp/tools/run-transcript-download.js +129 -0
- package/dist/mcp/tools/run-transcript.d.ts +19 -0
- package/dist/mcp/tools/run-transcript.js +70 -0
- package/dist/mcp/tools/runs.js +209 -27
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-elicitation-form.js +5 -0
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -61
- package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
- package/dist/mcp/tools/secret-elicitation.js +25 -2
- package/dist/mcp/tools/secrets.js +40 -6
- package/dist/mcp/tools/stop-run.d.ts +2 -0
- package/dist/mcp/tools/stop-run.js +82 -0
- package/dist/mcp/tools/subagents.js +2 -2
- package/dist/mcp/tools/tools.d.ts +7 -5
- package/dist/mcp/tools/tools.js +64 -16
- package/dist/mcp/tools/trigger.js +28 -6
- package/dist/mcp/transport/http-limits.d.ts +2 -0
- package/dist/mcp/transport/http-limits.js +6 -2
- package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
- package/dist/mcp/transport/stdio-link-host.js +67 -0
- package/dist/mcp/transport/streamable-http.d.ts +13 -0
- package/dist/mcp/transport/streamable-http.js +41 -1
- package/dist/mcp/webhooks/ingress.js +10 -0
- package/dist/native-worker/docker-launcher.d.ts +38 -2
- package/dist/native-worker/docker-launcher.js +65 -5
- package/dist/native-worker/gateway-server.d.ts +55 -3
- package/dist/native-worker/gateway-server.js +152 -34
- package/dist/native-worker/gateway.d.ts +29 -1
- package/dist/native-worker/gateway.js +74 -4
- package/dist/native-worker/http-server.d.ts +7 -1
- package/dist/native-worker/http-server.js +62 -7
- package/dist/native-worker/http-transport.js +1 -1
- package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
- package/dist/native-worker/kubernetes-launcher.js +43 -3
- package/dist/native-worker/launch.d.ts +18 -1
- package/dist/native-worker/launch.js +6 -1
- package/dist/native-worker/ledger.d.ts +24 -4
- package/dist/native-worker/ledger.js +62 -8
- package/dist/native-worker/loopback.js +3 -8
- package/dist/native-worker/main.d.ts +2 -1
- package/dist/native-worker/main.js +14 -3
- package/dist/native-worker/protocol.d.ts +130 -577
- package/dist/native-worker/protocol.js +51 -2
- package/dist/native-worker/sandbox-executor.d.ts +17 -2
- package/dist/native-worker/sandbox-executor.js +78 -4
- package/dist/native-worker/stderr-redaction.d.ts +77 -0
- package/dist/native-worker/stderr-redaction.js +237 -0
- package/dist/native-worker/stdio.d.ts +1 -1
- package/dist/native-worker/stdio.js +6 -5
- package/dist/native-worker/warm-pool.d.ts +2 -2
- package/dist/native-worker/warm-pool.js +4 -4
- package/dist/native-worker/worker.js +28 -2
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/self-hosted.d.ts +1 -1
- package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
- package/dist/providers/coding-proxy/capability-hash.js +5 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
- package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
- package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
- package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
- package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
- package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
- package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
- package/dist/providers/coding-proxy/hold.d.ts +32 -0
- package/dist/providers/coding-proxy/hold.js +86 -0
- package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
- package/dist/providers/coding-proxy/interrupted.js +104 -0
- package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
- package/dist/providers/coding-proxy/mcp-route.js +166 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -2
- package/dist/providers/coding-proxy/memory-ledger.js +99 -8
- package/dist/providers/coding-proxy/metering.d.ts +16 -0
- package/dist/providers/coding-proxy/metering.js +27 -4
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +16 -2
- package/dist/providers/coding-proxy/prisma-ledger.js +209 -69
- package/dist/providers/coding-proxy/proxy.d.ts +21 -2
- package/dist/providers/coding-proxy/proxy.js +300 -48
- package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
- package/dist/providers/coding-proxy/registry/audit.js +94 -17
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
- package/dist/providers/coding-proxy/registry/plan.js +201 -48
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
- package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
- package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
- package/dist/providers/coding-proxy/registry/service.js +579 -112
- package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
- package/dist/providers/coding-proxy/registry/store.js +54 -1
- package/dist/providers/coding-proxy/runtime.d.ts +10 -0
- package/dist/providers/coding-proxy/runtime.js +109 -16
- package/dist/providers/coding-proxy/server.d.ts +9 -1
- package/dist/providers/coding-proxy/server.js +55 -1
- package/dist/providers/coding-proxy/types.d.ts +78 -1
- package/dist/providers/datastore/types.d.ts +5 -0
- package/dist/providers/engine/types.d.ts +17 -2
- package/dist/providers/engine/types.js +17 -0
- package/dist/providers/executor/composition.d.ts +10 -3
- package/dist/providers/executor/composition.js +52 -7
- package/dist/providers/executor/container.d.ts +394 -9
- package/dist/providers/executor/container.js +1210 -96
- package/dist/providers/executor/dbos-status.d.ts +31 -0
- package/dist/providers/executor/dbos-status.js +64 -0
- package/dist/providers/executor/dbos.d.ts +50 -1
- package/dist/providers/executor/dbos.js +207 -20
- package/dist/providers/executor/deferred.d.ts +12 -24
- package/dist/providers/executor/deferred.js +10 -29
- package/dist/providers/executor/in-process.d.ts +9 -1
- package/dist/providers/executor/in-process.js +14 -4
- package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
- package/dist/providers/executor/linked-issue-reader.js +30 -0
- package/dist/providers/executor/routing.d.ts +2 -0
- package/dist/providers/executor/routing.js +4 -0
- package/dist/providers/executor/types.d.ts +13 -0
- package/dist/providers/host-tools/invoke.d.ts +37 -0
- package/dist/providers/host-tools/invoke.js +117 -0
- package/dist/providers/host-tools/operations.d.ts +65 -0
- package/dist/providers/host-tools/operations.js +149 -0
- package/dist/providers/host-tools/registry.d.ts +79 -0
- package/dist/providers/host-tools/registry.js +362 -0
- package/dist/providers/host-tools/request-guard.d.ts +17 -0
- package/dist/providers/host-tools/request-guard.js +99 -0
- package/dist/providers/host-tools/self-test.d.ts +64 -0
- package/dist/providers/host-tools/self-test.js +142 -0
- package/dist/providers/index.d.ts +2 -1
- package/dist/providers/issue-tracker/types.d.ts +17 -0
- package/dist/providers/issue-tracker/types.js +39 -1
- package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
- package/dist/providers/jobs/claude-tool-setup.js +5 -2
- package/dist/providers/jobs/docker-isolation.d.ts +10 -2
- package/dist/providers/jobs/docker-isolation.js +47 -8
- package/dist/providers/jobs/docker.d.ts +9 -0
- package/dist/providers/jobs/docker.js +60 -11
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
- package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
- package/dist/providers/jobs/kubernetes-api.js +10 -0
- package/dist/providers/jobs/kubernetes-client.js +10 -1
- package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
- package/dist/providers/jobs/kubernetes-isolation.js +32 -3
- package/dist/providers/jobs/kubernetes.d.ts +11 -1
- package/dist/providers/jobs/kubernetes.js +111 -17
- package/dist/providers/jobs/types.d.ts +39 -0
- package/dist/providers/jobs/types.js +13 -1
- package/dist/providers/llm/anthropic.js +5 -1
- package/dist/providers/llm/bedrock.d.ts +0 -12
- package/dist/providers/llm/bedrock.js +4 -0
- package/dist/providers/llm/claude-messages.d.ts +3 -1
- package/dist/providers/llm/claude-messages.js +4 -1
- package/dist/providers/llm/claude-provider.d.ts +2 -2
- package/dist/providers/llm/claude-provider.js +2 -2
- package/dist/providers/llm/openai.d.ts +2 -2
- package/dist/providers/llm/openai.js +6 -2
- package/dist/providers/llm/routing.d.ts +2 -2
- package/dist/providers/llm/routing.js +2 -2
- package/dist/providers/llm/types.d.ts +12 -2
- package/dist/providers/review-host/github-events.d.ts +9 -1
- package/dist/providers/review-host/github-events.js +34 -12
- package/dist/providers/review-host/github.d.ts +29 -2
- package/dist/providers/review-host/github.js +224 -29
- package/dist/providers/review-host/local.d.ts +8 -4
- package/dist/providers/review-host/local.js +49 -31
- package/dist/providers/review-host/patch-pages.d.ts +41 -0
- package/dist/providers/review-host/patch-pages.js +176 -0
- package/dist/providers/review-host/review-format.d.ts +19 -1
- package/dist/providers/review-host/review-format.js +38 -7
- package/dist/providers/review-host/types.d.ts +140 -6
- package/dist/providers/review-host/types.js +9 -1
- package/dist/providers/storage/gcs.d.ts +63 -0
- package/dist/providers/storage/gcs.js +69 -0
- package/dist/providers/storage/index.d.ts +15 -0
- package/dist/providers/storage/index.js +14 -0
- package/dist/providers/storage/local.d.ts +24 -0
- package/dist/providers/storage/local.js +92 -0
- package/dist/providers/storage/meter.d.ts +14 -0
- package/dist/providers/storage/meter.js +34 -0
- package/dist/providers/storage/s3.d.ts +41 -0
- package/dist/providers/storage/s3.js +107 -0
- package/dist/providers/storage/types.d.ts +37 -3
- package/dist/providers/storage/types.js +21 -4
- package/dist/providers/vcs/git.d.ts +39 -4
- package/dist/providers/vcs/git.js +339 -26
- package/dist/providers/vcs/github-remote.d.ts +26 -3
- package/dist/providers/vcs/github-remote.js +124 -14
- package/dist/providers/vcs/github.d.ts +183 -44
- package/dist/providers/vcs/github.js +455 -56
- package/dist/providers/vcs/index.d.ts +1 -1
- package/dist/providers/vcs/index.js +9 -2
- package/dist/providers/vcs/pr-description.d.ts +127 -0
- package/dist/providers/vcs/pr-description.js +270 -0
- package/dist/providers/vcs/remote.d.ts +37 -1
- package/dist/providers/vcs/remote.js +7 -1
- package/dist/providers/vcs/routing.d.ts +16 -8
- package/dist/providers/vcs/routing.js +27 -6
- package/dist/providers/vcs/types.d.ts +150 -5
- package/dist/quickstart/coding-seed.d.ts +14 -3
- package/dist/quickstart/coding-seed.js +213 -4
- package/dist/quickstart/index.d.ts +5 -0
- package/dist/quickstart/index.js +21 -0
- package/dist/quickstart/reviewer-prompt.d.ts +1 -1
- package/dist/quickstart/reviewer-prompt.js +6 -6
- package/dist/quickstart-images.json +1 -1
- package/dist/sandbox/eval-core.d.ts +12 -2
- package/dist/sandbox/eval-core.js +20 -4
- package/dist/sandbox/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +5 -0
- package/dist/sandbox/host-functions.js +13 -13
- package/dist/sandbox/limits.d.ts +4 -1
- package/dist/sandbox/limits.js +4 -1
- package/dist/sandbox/run-in-sandbox.d.ts +6 -0
- package/dist/sandbox/run-in-sandbox.js +14 -2
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +1 -1
- package/dist/sandbox/secret-broker.d.ts +1 -0
- package/dist/sandbox/secret-broker.js +4 -5
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/tool-timeout.d.ts +32 -0
- package/dist/sandbox/tool-timeout.js +52 -0
- package/dist/sandbox/user-tool.d.ts +8 -1
- package/dist/sandbox/user-tool.js +9 -3
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +8 -1
- package/dist/viewer/api-schema.d.ts +349 -2627
- package/dist/viewer/api-schema.js +7 -0
- package/dist/viewer/build-schemas.js +6 -2
- package/dist/viewer/graph.js +2 -1
- package/dist/viewer/openapi.js +2 -4
- package/dist/wardby-bin.js +15 -0
- package/docs/README.md +11 -1
- package/docs/agent-recipes.md +95 -24
- package/docs/architecture-runtime.md +1 -1
- package/docs/claude-code-plugin.md +164 -0
- package/docs/code-review-agents.md +557 -41
- package/docs/coding-agent-setup.md +566 -8
- package/docs/coding-packages.md +1033 -90
- package/docs/coding-services.md +27 -12
- package/docs/coding-worker-byo-images.md +24 -2
- package/docs/coding-worker-isolation.md +183 -37
- package/docs/debugging-agent-runs.md +242 -0
- package/docs/getting-started-gke.md +129 -141
- package/docs/getting-started-identity-provider.md +53 -38
- package/docs/getting-started.md +17 -0
- package/docs/host-providers.md +294 -0
- package/docs/jira-agents.md +17 -8
- package/docs/knowledge/blob-not-found-semantics.md +41 -0
- package/docs/knowledge/bounded-file-descriptor.md +52 -0
- package/docs/knowledge/delegation-admission-slots.md +52 -0
- package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
- package/docs/knowledge/import-rename-target.md +52 -0
- package/docs/knowledge/index.md +57 -0
- package/docs/knowledge/log.md +9 -0
- package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
- package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
- package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
- package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
- package/docs/knowledge/overview-cli.md +74 -0
- package/docs/knowledge/overview-coding-proxy.md +72 -0
- package/docs/knowledge/overview-coding.md +72 -0
- package/docs/knowledge/overview-config.md +60 -0
- package/docs/knowledge/overview-core.md +72 -0
- package/docs/knowledge/overview-deploy.md +83 -0
- package/docs/knowledge/overview-mcp.md +61 -0
- package/docs/knowledge/overview-prisma.md +72 -0
- package/docs/knowledge/overview-providers.md +89 -0
- package/docs/knowledge/overview-sandbox.md +83 -0
- package/docs/knowledge/overview-surfaces.md +83 -0
- package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
- package/docs/knowledge/proxy-settlement-projections.md +41 -0
- package/docs/knowledge/run-pricing-first-writer.md +43 -0
- package/docs/knowledge/schedule-claim-transaction.md +41 -0
- package/docs/knowledge/secret-entry-replica-contract.md +52 -0
- package/docs/knowledge/terminal-run-first-writer.md +41 -0
- package/docs/knowledge/transactional-agent-authorization.md +52 -0
- package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
- package/docs/knowledge/warm-input-publication.md +30 -0
- package/docs/knowledge/workspace-staging-failure.md +54 -0
- package/docs/knowledge.md +54 -14
- package/docs/mcp-servers.md +254 -0
- package/docs/native-sandbox.md +143 -31
- package/docs/observability.md +4 -0
- package/docs/security-deployment.md +139 -29
- package/docs/slack-notifications.md +35 -19
- package/docs/tool-secrets.md +45 -10
- package/docs/viewer-api.md +6 -0
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +28 -2
- package/help/agent-recipes.md +33 -2
- package/help/architecture-agent.md +11 -6
- package/help/brokered-secrets.md +3 -0
- package/help/build-claude-code-image.md +1 -1
- package/help/build-worker-image.md +3 -1
- package/help/builder-agent.md +19 -6
- package/help/claude-code-run-pane.md +40 -0
- package/help/code-review-agents.md +177 -6
- package/help/coding-packages.md +156 -6
- package/help/cost-attribution.md +9 -5
- package/help/creating-agents.md +14 -1
- package/help/dependency-cache.md +143 -0
- package/help/deploy-gke.md +15 -8
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- package/help/errors/coding-mcp-pins-unavailable.md +35 -0
- package/help/errors/coding-stream-quota-exceeded.md +33 -0
- package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
- package/help/errors/continuation-closed.md +9 -12
- package/help/errors/database-auth-invalid.md +1 -1
- package/help/errors/delegation-conflict.md +24 -0
- package/help/errors/file-list-truncated.md +45 -0
- package/help/errors/full-read-required.md +49 -0
- package/help/errors/github-account-not-allowed.md +4 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/host-provider-error.md +40 -0
- package/help/errors/host-tool-failed.md +36 -0
- package/help/errors/mcp-call-limit.md +22 -0
- package/help/errors/mcp-call-timeout.md +22 -0
- package/help/errors/mcp-server-auth-failed.md +22 -0
- package/help/errors/mcp-server-credentials-unavailable.md +45 -0
- package/help/errors/mcp-server-error.md +28 -0
- package/help/errors/mcp-server-unreachable.md +22 -0
- package/help/errors/mcp-servers-off.md +21 -0
- package/help/errors/mcp-tool-not-allowed.md +26 -0
- package/help/errors/mcp-tool-removed.md +22 -0
- package/help/errors/mcp-unavailable.md +25 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/native-sandbox-capacity.md +1 -1
- package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
- package/help/errors/native-sandbox-docker-failed.md +1 -1
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
- package/help/errors/native-sandbox-image-not-pinned.md +1 -1
- package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-network-unenforced.md +1 -1
- package/help/errors/native-sandbox-requires-catalog.md +1 -1
- package/help/errors/native-sandbox-unavailable.md +1 -1
- package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
- package/help/errors/native-sandbox-worker-exited.md +4 -3
- package/help/errors/native-sandbox-worker-lost.md +1 -1
- package/help/errors/native-sandbox-worker-unready.md +1 -1
- package/help/errors/package-not-allowed-pending.md +52 -0
- package/help/errors/package-not-allowed.md +51 -0
- package/help/errors/package-refusals.md +43 -0
- package/help/errors/patch-cursor-malformed.md +31 -0
- package/help/errors/repository-not-listed.md +36 -0
- package/help/errors/repository-required.md +36 -0
- package/help/errors/run-lost.md +39 -0
- package/help/errors/run-transcript-download.md +44 -0
- package/help/errors/secret-in-value.md +69 -0
- package/help/errors/target-merge.md +40 -0
- package/help/errors/tool-timeout.md +38 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/github-app-setup.md +132 -0
- package/help/github.md +22 -0
- package/help/host-providers.md +40 -0
- package/help/identity-and-access.md +6 -1
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +1 -1
- package/help/low-power-mode.md +7 -1
- package/help/mcp-servers.md +73 -0
- package/help/mcp.md +7 -2
- package/help/merge-order-check.md +5 -0
- package/help/native-capabilities.md +55 -1
- package/help/native-sandbox.md +16 -2
- package/help/operating-agents.md +21 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +17 -10
- package/help/repo-instructions-and-skills.md +3 -1
- package/help/resume-runs-locally.md +134 -0
- package/help/review-fix-rounds.md +33 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +19 -5
- package/help/status-comments.md +31 -0
- package/help/stop-run.md +58 -0
- package/help/troubleshooting/budgets.md +28 -0
- package/help/troubleshooting/coding-workers.md +86 -7
- package/help/troubleshooting/debugging-agent-runs.md +29 -0
- package/package.json +18 -10
- package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
- package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
- package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
- package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
- package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
- package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
- package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
- package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
- package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
- package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
- package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
- package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
- package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
- package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
- package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
- package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
- package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
- package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
- package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
- package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
- package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
- package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
- package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
- package/prisma/schema.prisma +468 -109
- package/scripts/git-askpass.sh +1 -1
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote MCP servers over Wardby's own MCP (docs/mcp-servers.md): register a server (HTTPS URL plus the
|
|
3
|
+
* owner's brokered secrets), keep its saved tool list fresh, and attach an allowlisted subset of its tools
|
|
4
|
+
* to an agent. Gated by WARDBY_MCP_SERVERS (off | admins | owners). Results carry secret names, never
|
|
5
|
+
* values: snapshots and errors arrive from fetchSnapshot already redacted. Audit lines carry the URL's host
|
|
6
|
+
* only, never the full URL (a query string can carry a token).
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { Prisma } from "#prisma";
|
|
10
|
+
import { loadMcpServersMode, MCP_SERVERS_OFF_MESSAGE } from "../../config/mcp-servers.js";
|
|
11
|
+
import { loadToolMaxTimeoutMs } from "../../config/tool-timeout.js";
|
|
12
|
+
import { atLeast, deleteGrantsFor, effectiveAccess, grantedIds } from "../../core/grants.js";
|
|
13
|
+
import { logger } from "../../core/logger.js";
|
|
14
|
+
import { McpClientError } from "../../core/mcp-client/client.js";
|
|
15
|
+
import { assertServerName, diffSnapshots, exposedNames, exposedToolName, fetchSnapshot, logCredentialsUnavailable, McpCredentialsUnavailableError, McpServerInputError, normaliseServerUrl, snapshotOf, } from "../../core/mcp-servers.js";
|
|
16
|
+
import { isCodexCoding, isMarkedReadOnly } from "../../core/mcp-tools.js";
|
|
17
|
+
import { REVIEW_HOST_TOOL_NAMES } from "../../core/review-host-tools.js";
|
|
18
|
+
import { preferIndexScans, withSerializableRetry } from "../../core/serializable-retry.js";
|
|
19
|
+
import { reservedToolNameReason } from "../../core/tool-names.js";
|
|
20
|
+
import { agentAccessResolver, assertAgentAccess, requireAgentAccess, requireBindable } from "../auth/access.js";
|
|
21
|
+
import { requireScope } from "../auth/resource-server.js";
|
|
22
|
+
import { McpError } from "../errors.js";
|
|
23
|
+
import { textResult } from "./text-result.js";
|
|
24
|
+
const serversLog = logger.child({ module: "mcp-servers" });
|
|
25
|
+
export { MCP_SERVERS_OFF_MESSAGE };
|
|
26
|
+
const DESCRIPTION_PREVIEW_CHARS = 300;
|
|
27
|
+
const MIN_CALL_TIMEOUT_MS = 1000;
|
|
28
|
+
/**
|
|
29
|
+
* Refuses when the mode is off, except for cleanup (delete and detach stay possible so an operator who
|
|
30
|
+
* turns the feature off can still remove servers and attachments); in admins mode, register/update/refresh
|
|
31
|
+
* also need hosts:admin.
|
|
32
|
+
*/
|
|
33
|
+
function gate(ctx, kind) {
|
|
34
|
+
const mode = loadMcpServersMode();
|
|
35
|
+
if (mode === "off" && kind !== "cleanup")
|
|
36
|
+
throw new McpError(403, MCP_SERVERS_OFF_MESSAGE);
|
|
37
|
+
if (kind === "configure" && mode === "admins")
|
|
38
|
+
requireScope(ctx, ctx.canonicalUri, "hosts:admin");
|
|
39
|
+
}
|
|
40
|
+
function audit(ctx, action, server) {
|
|
41
|
+
serversLog.info({
|
|
42
|
+
event: `mcp.server.${action}`,
|
|
43
|
+
serverId: server.id,
|
|
44
|
+
name: server.name,
|
|
45
|
+
host: new URL(server.url).hostname,
|
|
46
|
+
by: ctx.principal.id,
|
|
47
|
+
}, "MCP server changed");
|
|
48
|
+
}
|
|
49
|
+
function parse(schema, label, value) {
|
|
50
|
+
const result = schema.safeParse(value);
|
|
51
|
+
if (result.success)
|
|
52
|
+
return result.data;
|
|
53
|
+
const details = result.error.issues.map((i) => `${i.path.join(".") || "input"}: ${i.message}`).join("; ");
|
|
54
|
+
throw new McpError(400, `Invalid ${label}: ${details}`);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Input errors → 400; MCP client errors (already redacted) → 502 with their code. Undecryptable
|
|
58
|
+
* credentials → 500 with their code: the fault is this Wardby server's key setup, not the remote
|
|
59
|
+
* server (502 would point at it) or the caller's input (400).
|
|
60
|
+
*/
|
|
61
|
+
async function mapped(work) {
|
|
62
|
+
try {
|
|
63
|
+
return await work();
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (err instanceof McpServerInputError)
|
|
67
|
+
throw new McpError(400, err.message);
|
|
68
|
+
if (err instanceof McpCredentialsUnavailableError) {
|
|
69
|
+
logCredentialsUnavailable(serversLog, err);
|
|
70
|
+
throw new McpError(500, `${err.code}: ${err.message}`);
|
|
71
|
+
}
|
|
72
|
+
if (err instanceof McpClientError)
|
|
73
|
+
throw new McpError(502, `${err.code}: ${err.message}`);
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function serverNotFound(id) {
|
|
78
|
+
return new McpError(404, `MCP server "${id}" not found.`);
|
|
79
|
+
}
|
|
80
|
+
/** The caller's own server, or 404 (whether it is missing or someone else's). */
|
|
81
|
+
async function requireOwnedServer(ctx, id, db = ctx.db) {
|
|
82
|
+
const server = await db.mcpServer.findUnique({ where: { id } });
|
|
83
|
+
if (!server || server.ownerId !== ctx.principal.id)
|
|
84
|
+
throw serverNotFound(id);
|
|
85
|
+
return server;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A server the caller owns or holds at least `min` on through a grant. Missing and no-access look the same
|
|
89
|
+
* (404); a grant that is too low says what it lacks (403).
|
|
90
|
+
*/
|
|
91
|
+
async function requireServerAccess(ctx, id, min, db = ctx.db) {
|
|
92
|
+
const server = await db.mcpServer.findUnique({ where: { id } });
|
|
93
|
+
if (!server)
|
|
94
|
+
throw serverNotFound(id);
|
|
95
|
+
const access = await effectiveAccess(db, "mcp_server", server, ctx.principal.id);
|
|
96
|
+
if (access === "none")
|
|
97
|
+
throw serverNotFound(id);
|
|
98
|
+
if (!atLeast("mcp_server", access, min)) {
|
|
99
|
+
throw new McpError(403, `MCP server "${server.name}": attaching it needs use access (you have ${access}).`);
|
|
100
|
+
}
|
|
101
|
+
return server;
|
|
102
|
+
}
|
|
103
|
+
function takeSnapshot(ctx, server) {
|
|
104
|
+
return mapped(() => fetchSnapshot(server, { db: ctx.db, cipher: ctx.providers.secrets, fetchImpl: ctx.providers.sandboxFetch }));
|
|
105
|
+
}
|
|
106
|
+
function snapshotData(snapshot) {
|
|
107
|
+
return {
|
|
108
|
+
toolSnapshot: snapshot.tools,
|
|
109
|
+
serverInfo: snapshot.serverInfo,
|
|
110
|
+
snapshotAt: new Date(),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function serverView(server) {
|
|
114
|
+
return {
|
|
115
|
+
id: server.id,
|
|
116
|
+
name: server.name,
|
|
117
|
+
url: server.url,
|
|
118
|
+
secretNames: server.secretNames,
|
|
119
|
+
serverInfo: server.serverInfo,
|
|
120
|
+
snapshotAt: server.snapshotAt,
|
|
121
|
+
tools: snapshotOf(server).map((t) => ({
|
|
122
|
+
name: t.name,
|
|
123
|
+
description: t.description.slice(0, DESCRIPTION_PREVIEW_CHARS),
|
|
124
|
+
annotations: t.annotations,
|
|
125
|
+
})),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** get_agent's mcpServers field: each attachment with its exposed names and allowed tools gone from the snapshot. */
|
|
129
|
+
export async function agentMcpServerViews(db, agentId) {
|
|
130
|
+
const rows = await db.agentMcpServer.findMany({
|
|
131
|
+
where: { agentId },
|
|
132
|
+
include: { server: { select: { id: true, name: true, toolSnapshot: true } } },
|
|
133
|
+
orderBy: { createdAt: "asc" },
|
|
134
|
+
});
|
|
135
|
+
return rows.map((row) => {
|
|
136
|
+
const present = new Set(snapshotOf(row.server).map((t) => t.name));
|
|
137
|
+
return {
|
|
138
|
+
serverId: row.server.id,
|
|
139
|
+
serverName: row.server.name,
|
|
140
|
+
allowedTools: row.allowedTools,
|
|
141
|
+
exposedNames: exposedNames(row.server.name, row.allowedTools),
|
|
142
|
+
callTimeoutMs: row.callTimeoutMs,
|
|
143
|
+
missingTools: row.allowedTools.filter((name) => !present.has(name)),
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/** The update_agent warning when an agent becomes Codex with attached tools the server doesn't mark read-only. */
|
|
148
|
+
export function codexWriteToolsWarning(names) {
|
|
149
|
+
return `These MCP tools aren't read-only and won't be available to Codex runs: ${names.join(", ")}.`;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The exposed names of an agent's attached, allowed tools that the saved tool list doesn't mark read-only:
|
|
153
|
+
* a Codex run never gets them (loadMcpToolPins with readOnlyOnly). Tools no longer listed are left out.
|
|
154
|
+
*/
|
|
155
|
+
export async function codexUnavailableMcpTools(db, agentId) {
|
|
156
|
+
const rows = await db.agentMcpServer.findMany({
|
|
157
|
+
where: { agentId },
|
|
158
|
+
include: { server: { select: { name: true, toolSnapshot: true } } },
|
|
159
|
+
orderBy: [{ createdAt: "asc" }, { serverId: "asc" }],
|
|
160
|
+
});
|
|
161
|
+
return rows.flatMap((row) => {
|
|
162
|
+
const byName = new Map(snapshotOf(row.server).map((t) => [t.name, t]));
|
|
163
|
+
const writers = row.allowedTools.filter((name) => byName.has(name) && !isMarkedReadOnly(byName.get(name)));
|
|
164
|
+
return exposedNames(row.server.name, writers);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const SecretNames = z.array(z.string().min(1).max(1024)).max(8);
|
|
168
|
+
const RegisterSchema = z
|
|
169
|
+
.object({ name: z.string().max(64), url: z.string().max(2048), secretNames: SecretNames.default([]) })
|
|
170
|
+
.strict();
|
|
171
|
+
const UpdateSchema = z
|
|
172
|
+
.object({ id: z.string().min(1).max(64), url: z.string().max(2048).optional(), secretNames: SecretNames.optional() })
|
|
173
|
+
.strict();
|
|
174
|
+
const IdSchema = z.object({ id: z.string().min(1).max(64) }).strict();
|
|
175
|
+
const AttachSchema = z
|
|
176
|
+
.object({
|
|
177
|
+
agentId: z.string().min(1).max(64),
|
|
178
|
+
serverId: z.string().min(1).max(64),
|
|
179
|
+
allowedTools: z.array(z.string().min(1).max(200)).min(1).max(500),
|
|
180
|
+
callTimeoutMs: z.number().int().optional(),
|
|
181
|
+
})
|
|
182
|
+
.strict();
|
|
183
|
+
const DetachSchema = z.object({ agentId: z.string().min(1).max(64), serverId: z.string().min(1).max(64) }).strict();
|
|
184
|
+
const ID_ONLY = {
|
|
185
|
+
type: "object",
|
|
186
|
+
additionalProperties: false,
|
|
187
|
+
required: ["id"],
|
|
188
|
+
properties: { id: { type: "string" } },
|
|
189
|
+
};
|
|
190
|
+
export function registerMcpServerTools(mcp) {
|
|
191
|
+
mcp.registerTool({
|
|
192
|
+
name: "register_mcp_server",
|
|
193
|
+
scope: "tools:write",
|
|
194
|
+
description: "Register a remote MCP server (Streamable HTTP, https only) so its tools can be attached to your agents. secretNames are your brokered secrets, each brokered to the URL's host; they are sent on every request and never readable. Wardby calls the server's tools/list and saves the result. With WARDBY_MCP_SERVERS=admins this needs hosts:admin.",
|
|
195
|
+
inputSchema: {
|
|
196
|
+
type: "object",
|
|
197
|
+
additionalProperties: false,
|
|
198
|
+
required: ["name", "url"],
|
|
199
|
+
properties: {
|
|
200
|
+
name: {
|
|
201
|
+
type: "string",
|
|
202
|
+
description: "Lower-case letters, digits, _ or -; prefixes the tool names agents see.",
|
|
203
|
+
},
|
|
204
|
+
url: { type: "string", description: "The server's https endpoint, e.g. https://mcp.example.com/mcp." },
|
|
205
|
+
secretNames: { type: "array", items: { type: "string" } },
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
handler: async (rawArgs, ctx) => {
|
|
209
|
+
gate(ctx, "configure");
|
|
210
|
+
const input = parse(RegisterSchema, "register_mcp_server arguments", rawArgs);
|
|
211
|
+
const url = await mapped(async () => {
|
|
212
|
+
assertServerName(input.name);
|
|
213
|
+
return normaliseServerUrl(input.url);
|
|
214
|
+
});
|
|
215
|
+
const ownerId = ctx.principal.id;
|
|
216
|
+
const taken = () => new McpError(409, `You already have an MCP server named "${input.name}".`);
|
|
217
|
+
if (await ctx.db.mcpServer.findUnique({ where: { ownerId_name: { ownerId, name: input.name } } }))
|
|
218
|
+
throw taken();
|
|
219
|
+
const draft = { id: "", ownerId, name: input.name, url, secretNames: input.secretNames };
|
|
220
|
+
const snapshot = await takeSnapshot(ctx, draft);
|
|
221
|
+
let server;
|
|
222
|
+
try {
|
|
223
|
+
server = await ctx.db.mcpServer.create({
|
|
224
|
+
data: { ownerId, name: input.name, url, secretNames: input.secretNames, ...snapshotData(snapshot) },
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === "P2002")
|
|
229
|
+
throw taken();
|
|
230
|
+
throw err;
|
|
231
|
+
}
|
|
232
|
+
audit(ctx, "register", server);
|
|
233
|
+
return textResult(serverView(server));
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
mcp.registerTool({
|
|
237
|
+
name: "update_mcp_server",
|
|
238
|
+
scope: "tools:write",
|
|
239
|
+
description: "Owner only: change a server's URL or secretNames. Wardby re-checks the secrets, saves a fresh tool list straight away and returns what changed (diff). With WARDBY_MCP_SERVERS=admins this needs hosts:admin.",
|
|
240
|
+
inputSchema: {
|
|
241
|
+
type: "object",
|
|
242
|
+
additionalProperties: false,
|
|
243
|
+
required: ["id"],
|
|
244
|
+
properties: {
|
|
245
|
+
id: { type: "string" },
|
|
246
|
+
url: { type: "string" },
|
|
247
|
+
secretNames: { type: "array", items: { type: "string" } },
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
handler: async (rawArgs, ctx) => {
|
|
251
|
+
gate(ctx, "configure");
|
|
252
|
+
const input = parse(UpdateSchema, "update_mcp_server arguments", rawArgs);
|
|
253
|
+
const current = await requireOwnedServer(ctx, input.id);
|
|
254
|
+
const url = input.url === undefined ? current.url : await mapped(async () => normaliseServerUrl(input.url));
|
|
255
|
+
const secretNames = input.secretNames ?? current.secretNames;
|
|
256
|
+
const snapshot = await takeSnapshot(ctx, { ...current, url, secretNames });
|
|
257
|
+
const server = await ctx.db.mcpServer.update({
|
|
258
|
+
where: { id: current.id },
|
|
259
|
+
data: { url, secretNames, ...snapshotData(snapshot) },
|
|
260
|
+
});
|
|
261
|
+
audit(ctx, "update", server);
|
|
262
|
+
return textResult({ ...serverView(server), diff: diffSnapshots(snapshotOf(current), snapshot.tools) });
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
mcp.registerTool({
|
|
266
|
+
name: "refresh_mcp_server",
|
|
267
|
+
scope: "tools:write",
|
|
268
|
+
description: "Owner only: fetch the server's tools/list again and save it. Changes apply straight away: an allowed tool the server no longer lists is left out of runs and shown under missingTools by get_agent. Returns the diff (added, removed, changed) and the agents left with missing tools. With WARDBY_MCP_SERVERS=admins this needs hosts:admin.",
|
|
269
|
+
inputSchema: ID_ONLY,
|
|
270
|
+
handler: async (rawArgs, ctx) => {
|
|
271
|
+
gate(ctx, "configure");
|
|
272
|
+
const { id } = parse(IdSchema, "refresh_mcp_server arguments", rawArgs);
|
|
273
|
+
const current = await requireOwnedServer(ctx, id);
|
|
274
|
+
const snapshot = await takeSnapshot(ctx, current);
|
|
275
|
+
const server = await ctx.db.mcpServer.update({ where: { id }, data: snapshotData(snapshot) });
|
|
276
|
+
audit(ctx, "refresh", server);
|
|
277
|
+
const present = new Set(snapshot.tools.map((t) => t.name));
|
|
278
|
+
const attachments = await ctx.db.agentMcpServer.findMany({
|
|
279
|
+
where: { serverId: id },
|
|
280
|
+
include: { agent: { select: { id: true, ownerId: true } } },
|
|
281
|
+
orderBy: { createdAt: "asc" },
|
|
282
|
+
});
|
|
283
|
+
// Name only agents the caller can read; count the rest, so a refresh never reveals others' agent ids.
|
|
284
|
+
const accessOf = await agentAccessResolver(ctx);
|
|
285
|
+
const affected = attachments
|
|
286
|
+
.map((a) => ({ agent: a.agent, missingTools: a.allowedTools.filter((t) => !present.has(t)) }))
|
|
287
|
+
.filter((a) => a.missingTools.length > 0);
|
|
288
|
+
const readable = affected.filter((a) => accessOf(a.agent) !== "none");
|
|
289
|
+
const hidden = affected.length - readable.length;
|
|
290
|
+
return textResult({
|
|
291
|
+
diff: diffSnapshots(snapshotOf(current), snapshot.tools),
|
|
292
|
+
affectedAgents: readable.map((a) => ({ agentId: a.agent.id, missingTools: a.missingTools })),
|
|
293
|
+
...(hidden > 0 ? { otherAffectedAgents: hidden } : {}),
|
|
294
|
+
});
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
mcp.registerTool({
|
|
298
|
+
name: "list_mcp_servers",
|
|
299
|
+
scope: "agents:read",
|
|
300
|
+
description: "Your registered MCP servers and the ones shared with you: id, name, host, tool count, when the tool list was saved and yours (false for shared ones, which show no secret names).",
|
|
301
|
+
inputSchema: { type: "object", additionalProperties: false, properties: {} },
|
|
302
|
+
handler: async (_rawArgs, ctx) => {
|
|
303
|
+
gate(ctx, "other");
|
|
304
|
+
const sharedIds = await grantedIds(ctx.db, "mcp_server", ctx.principal.id, "read");
|
|
305
|
+
const rows = await ctx.db.mcpServer.findMany({
|
|
306
|
+
where: { OR: [{ ownerId: ctx.principal.id }, { id: { in: sharedIds } }] },
|
|
307
|
+
orderBy: [{ name: "asc" }, { id: "asc" }],
|
|
308
|
+
});
|
|
309
|
+
return textResult({
|
|
310
|
+
servers: rows.map((s) => ({
|
|
311
|
+
id: s.id,
|
|
312
|
+
name: s.name,
|
|
313
|
+
host: new URL(s.url).hostname,
|
|
314
|
+
ownerId: s.ownerId,
|
|
315
|
+
toolCount: snapshotOf(s).length,
|
|
316
|
+
snapshotAt: s.snapshotAt,
|
|
317
|
+
yours: s.ownerId === ctx.principal.id,
|
|
318
|
+
// Secret names stay with the owner.
|
|
319
|
+
...(s.ownerId === ctx.principal.id ? { secretNames: s.secretNames } : {}),
|
|
320
|
+
})),
|
|
321
|
+
});
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
mcp.registerTool({
|
|
325
|
+
name: "get_mcp_server",
|
|
326
|
+
scope: "agents:read",
|
|
327
|
+
description: "One of your MCP servers, or one shared with you (read or higher), with its full saved tool list (name, description, inputSchema, annotations). Secret names show for the owner only.",
|
|
328
|
+
inputSchema: ID_ONLY,
|
|
329
|
+
handler: async (rawArgs, ctx) => {
|
|
330
|
+
gate(ctx, "other");
|
|
331
|
+
const { id } = parse(IdSchema, "get_mcp_server arguments", rawArgs);
|
|
332
|
+
const server = await requireServerAccess(ctx, id, "read");
|
|
333
|
+
const view = serverView(server);
|
|
334
|
+
const yours = server.ownerId === ctx.principal.id;
|
|
335
|
+
// Secret names and the full URL (a query string can carry a token) stay with the owner.
|
|
336
|
+
const { secretNames: _secretNames, url: _url, ...shared } = view;
|
|
337
|
+
void _secretNames;
|
|
338
|
+
void _url;
|
|
339
|
+
return textResult({
|
|
340
|
+
...(yours ? view : { ...shared, host: new URL(server.url).hostname }),
|
|
341
|
+
yours,
|
|
342
|
+
ownerId: server.ownerId,
|
|
343
|
+
tools: snapshotOf(server),
|
|
344
|
+
});
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
mcp.registerTool({
|
|
348
|
+
name: "delete_mcp_server",
|
|
349
|
+
scope: "tools:write",
|
|
350
|
+
description: "Owner only: delete an MCP server. It is detached from every agent, including agents others attached it to through a grant. Allowed even when WARDBY_MCP_SERVERS=off, so cleanup stays possible.",
|
|
351
|
+
inputSchema: ID_ONLY,
|
|
352
|
+
handler: async (rawArgs, ctx) => {
|
|
353
|
+
gate(ctx, "cleanup");
|
|
354
|
+
const { id } = parse(IdSchema, "delete_mcp_server arguments", rawArgs);
|
|
355
|
+
const server = await requireOwnedServer(ctx, id);
|
|
356
|
+
await ctx.db.$transaction(async (tx) => {
|
|
357
|
+
await tx.mcpServer.delete({ where: { id } });
|
|
358
|
+
// Grants have no foreign key to the server.
|
|
359
|
+
await deleteGrantsFor(tx, "mcp_server", id);
|
|
360
|
+
});
|
|
361
|
+
audit(ctx, "delete", server);
|
|
362
|
+
return textResult({ deleted: id });
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
mcp.registerTool({
|
|
366
|
+
name: "attach_mcp_server",
|
|
367
|
+
scope: "tools:write",
|
|
368
|
+
description: "Agent owner only: let an agent (native or coding) call the named tools of one of your MCP servers, or of one shared with you at use or higher (its tools then run with the owner's credentials). allowedTools are exact names from the saved tool list (no wildcards); the agent sees each as <server name>__<tool name>. callTimeoutMs (per call, default 30000) is capped by WARDBY_TOOL_MAX_TIMEOUT_MS. Re-attaching replaces the allowlist and time limit. Coding agents get the tools as mcp__wardby_mcp__<name>; Codex agents can use only tools the server marks read-only (readOnlyHint) in the saved tool list.",
|
|
369
|
+
inputSchema: {
|
|
370
|
+
type: "object",
|
|
371
|
+
additionalProperties: false,
|
|
372
|
+
required: ["agentId", "serverId", "allowedTools"],
|
|
373
|
+
properties: {
|
|
374
|
+
agentId: { type: "string" },
|
|
375
|
+
serverId: { type: "string" },
|
|
376
|
+
allowedTools: { type: "array", items: { type: "string" } },
|
|
377
|
+
callTimeoutMs: { type: "integer" },
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
handler: async (rawArgs, ctx) => {
|
|
381
|
+
gate(ctx, "other");
|
|
382
|
+
const input = parse(AttachSchema, "attach_mcp_server arguments", rawArgs);
|
|
383
|
+
const ceiling = loadToolMaxTimeoutMs();
|
|
384
|
+
if (input.callTimeoutMs !== undefined &&
|
|
385
|
+
(input.callTimeoutMs < MIN_CALL_TIMEOUT_MS || input.callTimeoutMs > ceiling)) {
|
|
386
|
+
throw new McpError(400, `callTimeoutMs must be at least ${MIN_CALL_TIMEOUT_MS} and at most ${ceiling} (WARDBY_TOOL_MAX_TIMEOUT_MS).`);
|
|
387
|
+
}
|
|
388
|
+
const duplicates = input.allowedTools.filter((t, i) => input.allowedTools.indexOf(t) !== i);
|
|
389
|
+
if (duplicates.length > 0)
|
|
390
|
+
throw new McpError(400, `allowedTools lists "${duplicates[0]}" more than once.`);
|
|
391
|
+
// Bounded retry: a concurrent grant change or make_owner on the same rows aborts one side.
|
|
392
|
+
await withSerializableRetry(() => ctx.db.$transaction(async (tx) => {
|
|
393
|
+
await preferIndexScans(tx);
|
|
394
|
+
const { agent } = await assertAgentAccess(ctx, await tx.agent.findUnique({ where: { id: input.agentId } }), input.agentId, "read", tx);
|
|
395
|
+
// An attachment grants capabilities (the server's secrets act for the agent): strict owner only.
|
|
396
|
+
await requireBindable(ctx, agent, tx);
|
|
397
|
+
const server = await requireServerAccess(ctx, input.serverId, "use", tx);
|
|
398
|
+
const known = new Set(snapshotOf(server).map((t) => t.name));
|
|
399
|
+
const unknown = input.allowedTools.filter((t) => !known.has(t));
|
|
400
|
+
if (unknown.length > 0) {
|
|
401
|
+
throw new McpError(400, `Not in MCP server "${server.name}"'s saved tool list: ${unknown.join(", ")}. Run refresh_mcp_server if the server added them.`);
|
|
402
|
+
}
|
|
403
|
+
if (agent.kind === "coding") {
|
|
404
|
+
const profile = await tx.codingAgentProfile.findUnique({
|
|
405
|
+
where: { agentId: agent.id },
|
|
406
|
+
select: { provider: true },
|
|
407
|
+
});
|
|
408
|
+
// Fails closed: a coding agent with no profile, or any provider but claude-code, is Codex here.
|
|
409
|
+
if (isCodexCoding(profile?.provider)) {
|
|
410
|
+
const byName = new Map(snapshotOf(server).map((t) => [t.name, t]));
|
|
411
|
+
const writer = input.allowedTools.find((t) => !isMarkedReadOnly(byName.get(t)));
|
|
412
|
+
if (writer !== undefined) {
|
|
413
|
+
throw new McpError(400, `Codex agents can use only tools the server marks read-only (${writer} isn't).`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
const exposed = await mapped(async () => input.allowedTools.map((t) => exposedToolName(server.name, t)));
|
|
418
|
+
await assertNoClash(tx, agent.id, server.id, exposed);
|
|
419
|
+
const fields = { allowedTools: input.allowedTools, callTimeoutMs: input.callTimeoutMs ?? null };
|
|
420
|
+
await tx.agentMcpServer.upsert({
|
|
421
|
+
where: { agentId_serverId: { agentId: agent.id, serverId: server.id } },
|
|
422
|
+
create: { agentId: agent.id, serverId: server.id, attachedById: ctx.principal.id, ...fields },
|
|
423
|
+
update: { attachedById: ctx.principal.id, ...fields },
|
|
424
|
+
});
|
|
425
|
+
}, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }));
|
|
426
|
+
return textResult({ attached: true });
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
mcp.registerTool({
|
|
430
|
+
name: "detach_mcp_server",
|
|
431
|
+
scope: "tools:write",
|
|
432
|
+
description: "Agent owner only: remove an MCP server's tools from an agent. Allowed even when WARDBY_MCP_SERVERS=off, so cleanup stays possible.",
|
|
433
|
+
inputSchema: {
|
|
434
|
+
type: "object",
|
|
435
|
+
additionalProperties: false,
|
|
436
|
+
required: ["agentId", "serverId"],
|
|
437
|
+
properties: { agentId: { type: "string" }, serverId: { type: "string" } },
|
|
438
|
+
},
|
|
439
|
+
handler: async (rawArgs, ctx) => {
|
|
440
|
+
gate(ctx, "cleanup");
|
|
441
|
+
const input = parse(DetachSchema, "detach_mcp_server arguments", rawArgs);
|
|
442
|
+
await requireAgentAccess(ctx, input.agentId, "owner");
|
|
443
|
+
const { count } = await ctx.db.agentMcpServer.deleteMany({
|
|
444
|
+
where: { agentId: input.agentId, serverId: input.serverId },
|
|
445
|
+
});
|
|
446
|
+
return textResult({ detached: count > 0 });
|
|
447
|
+
},
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* 409 naming the first exposed name that clashes with a built-in, an attached tool or another MCP attachment.
|
|
452
|
+
* Exported for tests: no valid server and tool name maps to a built-in repository tool name.
|
|
453
|
+
*/
|
|
454
|
+
export async function assertNoClash(tx, agentId, serverId, exposed) {
|
|
455
|
+
const clash = (name, why) => new McpError(409, `The tool name "${name}" clashes with ${why} on agent "${agentId}".`);
|
|
456
|
+
const seen = new Set();
|
|
457
|
+
for (const name of exposed) {
|
|
458
|
+
if (seen.has(name))
|
|
459
|
+
throw clash(name, "another of the allowed tools (both map to this name)");
|
|
460
|
+
seen.add(name);
|
|
461
|
+
const reserved = reservedToolNameReason(name);
|
|
462
|
+
if (reserved)
|
|
463
|
+
throw new McpError(409, `The tool name "${name}" clashes with a built-in: ${reserved}`);
|
|
464
|
+
if (REVIEW_HOST_TOOL_NAMES.has(name))
|
|
465
|
+
throw clash(name, "a built-in repository tool");
|
|
466
|
+
}
|
|
467
|
+
const attached = await tx.agentTool.findMany({ where: { agentId }, select: { tool: { select: { name: true } } } });
|
|
468
|
+
for (const { tool } of attached)
|
|
469
|
+
if (seen.has(tool.name))
|
|
470
|
+
throw clash(tool.name, "an attached tool");
|
|
471
|
+
const others = await tx.agentMcpServer.findMany({
|
|
472
|
+
where: { agentId, serverId: { not: serverId } },
|
|
473
|
+
include: { server: { select: { name: true } } },
|
|
474
|
+
});
|
|
475
|
+
for (const other of others) {
|
|
476
|
+
for (const name of exposedNames(other.server.name, other.allowedTools)) {
|
|
477
|
+
if (seen.has(name))
|
|
478
|
+
throw clash(name, `a tool of MCP server "${other.server.name}"`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
package/dist/mcp/tools/memory.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { requireAgentAccess } from "../auth/access.js";
|
|
2
2
|
import { textResult } from "./text-result.js";
|
|
3
|
+
import { SecretInValueError, SecretCheckUnavailableError } from "../../core/secret-guard.js";
|
|
4
|
+
import { McpError } from "../errors.js";
|
|
3
5
|
export function registerMemoryTools(mcp) {
|
|
4
6
|
mcp.registerTool({
|
|
5
7
|
name: "get_agent_memory",
|
|
@@ -39,7 +41,15 @@ export function registerMemoryTools(mcp) {
|
|
|
39
41
|
},
|
|
40
42
|
handler: async (args, ctx) => {
|
|
41
43
|
await requireAgentAccess(ctx, args.agentId, "owner");
|
|
42
|
-
|
|
44
|
+
try {
|
|
45
|
+
await ctx.providers.memory.set(args.agentId, args.key, args.content);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (err instanceof SecretInValueError || err instanceof SecretCheckUnavailableError) {
|
|
49
|
+
throw new McpError(400, err.message);
|
|
50
|
+
}
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
43
53
|
return textResult({ ok: true });
|
|
44
54
|
},
|
|
45
55
|
});
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* for the whole deployment, no per-user OAuth), so link/unlink/test need
|
|
11
11
|
* agents:admin with the admin role, and the approver is stamped on the
|
|
12
12
|
* link. Exactly one of projectKey/agentId is the link's subject (enforced
|
|
13
|
-
* again by a DB CHECK constraint); `events` narrows which of the
|
|
13
|
+
* again by a DB CHECK constraint); `events` narrows which of the
|
|
14
14
|
* workflow event kinds post to it (empty/omitted = all); private Slack
|
|
15
15
|
* channels always need /invite @<app> before the bot can see or post to
|
|
16
16
|
* them. See docs/private/2026-10-08-slack-workflow-notifications-design.md §8.
|
|
@@ -52,7 +52,7 @@ export function registerNotificationChannelTools(mcp) {
|
|
|
52
52
|
"matches events for issues in that project; an agent link matches events for that agent's runs. " +
|
|
53
53
|
"channel is the Slack channel id (C… for public, G… for private), never a #name — find it in the channel's " +
|
|
54
54
|
"details in Slack. Private channels always need /invite @<app> before the bot can see or post to them. " +
|
|
55
|
-
"events narrows which of the
|
|
55
|
+
"events narrows which of the workflow event kinds post to this link; empty or omitted means all. " +
|
|
56
56
|
"includeCost appends the run's spend line to messages. Re-linking the same channel + subject replaces events and " +
|
|
57
57
|
"includeCost and clears any previously recorded delivery error — always send the full desired state.",
|
|
58
58
|
inputSchema: {
|