bws-mcp
Provides tools to list, get, create/update, and delete secrets in Bitwarden Secrets Manager, scoped to allowed projects.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bws-mcplist all secrets in the prod project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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_projectsenumerates them all.Comma list — only those names (for example
prod,staging).bws_list_projectsreturns 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.
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.jsonhas nobuildscript. Do not add a dummy one.Uncheck Builds for non-production branches. Production is
mainonly.preview_urls: falseinwrangler.jsoncturns 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 noaddressesfield 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_DOMAINACCESS_AUD
Access for SaaS OIDC (MCP OAuth after a human logs in):
CF_ACCESS_TEAM_DOMAINCF_ACCESS_AUDCF_ACCESS_CLIENT_IDALLOWED_EMAILSsecret
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.jsonClaude
.claude-plugin/plugin.jsonCodex
.codex-plugin/plugin.jsonClaude
.claude-plugin/marketplace.json(top-levelversionand the plugin entryversion)src/server.tsMCPversiononnew McpServer({ name: "bws-mcp", version: "..." })
Marketplaces live here:
Cursor:
.cursor-pluginClaude:
.claude-pluginCodex:
.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 devDo 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.
This server cannot be installed
Maintenance
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
The bridge from K2 agents through Wrangler to your master AI - safe, approval-gated Cloudflare ops.
Secrets for developers and agents—secure context and workflows without exposing secret values.
Encrypted secret store and rotation for autonomous agent credentials
Issue, rotate and revoke scoped API-key passes for 25+ providers — the agent never sees a real key
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA Cloudflare Worker that provides API access to Postman collections and environments via the Claude AI MCP interface, enabling Claude to assist with API testing, documentation, and management tasks.223ISC
- FlicenseNot gradedqualityCmaintenanceEnables admin operations for an Identity-Service, including user management, role assignments, and approval decisions via Cloudflare Workers.-
- FlicenseNot gradedqualityCmaintenanceAllows you to deploy a remote MCP server without authentication on Cloudflare Workers.-
- AlicenseNot gradedqualityCmaintenanceEnables secure access to Vikunja projects and tasks via MCP tools, protected by Cloudflare Access and designed for remote clients like ChatGPT.2MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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