@wardby/cli 0.7.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 +6 -0
- package/dist/claude-coding-worker/driver.d.ts +12 -0
- package/dist/claude-coding-worker/driver.js +29 -7
- package/dist/claude-coding-worker/main.js +5 -1
- package/dist/claude-coding-worker/sdk.js +17 -1
- 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 +2 -1
- package/dist/cli.js +47 -3
- package/dist/coding/code-host.d.ts +16 -0
- package/dist/coding/code-host.js +60 -0
- package/dist/coding/mcp-token.d.ts +12 -0
- package/dist/coding/mcp-token.js +26 -0
- package/dist/coding/protocol.js +2 -0
- package/dist/coding/redact.js +6 -1
- package/dist/coding/transcript/recorder.d.ts +5 -4
- package/dist/coding/transcript/recorder.js +1 -1
- package/dist/coding-worker/debug-trace.d.ts +3 -1
- package/dist/coding-worker/debug-trace.js +4 -2
- package/dist/coding-worker/driver.js +8 -1
- 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/types.d.ts +4 -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/test-simulators.d.ts +10 -0
- package/dist/config/test-simulators.js +28 -0
- package/dist/config/tool-timeout.d.ts +1 -0
- package/dist/config/tool-timeout.js +18 -0
- package/dist/core/coding-mcp.d.ts +36 -0
- package/dist/core/coding-mcp.js +253 -0
- package/dist/core/coding-repository.d.ts +46 -0
- package/dist/core/coding-repository.js +92 -0
- package/dist/core/delegation-slots.d.ts +27 -0
- package/dist/core/delegation-slots.js +44 -0
- package/dist/core/dispatch.d.ts +6 -2
- package/dist/core/dispatch.js +36 -11
- package/dist/core/error-code.js +1 -0
- package/dist/core/grants.d.ts +28 -3
- package/dist/core/grants.js +46 -4
- package/dist/core/host-events.js +7 -3
- package/dist/core/host-status.js +2 -2
- package/dist/core/issue-status.js +4 -3
- package/dist/core/mark-ready.d.ts +1 -1
- package/dist/core/mark-ready.js +1 -1
- 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/merge-order-check.js +38 -19
- package/dist/core/notification-dispatcher.js +2 -1
- package/dist/core/related-pull-requests.js +26 -10
- package/dist/core/review-fix.js +2 -2
- package/dist/core/review-host-tools.js +3 -1
- package/dist/core/runner.d.ts +66 -16
- package/dist/core/runner.js +281 -73
- package/dist/core/secret-broker-config.d.ts +2 -0
- package/dist/core/secret-broker-config.js +1 -1
- package/dist/core/secret-guard.d.ts +5 -2
- package/dist/core/secret-guard.js +22 -7
- 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/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-run-events.js +2 -1
- package/dist/generated/prisma/browser.d.ts +31 -0
- package/dist/generated/prisma/client.d.ts +31 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +50 -50
- package/dist/generated/prisma/internal/class.d.ts +66 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +530 -1
- package/dist/generated/prisma/internal/prismaNamespace.js +75 -2
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +79 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +75 -2
- package/dist/generated/prisma/models/Agent.d.ts +271 -0
- 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 +40 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +0 -7
- package/dist/generated/prisma/models/CodingProxySession.d.ts +119 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +76 -1
- 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/McpServer.d.ts +1500 -0
- package/dist/generated/prisma/models/McpServer.js +1 -0
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +39 -1
- package/dist/generated/prisma/models/Principal.d.ts +167 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
- 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 +6 -0
- package/dist/help/search.js +12 -3
- package/dist/help-index.json +719 -47
- package/dist/import/create.js +16 -1
- package/dist/import/neutral-schema.d.ts +1 -0
- package/dist/import/neutral-schema.js +2 -0
- package/dist/mcp/auth/grants-cli.d.ts +6 -4
- package/dist/mcp/auth/grants-cli.js +42 -3
- package/dist/mcp/auth/resource-server.d.ts +3 -1
- package/dist/mcp/auth/resource-server.js +17 -2
- package/dist/mcp/context.d.ts +3 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/tools/agents.js +100 -15
- package/dist/mcp/tools/grants.js +66 -28
- 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/repositories.js +50 -10
- package/dist/mcp/tools/runs.js +178 -18
- 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 +38 -4
- package/dist/mcp/tools/tools.d.ts +6 -4
- package/dist/mcp/tools/tools.js +40 -8
- 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/webhooks/ingress.js +10 -0
- package/dist/native-worker/gateway-server.d.ts +14 -0
- package/dist/native-worker/gateway-server.js +28 -7
- package/dist/native-worker/gateway.d.ts +2 -0
- package/dist/native-worker/gateway.js +5 -1
- package/dist/native-worker/http-server.d.ts +4 -0
- package/dist/native-worker/http-server.js +51 -0
- package/dist/native-worker/ledger.d.ts +6 -2
- package/dist/native-worker/ledger.js +5 -4
- package/dist/native-worker/protocol.d.ts +1 -0
- package/dist/native-worker/protocol.js +4 -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/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 +2 -0
- package/dist/providers/coding-proxy/memory-ledger.js +15 -0
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +1 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +30 -2
- package/dist/providers/coding-proxy/proxy.d.ts +7 -1
- package/dist/providers/coding-proxy/proxy.js +134 -34
- package/dist/providers/coding-proxy/runtime.d.ts +6 -0
- package/dist/providers/coding-proxy/runtime.js +32 -1
- package/dist/providers/coding-proxy/server.d.ts +3 -0
- package/dist/providers/coding-proxy/server.js +10 -0
- package/dist/providers/coding-proxy/types.d.ts +13 -0
- package/dist/providers/executor/composition.js +5 -0
- package/dist/providers/executor/container.d.ts +33 -1
- package/dist/providers/executor/container.js +76 -7
- 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/jobs/docker-isolation.d.ts +2 -2
- package/dist/providers/jobs/docker-isolation.js +30 -8
- package/dist/providers/jobs/docker.d.ts +8 -0
- package/dist/providers/jobs/docker.js +33 -9
- package/dist/providers/jobs/kubernetes-isolation.d.ts +3 -1
- package/dist/providers/jobs/kubernetes-isolation.js +15 -2
- package/dist/providers/jobs/kubernetes.d.ts +5 -0
- package/dist/providers/jobs/kubernetes.js +6 -1
- package/dist/providers/jobs/types.d.ts +6 -0
- package/dist/providers/review-host/types.d.ts +6 -4
- package/dist/providers/review-host/types.js +1 -1
- package/dist/providers/vcs/git.d.ts +6 -2
- package/dist/providers/vcs/git.js +15 -4
- package/dist/providers/vcs/github.d.ts +2 -71
- package/dist/providers/vcs/github.js +8 -11
- package/dist/providers/vcs/index.d.ts +1 -1
- package/dist/providers/vcs/index.js +1 -1
- package/dist/providers/vcs/remote.d.ts +4 -0
- package/dist/providers/vcs/remote.js +7 -1
- package/dist/providers/vcs/routing.d.ts +12 -6
- package/dist/providers/vcs/routing.js +21 -6
- package/dist/providers/vcs/types.d.ts +71 -3
- package/dist/quickstart/index.d.ts +5 -0
- package/dist/quickstart/index.js +21 -0
- 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/host-functions.d.ts +4 -0
- package/dist/sandbox/host-functions.js +7 -2
- 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 +1 -1
- 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/viewer/graph.js +2 -1
- package/dist/wardby-bin.js +5 -0
- package/docs/README.md +11 -1
- package/docs/agent-recipes.md +37 -4
- package/docs/architecture-runtime.md +1 -1
- package/docs/claude-code-plugin.md +164 -0
- package/docs/code-review-agents.md +6 -0
- package/docs/coding-agent-setup.md +77 -1
- package/docs/coding-worker-byo-images.md +4 -2
- package/docs/coding-worker-isolation.md +78 -7
- package/docs/debugging-agent-runs.md +242 -0
- package/docs/getting-started-gke.md +5 -4
- package/docs/getting-started-identity-provider.md +43 -37
- package/docs/getting-started.md +8 -0
- package/docs/host-providers.md +294 -0
- package/docs/mcp-servers.md +254 -0
- package/docs/native-sandbox.md +25 -9
- package/docs/security-deployment.md +110 -31
- package/docs/tool-secrets.md +3 -0
- package/docs/viewer-api.md +6 -0
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +4 -0
- package/help/agent-recipes.md +33 -2
- package/help/brokered-secrets.md +3 -0
- package/help/build-claude-code-image.md +1 -1
- package/help/claude-code-run-pane.md +40 -0
- package/help/errors/coding-mcp-pins-unavailable.md +35 -0
- package/help/errors/database-auth-invalid.md +1 -1
- 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/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 +1 -1
- 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-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 +1 -1
- package/help/errors/native-sandbox-worker-lost.md +1 -1
- package/help/errors/native-sandbox-worker-unready.md +1 -1
- package/help/errors/repository-not-listed.md +36 -0
- package/help/errors/repository-required.md +36 -0
- package/help/errors/tool-timeout.md +38 -0
- package/help/host-providers.md +40 -0
- package/help/identity-and-access.md +4 -1
- package/help/mcp-servers.md +73 -0
- package/help/mcp.md +7 -2
- package/help/native-capabilities.md +27 -1
- package/help/native-sandbox.md +1 -1
- package/help/operating-agents.md +16 -0
- package/help/related-pull-requests.md +7 -3
- package/help/repo-instructions-and-skills.md +3 -1
- package/help/resume-runs-locally.md +3 -0
- package/help/stop-run.md +1 -1
- package/help/troubleshooting/coding-workers.md +9 -1
- package/help/troubleshooting/debugging-agent-runs.md +29 -0
- package/package.json +2 -1
- 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 +159 -14
- package/scripts/git-askpass.sh +1 -1
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# Remote MCP servers for native and coding agents
|
|
2
|
+
|
|
3
|
+
A native, Claude Code or Codex agent can call the tools of a remote MCP server. You register the
|
|
4
|
+
server once (its HTTPS URL plus your brokered secrets), Wardby saves the
|
|
5
|
+
server's tool list, and you attach an allowlisted subset of those tools to
|
|
6
|
+
an agent. A native agent sees each tool as `<server name>__<tool name>`; coding agents see
|
|
7
|
+
them as described in [Coding agents](#coding-agents).
|
|
8
|
+
|
|
9
|
+
`WARDBY_MCP_SERVERS` decides who may register servers: `owners` (the
|
|
10
|
+
default, anyone), `admins` (registering, updating and refreshing need
|
|
11
|
+
`hosts:admin`) or `off` (every tool below is refused except
|
|
12
|
+
`detach_mcp_server` and `delete_mcp_server`, so cleanup stays possible, and
|
|
13
|
+
attached servers' tools are left out of runs).
|
|
14
|
+
|
|
15
|
+
The tools below need the `tools:write` scope to change servers and
|
|
16
|
+
attachments and `agents:read` to list and get them.
|
|
17
|
+
|
|
18
|
+
## Tools
|
|
19
|
+
|
|
20
|
+
| Tool | Who | What it does |
|
|
21
|
+
| --------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
22
|
+
| `register_mcp_server` | anyone (see mode) | Registers a server from `name`, `url` (e.g. `https://mcp.example.com/mcp`) and `secretNames`; saves its tool list. |
|
|
23
|
+
| `update_mcp_server` | the server's owner | Changes the URL or secret names, saves a fresh tool list and returns what changed. |
|
|
24
|
+
| `refresh_mcp_server` | the server's owner | Saves a fresh tool list straight away; returns added, removed and changed tools and the agents left missing tools. |
|
|
25
|
+
| `list_mcp_servers` | anyone | Your servers and those shared with you: id, name, host, tool count, saved-at, `yours`. |
|
|
26
|
+
| `get_mcp_server` | owner, or `read`+ | One server with its full saved tool list (secret names and URL only for the owner). |
|
|
27
|
+
| `delete_mcp_server` | the server's owner | Deletes a server and detaches it from every agent. Works when the mode is `off`. |
|
|
28
|
+
| `attach_mcp_server` | agent's owner; `use`+ | Lets a native or coding agent call the named tools (`allowedTools`, exact names) with an optional `callTimeoutMs`. |
|
|
29
|
+
| `detach_mcp_server` | the agent's owner | Removes a server's tools from an agent. Works when the mode is `off`. |
|
|
30
|
+
|
|
31
|
+
`get_agent` shows each attached server under `mcpServers`: the server's `serverId`
|
|
32
|
+
and name, the allowed tools, `callTimeoutMs`, the exposed tool names and any allowed tools the server no
|
|
33
|
+
longer lists (`missingTools`). Anyone with read access on the agent sees this.
|
|
34
|
+
It never includes URLs, secret names or values, or saved tool lists.
|
|
35
|
+
|
|
36
|
+
## Create a secret for the server
|
|
37
|
+
|
|
38
|
+
Servers are authenticated with [brokered secrets](tool-secrets.md): Wardby adds
|
|
39
|
+
the value to every request to the server's host and nobody, including the
|
|
40
|
+
model, can read it back. Create the secret, then set its broker config with
|
|
41
|
+
`set_secret_broker` so it is limited to the server's host. For a bearer token:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"hosts": ["mcp.example.com"],
|
|
46
|
+
"placement": { "kind": "header", "name": "Authorization", "format": "Bearer {value}" }
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
A server that wants two headers needs two secrets, each with its own
|
|
51
|
+
placement (for example `X-Api-Key` with `format: "{value}"`, and
|
|
52
|
+
`X-Workspace` the same way); name both in `secretNames` (at most 8 names, each up to 1024 characters). The URL itself can't
|
|
53
|
+
carry credentials: a username, password or fragment is refused.
|
|
54
|
+
|
|
55
|
+
## Register, read the tool list, attach
|
|
56
|
+
|
|
57
|
+
1. `register_mcp_server` with `name` (1-32 characters: lower-case letters,
|
|
58
|
+
digits, `_` or `-`), `url` (`https://mcp.example.com/mcp`: HTTPS only,
|
|
59
|
+
default port) and `secretNames`. Wardby calls the server's `tools/list`
|
|
60
|
+
and saves the result. A secret that is missing, not brokered, or not
|
|
61
|
+
brokered to the URL's host is refused.
|
|
62
|
+
2. `get_mcp_server` shows the saved tools: name, description, input schema and
|
|
63
|
+
the server's annotations.
|
|
64
|
+
3. `attach_mcp_server` with the agent, the server and `allowedTools`: exact
|
|
65
|
+
tool names from the saved list, at least one, no wildcards. Attaching
|
|
66
|
+
replaces the agent's earlier allowlist and time limit for that server.
|
|
67
|
+
Native, Claude Code and Codex agents can attach a server (see [Coding agents](#coding-agents)).
|
|
68
|
+
|
|
69
|
+
The agent sees each tool as `<server name>__<tool name>`, with any character
|
|
70
|
+
outside letters, digits, `_` and `-` changed to `_`; the result must be at
|
|
71
|
+
most 64 characters. The description starts with `From MCP server <server name>: `.
|
|
72
|
+
Attaching is refused if the name clashes with another tool on the agent
|
|
73
|
+
(attached, another MCP tool, or a built-in name).
|
|
74
|
+
|
|
75
|
+
## Coding agents
|
|
76
|
+
|
|
77
|
+
A Claude Code or Codex agent can use attached servers too. Attach them the same way, with
|
|
78
|
+
`attach_mcp_server`. The tools reach the run like this:
|
|
79
|
+
|
|
80
|
+
1. The worker calls the coding proxy's `/mcp` route with a per-run MCP token (`rmt_…`, in the
|
|
81
|
+
worker's `WARDBY_MCP_TOKEN`). Workers still reach only the proxy.
|
|
82
|
+
2. The proxy forwards the request to the native gateway's `/coding-mcp` route. The proxy never sees
|
|
83
|
+
a server's URL or secrets. The gateway checks the token again, checks the live attachment and
|
|
84
|
+
runs the call, and removes secret values from the result before it leaves.
|
|
85
|
+
|
|
86
|
+
The token belongs to one run: it works only on `/mcp`, only while the run is active and before its
|
|
87
|
+
deadline, and only its hash is stored.
|
|
88
|
+
|
|
89
|
+
- **Claude Code agents** see each tool as `mcp__wardby_mcp__<server name>__<tool name>` and may use
|
|
90
|
+
any allowed tool. The 64-character limit on `<server name>__<tool name>` is the same as for
|
|
91
|
+
native agents; the prefix adds no other limit.
|
|
92
|
+
- **Codex agents may use only tools the server marks `readOnlyHint: true`.** Wardby enforces this
|
|
93
|
+
when you attach (an allowlist with another tool is refused), when a run loads its tools (a tool
|
|
94
|
+
whose saved annotations no longer say read-only, for example after `refresh_mcp_server`, is left
|
|
95
|
+
out) and on every call. The reason is that repository code running in a Codex run can read the
|
|
96
|
+
run's MCP token, so only tools that don't change anything are safe to give it. `readOnlyHint` is
|
|
97
|
+
the server's own claim, which Wardby can't verify. The allowlist stays your control: allow only
|
|
98
|
+
tools you trust to be read-only.
|
|
99
|
+
|
|
100
|
+
A run follows the provider it was started with, even if the agent's provider changes before the
|
|
101
|
+
run launches. A coding agent with no coding profile is treated as Codex when you attach.
|
|
102
|
+
|
|
103
|
+
- **Switching an agent to Codex.** When `update_agent` makes an agent a Codex agent (changing
|
|
104
|
+
`codingProfile.provider` to `codex`, or making a native agent a coding agent, which uses Codex by
|
|
105
|
+
default) and some of its attached tools aren't marked read-only, the change still goes ahead and
|
|
106
|
+
the result's `warnings` names those tools: "These MCP tools aren't read-only and won't be
|
|
107
|
+
available to Codex runs: …". They stay attached but Codex runs don't get them. Detach them, or
|
|
108
|
+
re-attach the server with only read-only tools, to remove the warning's cause.
|
|
109
|
+
- **Call limit.** A run may make `WARDBY_MCP_MAX_CALLS_PER_RUN` calls (default `100`). Every call
|
|
110
|
+
counts, whatever its outcome. Past the limit a call returns
|
|
111
|
+
[`mcp_call_limit`](../help/errors/mcp-call-limit.md); the run goes on.
|
|
112
|
+
- **Proxy setting.** The coding proxy needs `WARDBY_MCP_GATEWAY_URL`, the native gateway's base URL
|
|
113
|
+
(the kind and GKE manifests set it). Without it `/mcp` answers `503` with
|
|
114
|
+
[`mcp_unavailable`](../help/errors/mcp-unavailable.md) and coding agents get no MCP tools. See
|
|
115
|
+
[Remote MCP servers](security-deployment.md#remote-mcp-servers) for the variables.
|
|
116
|
+
- **Worker images.** MCP for coding agents needs this release's Claude worker image and a new Codex
|
|
117
|
+
driver image. An older image ignores the token and the agent gets no MCP tools; the run does not
|
|
118
|
+
fail. Update the images together with the server.
|
|
119
|
+
- **Repository configuration.** A repository's own MCP configuration (such as `.mcp.json`) is still
|
|
120
|
+
never loaded; the attached servers are the only MCP tools a coding run has.
|
|
121
|
+
- **Codex models that use tool search** load MCP tools on demand: Codex sends a client-side
|
|
122
|
+
`tool_search` tool and adds the matching MCP tools to the conversation when the model searches.
|
|
123
|
+
This needs this release's coding proxy; an older proxy refuses those models' requests with
|
|
124
|
+
`openai_tool_not_allowed:tool_search`, MCP or not.
|
|
125
|
+
|
|
126
|
+
Time limits and the other rules in this guide apply to coding agents too. See
|
|
127
|
+
[Coding worker isolation](coding-worker-isolation.md#remote-mcp-tools) for the security notes.
|
|
128
|
+
|
|
129
|
+
## Time limits
|
|
130
|
+
|
|
131
|
+
Each call has `callTimeoutMs` (default `30000`, set on `attach_mcp_server`).
|
|
132
|
+
It must be at least `1000` and can't exceed `WARDBY_TOOL_MAX_TIMEOUT_MS`; a call runs with the lower of
|
|
133
|
+
the two, and never past the run's own deadline. `stop_run` aborts a call in
|
|
134
|
+
flight. A call that runs out of time returns `mcp_call_timeout` to the model
|
|
135
|
+
and the run goes on.
|
|
136
|
+
|
|
137
|
+
A coding agent's calls have one more limit: the coding proxy gives up on a forwarded call after 5
|
|
138
|
+
minutes, whatever `WARDBY_TOOL_MAX_TIMEOUT_MS` and `callTimeoutMs` say. The call then fails with
|
|
139
|
+
[`mcp_unavailable`](../help/errors/mcp-unavailable.md) (`502`), the gateway stops the call, and it
|
|
140
|
+
still counts against the run's call limit. A run that has been stopped or cancelled can't start new
|
|
141
|
+
calls: its token is refused with `401`.
|
|
142
|
+
|
|
143
|
+
## Refreshing and changes
|
|
144
|
+
|
|
145
|
+
`refresh_mcp_server` (and `update_mcp_server`) fetch the tool list again and
|
|
146
|
+
apply it at once. The reply lists tools added, removed and changed
|
|
147
|
+
(description or schema). A removed tool that an agent allows is dropped from
|
|
148
|
+
that agent's runs and shows under `missingTools` in `get_agent`; nothing
|
|
149
|
+
needs re-attaching if the server brings it back and you refresh again. A
|
|
150
|
+
tool the server newly adds is not available to any agent until you attach it.
|
|
151
|
+
|
|
152
|
+
## What a call does
|
|
153
|
+
|
|
154
|
+
Each call opens its own session: `initialize`, `notifications/initialized`,
|
|
155
|
+
`tools/call`, then a `DELETE` to end it. Because every call gets a fresh
|
|
156
|
+
session, a server that keeps state between calls in one session won't see
|
|
157
|
+
that state on the next call. Wardby checks on every call that the tool is
|
|
158
|
+
still attached and still in the saved list, and that the agent's owner still
|
|
159
|
+
owns the server or holds `use` on it; the call uses the server's current URL
|
|
160
|
+
and secrets. Arguments that aren't a JSON object return `invalid_arguments`
|
|
161
|
+
without calling the server. Text returned to the model is cut at 100,000
|
|
162
|
+
characters, with a note.
|
|
163
|
+
|
|
164
|
+
Wardby answers none of a server's own requests (sampling, elicitation,
|
|
165
|
+
roots). Notifications in a reply are ignored. A reply that carries only a
|
|
166
|
+
request from the server, and no answer to Wardby's request, fails the call
|
|
167
|
+
with `mcp_server_error`.
|
|
168
|
+
|
|
169
|
+
One log line per call records the run id, agent id, server id, tool,
|
|
170
|
+
outcome, duration and result size, never the arguments, the response or the
|
|
171
|
+
URL. Secret values are removed from results, errors and logs.
|
|
172
|
+
|
|
173
|
+
## Not supported
|
|
174
|
+
|
|
175
|
+
stdio servers, OAuth to a server (use a header secret), MCP resources,
|
|
176
|
+
prompts and sampling.
|
|
177
|
+
|
|
178
|
+
## Trust
|
|
179
|
+
|
|
180
|
+
A server's results are untrusted input to the model, like any tool result. The
|
|
181
|
+
allowlist is the control: attach only the tools an agent needs. A server's
|
|
182
|
+
annotations (read-only, destructive and so on) are hints from the server, not
|
|
183
|
+
something Wardby can verify. The one place Wardby acts on a hint is Codex coding
|
|
184
|
+
agents, which may use only tools marked `readOnlyHint: true` (see
|
|
185
|
+
[Coding agents](#coding-agents)).
|
|
186
|
+
|
|
187
|
+
## Sharing a server
|
|
188
|
+
|
|
189
|
+
Share a server you own with `grant_access` (`resourceType: "mcp_server"`, a
|
|
190
|
+
principal or `everyone`, level `read`, `use` or `write`; `everyone` is capped
|
|
191
|
+
at `use`). `read` lets the grantee see the server and its tool list; `use`
|
|
192
|
+
also lets them attach it to their own agents. The server's tools then run with
|
|
193
|
+
your brokered secrets, so grant `use` only to people you trust with them.
|
|
194
|
+
`write` allows nothing beyond `use`: only the owner updates, refreshes,
|
|
195
|
+
deletes or re-grants a server.
|
|
196
|
+
|
|
197
|
+
Sharing uses `grant_access` and `revoke_access`, which need the
|
|
198
|
+
`agents:write` scope; registering and attaching need `tools:write`.
|
|
199
|
+
|
|
200
|
+
An agent may use a server only while its owner owns the server or holds `use`
|
|
201
|
+
(or `write`) on it. `revoke_access`, and `grant_access` lowering a grant to
|
|
202
|
+
`read` (for a principal, or `everyone` from `use` to `read`), detach the
|
|
203
|
+
server at once from every agent whose owner can no longer use it; the reply
|
|
204
|
+
counts them under `attachmentsRemoved`. Your own agents, and agents whose
|
|
205
|
+
owner still holds `use` through another grant, keep it. Runs already going
|
|
206
|
+
lose the tools on their next call, which returns `mcp_tool_not_allowed`.
|
|
207
|
+
|
|
208
|
+
`delete_mcp_server` removes the server's tools from every agent attached to
|
|
209
|
+
it, including other owners' agents that use it through a grant, and removes
|
|
210
|
+
its grants.
|
|
211
|
+
|
|
212
|
+
When the server's secrets can't be loaded (a secret was deleted, or its
|
|
213
|
+
broker config no longer lists the server's host), the owner's own agents get
|
|
214
|
+
an `mcp_server_error` that names the secret. An agent using the server through
|
|
215
|
+
a grant gets only "The MCP server's credentials can't be used; ask its owner
|
|
216
|
+
to check it.", never the owner's secret names.
|
|
217
|
+
|
|
218
|
+
When a secret exists but the Wardby process making the call can't decrypt its
|
|
219
|
+
stored value, the call returns `mcp_server_credentials_unavailable`, and
|
|
220
|
+
`register_mcp_server`, `update_mcp_server` and `refresh_mcp_server` fail with
|
|
221
|
+
it as an HTTP 500 error. Every process that decrypts secrets (control plane,
|
|
222
|
+
scheduler, native gateway) must use the same `SECRET_APP_KEY`; if the key
|
|
223
|
+
changed, set the secret again. The owner's agents get that advice; an agent
|
|
224
|
+
using the server through a grant gets the generic message above. Each failure
|
|
225
|
+
also writes one operator `warn` log line with
|
|
226
|
+
`reason: "mcp_secret_decrypt_failed"`, the server and the secret name.
|
|
227
|
+
|
|
228
|
+
An attachment acts with the server owner's secrets. When `make_owner` gives an
|
|
229
|
+
agent a new owner, servers the new owner neither owns nor holds `use` on are
|
|
230
|
+
detached and listed under `bindingsRemoved` with `kind: "mcp_server"`.
|
|
231
|
+
`wardby grants adopt-public` and `wardby grants prune-bindings` remove them the
|
|
232
|
+
same way. An agent that holds an MCP server can't be made writable by
|
|
233
|
+
everyone.
|
|
234
|
+
|
|
235
|
+
## Troubleshooting
|
|
236
|
+
|
|
237
|
+
A failed call returns `{"error": "<code>", "message": "..."}` to the model;
|
|
238
|
+
the run goes on.
|
|
239
|
+
|
|
240
|
+
| Code | Meaning |
|
|
241
|
+
| -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
242
|
+
| [`mcp_servers_off`](../help/errors/mcp-servers-off.md) | `WARDBY_MCP_SERVERS=off`. |
|
|
243
|
+
| [`mcp_server_unreachable`](../help/errors/mcp-server-unreachable.md) | Wardby couldn't connect to the server. |
|
|
244
|
+
| [`mcp_server_auth_failed`](../help/errors/mcp-server-auth-failed.md) | The server answered 401 or 403. |
|
|
245
|
+
| [`mcp_server_credentials_unavailable`](../help/errors/mcp-server-credentials-unavailable.md) | A secret can't be decrypted: check every process's `SECRET_APP_KEY`. |
|
|
246
|
+
| [`mcp_server_error`](../help/errors/mcp-server-error.md) | Another HTTP error, a malformed reply, or the tool reported an error. |
|
|
247
|
+
| [`mcp_tool_not_allowed`](../help/errors/mcp-tool-not-allowed.md) | Detached, off the allowlist, or the owner lost `use` on the server. |
|
|
248
|
+
| [`mcp_tool_removed`](../help/errors/mcp-tool-removed.md) | The server no longer lists the tool. |
|
|
249
|
+
| [`mcp_call_timeout`](../help/errors/mcp-call-timeout.md) | The call hit its time limit or the run was stopped. |
|
|
250
|
+
| [`mcp_call_limit`](../help/errors/mcp-call-limit.md) | A coding run made more calls than `WARDBY_MCP_MAX_CALLS_PER_RUN`. |
|
|
251
|
+
| [`mcp_unavailable`](../help/errors/mcp-unavailable.md) | The coding proxy has no gateway to forward MCP calls to. |
|
|
252
|
+
|
|
253
|
+
See also [Secrets and tools](tool-secrets.md) and
|
|
254
|
+
[Remote MCP servers](security-deployment.md#remote-mcp-servers).
|
package/docs/native-sandbox.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Native sandbox
|
|
2
2
|
|
|
3
|
-
> **Requires Wardby 0.
|
|
3
|
+
> **Requires Wardby 0.6.0 or later.**
|
|
4
4
|
|
|
5
5
|
By default a native agent runs inside the Wardby server process: its turn loop
|
|
6
6
|
and any user tool code you attach execute next to the database connection, the
|
|
@@ -78,6 +78,13 @@ container to it under the alias `wardby-native-gateway`, and starts the worker
|
|
|
78
78
|
on it. When the run ends the worker, the network, and the gateway's membership
|
|
79
79
|
of it are removed.
|
|
80
80
|
|
|
81
|
+
The gateway also serves coding agents' remote MCP tools: the coding proxy
|
|
82
|
+
forwards a coding run's `/mcp` requests to the gateway's HTTP port, on the
|
|
83
|
+
`/coding-mcp` route, where the run's MCP token is checked again. Set
|
|
84
|
+
`WARDBY_MCP_GATEWAY_URL` on the coding proxy to the gateway's base URL
|
|
85
|
+
([details](security-deployment.md#remote-mcp-servers)). The proxy holds no
|
|
86
|
+
gateway credentials, and each route authenticates separately.
|
|
87
|
+
|
|
81
88
|
The gateway is stateless: all state is in Postgres. You can restart it while
|
|
82
89
|
runs are in flight; workers retry their calls. It must not be given the Docker
|
|
83
90
|
socket, because workers can reach it.
|
|
@@ -131,13 +138,15 @@ The gateway is the same Wardby build as the server, started with the
|
|
|
131
138
|
`native-gateway` command. It needs the server's database, LLM, secrets, and
|
|
132
139
|
integration settings, and **no Docker access**.
|
|
133
140
|
|
|
134
|
-
| Gateway variable
|
|
135
|
-
|
|
|
136
|
-
| `NATIVE_GATEWAY_LISTEN`
|
|
137
|
-
| `DATABASE_URL`
|
|
138
|
-
| LLM provider keys
|
|
139
|
-
| `SECRET_APP_KEY`
|
|
140
|
-
| Integration settings
|
|
141
|
+
| Gateway variable | Purpose |
|
|
142
|
+
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
143
|
+
| `NATIVE_GATEWAY_LISTEN` | `host:port` to listen on. Default `0.0.0.0:8790`. |
|
|
144
|
+
| `DATABASE_URL` | The same database the server uses. With `DATABASE_AUTH=rds-iam` the gateway also needs `DATABASE_AUTH`, `AWS_REGION` (or `DATABASE_AWS_REGION`) and the CA bundle file named by `sslrootcert` ([details](security-deployment.md#database-authentication)). |
|
|
145
|
+
| LLM provider keys | The same provider settings as the server (for example `OPENAI_API_KEY`). |
|
|
146
|
+
| `SECRET_APP_KEY` | Same value as the server, so tools can read their bound secrets or send brokered ones ([details](tool-secrets.md)). |
|
|
147
|
+
| Integration settings | The same repository-host and issue-tracker settings as the server. |
|
|
148
|
+
| `WARDBY_TOOL_MAX_TIMEOUT_MS` | Same value as the server, if you set it: the longest time limit a tool may use ([details](security-deployment.md#tool-time-limits)). |
|
|
149
|
+
| `WARDBY_MCP_MAX_CALLS_PER_RUN` | Same value as the server, if you set it: the most remote MCP tool calls one coding run may make (default `100`; [details](security-deployment.md#remote-mcp-servers)). |
|
|
141
150
|
|
|
142
151
|
For local development, the repository ships a compose overlay
|
|
143
152
|
(`deploy/local/docker-compose.native-sandbox.yml`) that runs the gateway next to
|
|
@@ -549,6 +558,12 @@ set on the gateway, not the server.
|
|
|
549
558
|
- A sandbox run has a maximum lifetime of 60 minutes. Past it the worker is
|
|
550
559
|
stopped and the run fails with `native_sandbox_deadline_exceeded`.
|
|
551
560
|
- The agent's own turn and budget limits still apply as for any native agent.
|
|
561
|
+
- Each tool call has the tool's own time limit (`timeoutMs`, default 10
|
|
562
|
+
seconds, capped by `WARDBY_TOOL_MAX_TIMEOUT_MS`). The worker enforces it; the
|
|
563
|
+
gateway gives each host call the limit plus 20 seconds, never past the run's
|
|
564
|
+
deadline. Update the worker image with the server: an older image refuses a
|
|
565
|
+
run whose agent has a tool with `timeoutMs`
|
|
566
|
+
([details](security-deployment.md#tool-time-limits)).
|
|
552
567
|
|
|
553
568
|
## Stopping a run
|
|
554
569
|
|
|
@@ -558,7 +573,8 @@ run whether it is still waiting for a worker or already running:
|
|
|
558
573
|
1. The run is recorded `cancelled` with the caller's reason, unless it already
|
|
559
574
|
finished (the first terminal state wins; a finished run is not changed).
|
|
560
575
|
2. Its gateway session ends. The worker's next call (a model turn, a tool, or
|
|
561
|
-
its result) is refused, and the worker exits on its own.
|
|
576
|
+
its result) is refused, and the worker exits on its own. A tool's host call
|
|
577
|
+
still running on the gateway is aborted within a few seconds.
|
|
562
578
|
3. A worker still running 5 seconds later is killed. Either way the worker is
|
|
563
579
|
then removed; a worker claimed from the warm pool is discarded with its pool
|
|
564
580
|
row and never returned to the pool.
|
|
@@ -79,15 +79,16 @@ Scopes and roles do different jobs:
|
|
|
79
79
|
- **Roles authorize.** A user has a set of roles. With no roles, the user is a
|
|
80
80
|
member:
|
|
81
81
|
|
|
82
|
-
| Role | Grants
|
|
83
|
-
| ------------------ |
|
|
84
|
-
| `admin` | `agents:admin`, `packages:approve`, `services:manage`, `admin:view`, `models:admin` and `
|
|
85
|
-
| `package-approver` | `packages:approve`
|
|
86
|
-
| `service-manager` | `services:manage`
|
|
87
|
-
| `model-manager` | `models:admin`
|
|
88
|
-
|
|
|
82
|
+
| Role | Grants |
|
|
83
|
+
| ------------------ | --------------------------------------------------------------------------------------------------------------------- |
|
|
84
|
+
| `admin` | `agents:admin`, `packages:approve`, `services:manage`, `admin:view`, `models:admin`, `power:manage` and `hosts:admin` |
|
|
85
|
+
| `package-approver` | `packages:approve` |
|
|
86
|
+
| `service-manager` | `services:manage` |
|
|
87
|
+
| `model-manager` | `models:admin` |
|
|
88
|
+
| `host-manager` | `hosts:admin` |
|
|
89
|
+
| (none) | nothing privileged; every other scope works as the token allows |
|
|
89
90
|
|
|
90
|
-
|
|
91
|
+
Nine kinds of operation are privileged:
|
|
91
92
|
|
|
92
93
|
- `make_owner`, which reassigns any agent's owner, including another
|
|
93
94
|
principal's private agent (see [Sharing agents](#sharing-agents) for what
|
|
@@ -107,7 +108,15 @@ Eight operations are privileged:
|
|
|
107
108
|
[viewer-api.md](viewer-api.md));
|
|
108
109
|
- reading low-power state and scaling the coding proxy and native gateway to
|
|
109
110
|
zero now (`power_status`, `power_sleep`; see
|
|
110
|
-
[Low-power mode](getting-started-gke.md#low-power-mode))
|
|
111
|
+
[Low-power mode](getting-started-gke.md#low-power-mode));
|
|
112
|
+
- registering, approving, testing and deleting host providers
|
|
113
|
+
(`register_host_provider`, `approve_host_provider_tools`,
|
|
114
|
+
`test_host_provider`, `delete_host_provider`; reading one with
|
|
115
|
+
`get_host_provider` needs the same permission). Approved tools run on the
|
|
116
|
+
control plane with the provider's credentials, so grant `hosts:admin` like
|
|
117
|
+
`agents:admin`. Any host manager can read and re-register any provider,
|
|
118
|
+
including its tool code, whoever owns the tools; see
|
|
119
|
+
[host-providers.md](host-providers.md).
|
|
111
120
|
|
|
112
121
|
Each needs **both** its scope on the token **and** a role that grants that
|
|
113
122
|
permission:
|
|
@@ -119,13 +128,16 @@ permission:
|
|
|
119
128
|
- The admin viewer API needs `admin:view`, which only the `admin` role grants.
|
|
120
129
|
- `power_status` and `power_sleep` need `power:manage`, which only the `admin`
|
|
121
130
|
role grants.
|
|
131
|
+
- Host provider tools need `hosts:admin`, which the `admin` and `host-manager`
|
|
132
|
+
roles grant.
|
|
122
133
|
|
|
123
134
|
In practice:
|
|
124
135
|
|
|
125
|
-
- an `admin` can do all
|
|
136
|
+
- an `admin` can do all of them;
|
|
126
137
|
- a `package-approver` can approve packages only;
|
|
127
138
|
- a `service-manager` can change the service catalog only;
|
|
128
139
|
- a `model-manager` can change the model catalog only;
|
|
140
|
+
- a `host-manager` can manage host providers only;
|
|
129
141
|
- a member can do none of them.
|
|
130
142
|
|
|
131
143
|
Callers who fail the check get `403`:
|
|
@@ -312,7 +324,7 @@ someone else's agent (it can adopt the agent first). An HTTP user whose
|
|
|
312
324
|
subject equals `LOCAL_PRINCIPAL` is not the operator. **Admins** get no
|
|
313
325
|
implicit access to others' agents: they can `list_access` any agent (incident
|
|
314
326
|
response) and reassign one with `make_owner`, which removes bindings the new
|
|
315
|
-
owner doesn't own, suspends tool capabilities the new owner never granted,
|
|
327
|
+
owner doesn't own (secrets, datastores and MCP server attachments), suspends tool capabilities the new owner never granted,
|
|
316
328
|
cuts sub-agent edges the new owner can't delegate, and, between two owners,
|
|
317
329
|
resets every grant. Adopting an owner-less agent keeps its grants but lowers
|
|
318
330
|
an everyone grant to `read` unless `keepEveryoneExecute` is set.
|
|
@@ -347,7 +359,7 @@ without their tools' capabilities. Operator runbook:
|
|
|
347
359
|
printed for review, with the `attach_tool` call that re-grants any
|
|
348
360
|
capabilities it had. The subject must already exist.
|
|
349
361
|
4. `wardby grants prune-bindings` removes, and prints, every remaining
|
|
350
|
-
binding of one owner's secret or
|
|
362
|
+
binding of one owner's secret, datastore or MCP server to another owner's agent
|
|
351
363
|
(already inert).
|
|
352
364
|
5. `wardby grants migration-report > after.txt`.
|
|
353
365
|
|
|
@@ -380,6 +392,15 @@ Trust assumptions:
|
|
|
380
392
|
owner enabled `allowWebhookTaskOverride`; the owner controls the tools,
|
|
381
393
|
secrets and repository. A repository is a binding: only the owner (or an
|
|
382
394
|
admin's explicit approval) sets it, never a `write`-grantee.
|
|
395
|
+
- **A task can steer a coding agent to any repository on its list.** A caller
|
|
396
|
+
who may pass `repository` (for `trigger_agent`, the owner, or anyone when
|
|
397
|
+
`allowWebhookTaskOverride` is on; for a webhook, whoever created it, and only
|
|
398
|
+
when `allowWebhookTaskOverride` is on), and a lead that delegates to the
|
|
399
|
+
agent, can pick any listed repository, and the agent's one toolchain,
|
|
400
|
+
services and package allowlist apply to all of them. Keep the list small, and keep
|
|
401
|
+
repositories with different trust levels on separate agents. Refusals never
|
|
402
|
+
repeat the requested value, and a lead sees a sub-agent's list only when it
|
|
403
|
+
has the same owner or may choose (execute access and the opt-in).
|
|
383
404
|
- **Owner-less agents never hold a repository**, even admin-approved: there is
|
|
384
405
|
no owner whose GitHub access can be checked. Assign an owner first.
|
|
385
406
|
- **Checked where it's used.** Every coding run (before its workspace is
|
|
@@ -522,22 +543,22 @@ records. Delete them (see pruning above) if you want the rollback to be final.
|
|
|
522
543
|
|
|
523
544
|
## Resource and networking limits
|
|
524
545
|
|
|
525
|
-
| Surface | Limit
|
|
526
|
-
| ------------------------------ |
|
|
527
|
-
| MCP/webhook bodies | 1 MiB raw bytes
|
|
528
|
-
| MCP tool-call arguments | 100,000 array elements and object members
|
|
529
|
-
| Auth bodies | 64 KiB raw bytes
|
|
530
|
-
| Request completion / headers | 15 seconds / 10 seconds
|
|
531
|
-
| Sandbox invocation | 32 MiB heap, 1 MiB stack, 10 seconds
|
|
532
|
-
| Sandbox fetch | 8 MiB encoded and decoded, 5 redirects
|
|
533
|
-
| Bridge input / output | 1 MiB / 12 MiB
|
|
534
|
-
| Parser input / console payload | 256 KiB / 16 KiB
|
|
535
|
-
| HTML links extracted | 1000, with incremental result-byte accounting
|
|
536
|
-
| Random bytes | 65,536 bytes
|
|
537
|
-
| Host calls | 256 per invocation, at most 8 pending
|
|
538
|
-
| Datastore value / keys listed | 1 MiB / 1000
|
|
539
|
-
| Datastore key / secret name | 1024 bytes
|
|
540
|
-
| New secret plaintext | 64 KiB
|
|
546
|
+
| Surface | Limit |
|
|
547
|
+
| ------------------------------ | ------------------------------------------------ |
|
|
548
|
+
| MCP/webhook bodies | 1 MiB raw bytes |
|
|
549
|
+
| MCP tool-call arguments | 100,000 array elements and object members |
|
|
550
|
+
| Auth bodies | 64 KiB raw bytes |
|
|
551
|
+
| Request completion / headers | 15 seconds / 10 seconds |
|
|
552
|
+
| Sandbox invocation | 32 MiB heap, 1 MiB stack, 10 seconds (see below) |
|
|
553
|
+
| Sandbox fetch | 8 MiB encoded and decoded, 5 redirects |
|
|
554
|
+
| Bridge input / output | 1 MiB / 12 MiB |
|
|
555
|
+
| Parser input / console payload | 256 KiB / 16 KiB |
|
|
556
|
+
| HTML links extracted | 1000, with incremental result-byte accounting |
|
|
557
|
+
| Random bytes | 65,536 bytes |
|
|
558
|
+
| Host calls | 256 per invocation, at most 8 pending |
|
|
559
|
+
| Datastore value / keys listed | 1 MiB / 1000 |
|
|
560
|
+
| Datastore key / secret name | 1024 bytes |
|
|
561
|
+
| New secret plaintext | 64 KiB |
|
|
541
562
|
|
|
542
563
|
Oversized or malformed input fails explicitly. Existing oversized datastore
|
|
543
564
|
values/keys and secret ciphertext fail instead of entering Node allocations.
|
|
@@ -551,8 +572,9 @@ call arguments against its `paramsZod`, runs in a fresh QuickJS runtime with the
|
|
|
551
572
|
heap, stack, and time limits above. One that hits a limit fails that tool call
|
|
552
573
|
only: the model receives a `validation_failed` or sandbox error result and the
|
|
553
574
|
run continues. The invocation runs on the thread of the process that hosts the
|
|
554
|
-
run (the server, or the run's worker with the native sandbox)
|
|
555
|
-
|
|
575
|
+
run (the server, or the run's worker with the native sandbox). Code that keeps
|
|
576
|
+
the thread busy is also stopped by the instruction budget, so a long time limit
|
|
577
|
+
mostly lets a call wait on slow requests.
|
|
556
578
|
|
|
557
579
|
For this release only, a custom tool's `paramsZod` is compiled with Zod 4's
|
|
558
580
|
built-in Zod 3 API (`zod/v3`) so that existing tools keep working; see
|
|
@@ -578,7 +600,7 @@ The network layer cannot back this up for the control plane on GKE, because
|
|
|
578
600
|
Workload Identity needs the metadata server.
|
|
579
601
|
Sandbox code can explicitly log secrets it has been given; log size limits do
|
|
580
602
|
not provide automatic redaction. Keep tool-authoring privileges restricted.
|
|
581
|
-
Public/non-owner tool listings expose only id/name/description; owners retain
|
|
603
|
+
Public/non-owner tool listings expose only id/name/description/timeoutMs; owners retain
|
|
582
604
|
their source and schema. Private agents are indistinguishable from missing IDs.
|
|
583
605
|
|
|
584
606
|
Cancellation stops bridge delivery, sleep timers, and in-flight network work.
|
|
@@ -591,6 +613,57 @@ bound connection pools and concurrent invocations, and review a cancellable
|
|
|
591
613
|
database adapter or isolated worker if strict immediate termination is required.
|
|
592
614
|
Do not claim these per-invocation caps establish a whole-process memory ceiling.
|
|
593
615
|
|
|
616
|
+
### Tool time limits
|
|
617
|
+
|
|
618
|
+
A tool call has 10 seconds unless the tool sets its own `timeoutMs`
|
|
619
|
+
(`create_tool`, `update_tool`, `dry_run_tool`, `wardby tool create|update
|
|
620
|
+
--timeout-ms`, or `timeoutMs` in a bundle's `config/tools.json`). The limit
|
|
621
|
+
covers the whole call: each `fetch` may run until it, and a timer can't be set
|
|
622
|
+
for longer. A call never outlasts its run: stopping the run aborts it, and a
|
|
623
|
+
sandboxed run's deadline cuts it off.
|
|
624
|
+
|
|
625
|
+
| Variable | Default | Meaning |
|
|
626
|
+
| ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
627
|
+
| `WARDBY_TOOL_MAX_TIMEOUT_MS` | `300000` | The longest `timeoutMs` a tool may set, in milliseconds (at least `10000`). A larger value is refused when the tool is saved. A run uses the lower of the tool's `timeoutMs` and this value, so lowering it also covers existing tools. |
|
|
628
|
+
|
|
629
|
+
Set it on every process that runs tools or serves the native sandbox gateway:
|
|
630
|
+
`wardby serve`, `wardby scheduler` and the gateway. An invalid value stops
|
|
631
|
+
start-up. On the native sandbox the gateway gives each of a tool's host calls
|
|
632
|
+
its limit plus 20 seconds, never past the run's deadline. A long limit lets one
|
|
633
|
+
call hold its run (and a sandboxed run's worker) for longer, so raise the
|
|
634
|
+
ceiling only as far as your tools need.
|
|
635
|
+
|
|
636
|
+
**Upgrading:** the release adds the nullable `Tool.timeoutMs` and
|
|
637
|
+
`HostProviderOperation.timeoutMs` columns; apply the migration with
|
|
638
|
+
`prisma migrate deploy` as with any upgrade. A sandboxed run passes a tool's
|
|
639
|
+
`timeoutMs` to its worker, so update the native worker image together with the
|
|
640
|
+
server: an older image refuses the run of an agent that has a tool with
|
|
641
|
+
`timeoutMs`. Tools without `timeoutMs` run on either image.
|
|
642
|
+
|
|
643
|
+
### Remote MCP servers
|
|
644
|
+
|
|
645
|
+
Owners can register a remote MCP server (Streamable HTTP, HTTPS only) and attach
|
|
646
|
+
an allowlisted subset of its tools to a native agent, which then calls them
|
|
647
|
+
through Wardby's control plane. `WARDBY_MCP_SERVERS` decides who may register
|
|
648
|
+
servers: `owners` (the default), `admins` (only `hosts:admin` holders), or `off`
|
|
649
|
+
to disable the feature. An agent can use a server only while its owner owns it or
|
|
650
|
+
holds `use` on it through a grant; revoking or lowering that grant detaches it. Secret values for a server are never sent to the model,
|
|
651
|
+
stored in run records, or returned by Wardby's MCP tools. See [Remote MCP servers](mcp-servers.md) for the
|
|
652
|
+
full guide.
|
|
653
|
+
|
|
654
|
+
Claude Code and Codex agents can use attached servers too. Their workers reach
|
|
655
|
+
the tools only through the coding proxy's `/mcp` route, which forwards to the
|
|
656
|
+
native sandbox gateway's `/coding-mcp` route; the proxy never sees a server's URL
|
|
657
|
+
or secrets. Codex agents get only tools the server marks `readOnlyHint: true`
|
|
658
|
+
(see [Coding worker isolation](coding-worker-isolation.md#remote-mcp-tools)).
|
|
659
|
+
|
|
660
|
+
| Variable | Read by | Default | Meaning |
|
|
661
|
+
| ------------------------------ | -------------------------------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
662
|
+
| `WARDBY_MCP_SERVERS` | the server processes and the gateway | `owners` | Who may register remote MCP servers: `owners` (the default: owners may register servers), `admins` (registering, updating and refreshing a server needs `hosts:admin`), or `off` (every MCP-server tool except `detach_mcp_server` and `delete_mcp_server` is refused with a 403 that names this variable, and attached servers' tools are left out of runs). Any other value stops start-up. |
|
|
663
|
+
| `WARDBY_MCP_MAX_CALLS_PER_RUN` | the native gateway, which counts calls; also checked at start-up by the server processes and the gateway | `100` | The most remote MCP tool calls one coding run (Claude Code or Codex) may make. Every call to one of the run's MCP tools counts, whatever its outcome; a call past the limit is refused with the [`mcp_call_limit`](../help/errors/mcp-call-limit.md) error, which the agent sees as the tool's result. A positive whole number; any other value stops start-up. |
|
|
664
|
+
| `WARDBY_MCP_GATEWAY_URL` | the coding proxy | unset | The native sandbox gateway's base URL, for example `http://<gateway host>:<port>`. The proxy's `/mcp` route, which a coding run's worker uses as its MCP server, forwards each request to the gateway's `/coding-mcp` route; the proxy never sees an MCP server's URL or credentials. Unset, coding runs get no MCP tools: `/mcp` answers `503` with [`mcp_unavailable`](../help/errors/mcp-unavailable.md). An `http` or `https` URL without credentials, query or fragment; any other value stops start-up. |
|
|
665
|
+
| `WARDBY_MCP_TOKEN` | the coding worker | set by Wardby | Don't set it. Wardby gives each coding run whose agent has MCP tools its own MCP token in this worker variable. It is valid only for the proxy's `/mcp` route, and only while the run is active and before its deadline; only its hash is stored, and it is never logged. |
|
|
666
|
+
|
|
594
667
|
## Slack workflow notifications
|
|
595
668
|
|
|
596
669
|
This integration requires Wardby 0.6.0 or later.
|
|
@@ -779,6 +852,12 @@ packages, both forced to patched versions by `overrides` in `package.json`:
|
|
|
779
852
|
re-run `prisma generate`, `prisma validate`, the `migrate diff` drift check,
|
|
780
853
|
and the migration image's `migrate deploy`.
|
|
781
854
|
|
|
855
|
+
ESLint and `typescript-eslint` still ask for `minimatch` 10, which is flagged
|
|
856
|
+
(GHSA-g3hv-75wg-m249, moderate, fixed in 11.0.1), so `overrides` also forces
|
|
857
|
+
`minimatch` to 11.0.3. It is development-only and never reaches a production
|
|
858
|
+
image. After changing it, confirm `npm run lint` checks the same files and
|
|
859
|
+
still reports problems.
|
|
860
|
+
|
|
782
861
|
`scripts/security-audit.mjs` carries no exceptions: with the overrides the full
|
|
783
862
|
and production audits are clean, and if a lockfile change ever dropped one, the
|
|
784
863
|
advisory would reappear and the security job would fail.
|
package/docs/tool-secrets.md
CHANGED
|
@@ -157,6 +157,9 @@ or that the tool is not granted, fails with
|
|
|
157
157
|
[`secret_brokered`](../help/errors/secret-brokered.md), so update tools that read
|
|
158
158
|
the value to use `fetch` instead.
|
|
159
159
|
|
|
160
|
+
A host provider's credentials must be brokered secrets, placed in a header or
|
|
161
|
+
query parameter. See [host-providers.md](host-providers.md).
|
|
162
|
+
|
|
160
163
|
## What the host enforces
|
|
161
164
|
|
|
162
165
|
- **https only**, to the default port. Any other scheme or port is refused with
|
package/docs/viewer-api.md
CHANGED
|
@@ -13,6 +13,12 @@ the `admin` role.
|
|
|
13
13
|
|
|
14
14
|
## Access
|
|
15
15
|
|
|
16
|
+
From an MCP client, an admin gets a deployment-wide listing without this API:
|
|
17
|
+
`list_agents` and `list_runs` with `all: true` (Wardby 0.8.0 and later) need the
|
|
18
|
+
same `admin:view` scope and `admin` role, and are refused otherwise. Their
|
|
19
|
+
`triggerInfo` and `outcomes` fields have the same shapes as a graph run's
|
|
20
|
+
`trigger` and `outcomes` here; `serviceReadiness` is `services` without `reason`.
|
|
21
|
+
|
|
16
22
|
A caller needs an access token for the Wardby MCP resource that carries the
|
|
17
23
|
`admin:view` scope, and the Wardby `admin` role. Send it as
|
|
18
24
|
`Authorization: Bearer <token>`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
openapi: 3.1.0
|
|
3
3
|
info:
|
|
4
4
|
title: wardby admin viewer API
|
|
5
|
-
version: 0.
|
|
5
|
+
version: 0.8.0
|
|
6
6
|
description: "Read-only admin API behind the wardby viewer: graph, run detail, infrastructure info and a live event stream. Response objects may gain new fields in later releases; clients should ignore unknown fields. See docs/viewer-api.md for the prose contract."
|
|
7
7
|
servers:
|
|
8
8
|
- url: https://{host}
|
package/help/admin-viewer.md
CHANGED
|
@@ -19,6 +19,10 @@ It requires the Wardby `admin` role and the `admin:view` scope, which only the
|
|
|
19
19
|
provider and map it like `agents:admin`. See
|
|
20
20
|
[Configure identity and privileged access](identity-and-access.md).
|
|
21
21
|
|
|
22
|
+
From an MCP client, an admin gets the same deployment-wide listing with
|
|
23
|
+
`list_agents` and `list_runs` and `all: true` (Wardby 0.8.0 and later; also
|
|
24
|
+
`admin:view`). Without the role the call is refused.
|
|
25
|
+
|
|
22
26
|
Endpoints, all `GET`:
|
|
23
27
|
|
|
24
28
|
- `/admin/api/graph?since=1h&limit=500`: a snapshot of runs in a time window.
|