Skip to main content
Glama
bchoor
by bchoor

bws-mcp

Remote MCP for Bitwarden Secrets Manager, running as a Cloudflare Worker.

Tools: bws_list_projects, bws_list_secrets, bws_get_secret, bws_put_secret (create or update), and bws_delete_secret. Secret tools require project (the BWS project name, not a UUID). The Worker never searches across projects.

BWS_ALLOWED_PROJECTS is a Worker var:

  • * — allow every project the machine token can see. bws_list_projects enumerates them all.

  • Comma list — only those names (for example prod,staging). bws_list_projects returns the intersection with what the token can see.

  • Empty or unset — the Worker rejects BWS calls with BWS_ALLOWED_PROJECTS is not configured.

A * anywhere in the comma list means allow-all. Empty is not a synonym for *.

Auth is OAuth 2.1 with open Dynamic Client Registration at /register. After Cloudflare Access login, the Worker completes the MCP grant without a second consent screen. If the request already carries a Cloudflare Access JWT (Cf-Access-Jwt-Assertion), the Worker verifies it itself and skips the MCP OAuth dance.

ACCESS_SKIP exists for local wrangler dev only. It is honored only when the request hostname is localhost or 127.0.0.1. Do not set it in production.

Deploy to Cloudflare

The Deploy to Cloudflare form asks for one secret: BWS_ACCESS_TOKEN, the Bitwarden Secrets Manager machine token. BWS_ALLOWED_PROJECTS defaults to * (every project that token can see). Cookie HMAC material is created on first OAuth use and stored in OAUTH_KV. Team domain, audience, client id, client secret, cookie key, and email allowlist are not deploy-time fields.

On that form:

  • Leave Build command empty. This Worker has no build step. Cloudflare leaves the box blank because package.json has no build script. Do not add a dummy one.

  • Uncheck Builds for non-production branches. Production is main only. preview_urls: false in wrangler.jsonc turns off Worker preview URLs. It does not control this checkbox. Cloudflare turns the checkbox on. There is no wrangler or button query that defaults it off. Uncheck it here. After deploy you can also clear it under Settings, Build, Branch control.

  • Cloudflare's OAuth consent may list Email Routing (email_routing) scopes. That list is Wrangler's default login scopes, not a bws-mcp requirement. This Worker has no addresses field and no email bindings. Granting those scopes does not enable Email Routing. Declining the whole consent blocks the deploy.

Deploy

Button. Paste BWS_ACCESS_TOKEN. Leave the build command empty. Uncheck non-production branch builds. KV is provisioned for you. Access comes after the Worker is up.

CLI. Create a KV namespace, put its id on OAUTH_KV in wrangler.jsonc, set BWS_ACCESS_TOKEN (wrangler secret put or .dev.vars locally), then npx wrangler deploy.

Cloudflare Access (second step)

The Worker deploys without Access. /authorize returns 503 until you finish this.

Machine JWTs on Cf-Access-Jwt-Assertion:

  • ACCESS_TEAM_DOMAIN

  • ACCESS_AUD

Access for SaaS OIDC (MCP OAuth after a human logs in):

  • CF_ACCESS_TEAM_DOMAIN

  • CF_ACCESS_AUD

  • CF_ACCESS_CLIENT_ID

  • ALLOWED_EMAILS

  • secret CF_ACCESS_CLIENT_SECRET

Set those in the dashboard or with wrangler after the first deploy. COOKIE_ENCRYPTION_KEY is optional. If you skip it, the Worker writes a random key to OAUTH_KV and reuses it.

Access for SaaS id_token issuer is https://<team>.cloudflareaccess.com/cdn-cgi/access/sso/oidc/<client_id>, not the team-domain root.

Related MCP server: Identity Admin MCP Server

Security

This Worker lists, gets, creates, updates, and deletes secrets in every allowed project (* or the comma list). An OAuth client that finishes /authorize for an approved human can rotate and delete those secrets. Treat that as vault rewrite access, not look-around access.

Two walls. Do not collapse them into one secret.

  • The BWS access token is a machine account, not a user. Its SM ACL is only which projects that machine can touch.

  • Approved humans belong on the Worker email allowlist (ALLOWED_EMAILS) only. Do not keep a second people list next to the token in Secrets Manager. SM is not a people list.

  • Token = machine project ACL. Humans = ALLOWED_EMAILS. Not one secret that does both.

Give the machine account Can write (and delete) on only the projects this MCP should touch. In SM a project is the folder. The Worker cannot enforce a finer ACL than that token. If the token can write a project, bws_put_secret and bws_delete_secret can change any secret in it. Skip write on the token only if you intend this deploy to fail writes.

BWS_ALLOWED_PROJECTS is a Worker project-name gate, not a people list. Keep using it. With *, the token ACL is the only project boundary. With a comma list, put only those same names on the token. An extra name on the token and a missing name on the var, or the reverse, is how you leak or lock yourself out.

ACCESS_SKIP is for local wrangler dev on localhost or 127.0.0.1. Never set it in production. The Deploy to Cloudflare button does not inject it, and should stay that way.

Registration at /register is open, and /authorize auto-consents after Access login. An allowlisted person who clicks a hostile /authorize link grants that client create, rotate, and delete on every allowed project (* or the list).

Bots that mint tokens or credentials should live in their own SM project. Give this Worker a token that can read and write only that project so a chat client cannot pull or rewrite the rest of the vault.

Create a KV namespace for this Worker and bind it as OAUTH_KV. Do not reuse another Worker's KV. Grants and DCR clients would share a store with whatever else lives there.

Versions and marketplaces

package.json version is the source of truth. These must match it:

  • Cursor .cursor-plugin/plugin.json

  • Claude .claude-plugin/plugin.json

  • Codex .codex-plugin/plugin.json

  • Claude .claude-plugin/marketplace.json (top-level version and the plugin entry version)

  • src/server.ts MCP version on new McpServer({ name: "bws-mcp", version: "..." })

Marketplaces live here:

  • Cursor: .cursor-plugin

  • Claude: .claude-plugin

  • Codex: .codex-plugin, plus the repo marketplace at .agents/plugins

npm run ci runs scripts/check-manifests.mjs. That fails the PR if any of the versions above drift, or if an official plugin or marketplace schema shape is wrong. Name, homepage, and license on the plugin manifests must match package.json too.

Plugins

Cursor. Install the plugin from this repo, then set Worker URL to your deployed origin (no path). MCP is ${WORKER_URL}/mcp.

Claude Code. Add the marketplace in this repo (.claude-plugin/marketplace.json), install bws-mcp, then set Worker URL the same way.

Codex / ChatGPT Work. codex plugin marketplace add bchoor/bws-mcp, then install bws-mcp. Point .mcp.json at your Worker /mcp URL after deploy. Codex does not document a Worker URL setup field.

Other clients

Claude connectors. You can still paste https://<your-worker>/mcp in Claude Desktop or claude.ai. DCR registers the client at /register.

ChatGPT custom MCP. Enable custom MCP in developer settings, paste the same /mcp URL, and finish the OAuth redirect.

Windsurf. Add a server in mcp_config.json:

{
  "mcpServers": {
    "bws-mcp": {
      "serverUrl": "https://<your-worker>/mcp"
    }
  }
}

Cline. Same shape in Cline's MCP settings, url pointing at /mcp.

Local skip (ACCESS_SKIP=1 in .dev.vars, never in git) only works against http://localhost:8787 or 127.0.0.1.

Develop

npm install
cp .dev.vars.example .dev.vars
# Fill BWS_ACCESS_TOKEN. Access vars and CF_ACCESS_CLIENT_SECRET are optional until you test OIDC.
npm run ci
npx wrangler dev

Do not open a PR until npm run ci is green.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bchoor/bws-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server