Deploy a remote vault PR #11 · merging

From a local CLI to a network service in two minutes.

In remote mode, the same vault binary speaks Streamable HTTP MCP with OAuth auth-code + PKCE. Stand it up on a real host so your agents — wherever they run, sandboxed or not — can resolve, verify, and install signed skills without ever touching a local filesystem.

Transport: Streamable HTTP MCP
Auth: OAuth 2.1 + PKCE
Storage: SQLite or Postgres
Remote topologylive trace
AgentClaude CodeCodex · CursorHTTPSOAuthautovault-remote/mcpStreamable HTTP/oauth/*auth-code · PKCE · refresh/admin/*owner routespolicy layerscopes · roles · filterCORS · origin guardallowed originsSQLiteuserstokens

Pick a host

Start with managed static vault hosting, or self-host the remote MCP service on one of four officially-tested targets. Managed stores signed files and rendered profiles; self-hosted targets run the full Docker image with OAuth and policy enforcement.

Deploy to Managed by AutoVault · 4 steps · ~30 sec
1

Create hosted vault

Create a team vault on AutoVault's managed static origin. It stores manifests, signed skill bundles, and rendered agent profiles only.

2

Provision namespace

AutoVault allocates an isolated tenant namespace on shared infrastructure. The host never executes uploaded skills; trust stays anchored in local signatures.

3

Connect local CLI

Link your local vault to the hosted namespace. The command pins the remote origin before any sync happens.

autovault cloud connect https://vault.autovault.dev/your-team
4

Sync signed files

The CLI scans local skills, runs the gate, signs accepted bundles, and pushes only the manifest, bundles, and rendered profiles.

autovault sync --cloud
autovault status --cloud
After deploy
autovault status
$ autovault status --cloud
 
vault your-team
endpoint https://vault.autovault.dev/your-team
mode hosted static vault
storage signed manifests + skill bundles
runtime none · skills are not executed on host
 
sync
manifest 18 skills · ed25519:9af4...2c81
rendered claude-code, codex, cursor
namespace tenant:yteam_7f2c
last push 26s ago
 
✓ synced · local signatures verified
hosted vault

Create a hosted static vault namespace

AutoVault stores pending drafts, signed manifests, skill bundles, and rendered profiles in a tenant namespace. The host does not execute skills; your local CLI gates, signs, and syncs the files.

AuthContinue with GitHub or Google
CheckoutStripe-hosted payment form
NamespaceShared static vault storage
SyncCLI signs and syncs local files
Provisioning
okQueue selected starter skills
--Confirm paid access from webhook state
--Allocate tenant namespace
--Save pending cloud import
--Sync signed bundles from CLI
Suggested starter skills
Agent handoff
autovault cloud connect https://vault.autovault.dev/your-team
autovault sync --cloud
autovault cloud pull --pending

Environment

All knobs are env-var driven. The first card is the breaking change in remote mode — Compose now hard-fails if these aren't set, instead of falling back to a known-default password.

Admin seed required
AUTOVAULT_ADMIN_EMAIL
Email address for the bootstrap owner. Created on first boot only.
AUTOVAULT_ADMIN_PASSWORD
Min 24 chars. Compose / Railway / Render templates refuse to start without this.
Public surface required
AUTOVAULT_PUBLIC_URL
Public HTTPS origin. Used as the OAuth issuer and embedded in /.well-known docs.
AUTOVAULT_PORT
Bind port. Default 8080. PaaS providers usually inject $PORT.
CORS & origin guard optional
AUTOVAULT_ALLOWED_ORIGINS
Comma-separated origin list. Browsers calling /mcp must come from one of these.
AUTOVAULT_TRUSTED_PROXIES
CIDR list for X-Forwarded-* trust behind Caddy, Cloudflare, or fly-proxy.
Storage & tokens optional
AUTOVAULT_DATABASE_URL
SQLite path or Postgres URL. Default: ./data/vault.db.
AUTOVAULT_TOKEN_TTL
Access token lifetime in seconds. Default 900; refresh tokens rotate on use.

OAuth handshake

Streamable HTTP MCP layered on OAuth 2.1 — auth-code flow with mandatory PKCE, dynamic client registration, refresh rotation, and revoke. Below is the exact sequence the bundled smoke suite walks for every release.

Agent CLIBrowser/oauth/*/mcp1open authorize URLPKCE challenge2GET /oauth/authorizecode_challenge + redirect_uri3consent screensession cookie set4redirect with code?code=...&state=...5POST /oauth/tokencode + verifier6access + refresh tokensscopes: read write7POST /mcpAuthorization: Bearer …8tool resultpolicy-filtered by scope

Endpoint reference

Every route the remote service exposes. Public routes are reachable pre-auth; bearer routes need a valid access token; owner routes additionally require role:owner.

MethodPathDescriptionAuth
GET/.well-known/oauth-authorization-serverRFC 8414 metadata. Issuer, endpoints, supported flows.public
POST/oauth/registerDynamic client registration. Returns client_id.public
GET/oauth/authorizeAuth-code endpoint. Requires PKCE challenge.public
POST/oauth/tokenCode → token, refresh → token. Rotates refresh on use.public
POST/oauth/revokeRevoke an access or refresh token.bearer
POST/mcpStreamable HTTP MCP transport. All tool calls land here.bearer
GET/admin/usersList users with roles and last-seen timestamps.owner
POST/admin/users/:id/scopesGrant or revoke scopes. Audit-logged.owner
DELETE/admin/clients/:idForce-revoke a client and all tokens.owner
GET/healthzLiveness probe. Returns boot time and DB ping.public

Policy gate on every call

The same role + scope filter runs at the MCP boundary. Non-owner reads are filtered by capability access; writes require explicit scope:write.

src/remote/policy.ts

PKCE is mandatory

The /oauth/authorize endpoint rejects requests without a code_challenge. Refresh tokens rotate on use.

src/remote/auth.ts

CORS & origin pinning

Browser access is opt-in. AUTOVAULT_ALLOWED_ORIGINS is a strict allowlist; server-to-server calls bypass cleanly.

src/remote/server.ts

Verify with npm run smoke:remote

Bundled in the repo. Walks the full OAuth flow against your live deployment, calls real MCP tools, and verifies policy enforcement end-to-end. Wire it into CI to catch drift before users do.

npm run smoke:remote — bash
$ AUTOVAULT_REMOTE_URL=https://vault.acme.dev npm run smoke:remote
 
▸ phase 1 · discovery
GET /.well-known/oauth-authorization-server 200
GET /.well-known/openid-configuration 200
→ issuer matches AUTOVAULT_PUBLIC_URL ✓
 
▸ phase 2 · dynamic registration
POST /oauth/register 201
→ client_id: smk_8f3c…21a4 ✓
 
▸ phase 3 · auth-code + PKCE
GET /oauth/authorize 302
POST /oauth/token 200
POST /oauth/token refresh 200
 
▸ phase 4 · MCP tool calls
POST /mcp initialize 200
POST /mcp skill.list 200
POST /mcp skill.fetch autoworks-ai/extract-pdf 200
→ ed25519 signature verified ✓
 
▸ phase 5 · policy enforcement
POST /mcp skill.publish (non-owner) 403
→ expected denial: scope:write missing ✓
 
✓ remote smoke complete · 18/18 checks passed · 4.2s