Bitwarden
NPM · @FOREVERWORKS/MCP-BITWARDEN
Give your assistant its own Bitwarden vault for logins, passwords, 2FA codes and passkeys.
Available components
Last scanned (6 hours ago)
Scores higher than 53% of npm servers
Category Security
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security89
- No malware found by supply-chain analysis.Pass
- CVE check failed: a known high-severity CVE affects multer 2.3.0, reached via @bitwarden/cli > multer. A fixed version is available. View diagnostics → Fail
- No install/post-install scripts declared.Pass
- 94 of 237 dependencies flagged as unhealthy (1 deprecated). View diagnostics → Partial
Provenance & Transparency100
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to foreverworks/mcps). View diagnostics → Pass
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 2 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability65
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 3785 tokens (~222/item across 17 items; 17 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management0
- Stability not yet verified: not enough scan history yet (needs a 30-day window).Unverified
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
- Structured output schemas are declared (12% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 18 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Unverified: 1 category
A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 4 Nov 26 +7
- CVE-2026-118781 affects this package: high ▼ security
- CVE-2026-119186 affects this package: high ▼ security
- CVE-2026-113872 affects this package: high ▼ security
- CVE-2026-118780 affects this package: high ▼ security
- CVE-2026-88932 affects this package: high ▼ security
- CVE-2026-119190 affects this package: high ▼ security
- CVE-2026-119188 affects this package: high ▼ security
- CVE-2026-44705 affects this package: high ▼ security
- CVE-2026-118775 affects this package: high ▼ security
- CVE-2026-119187 affects this package: high ▼ security
- CVE-2026-118779 affects this package: high ▼ security
- CVE-2025-54798 affects this package: high ▼ security
- CVE-2026-118778 affects this package: high ▼ security
- CVE-2026-118777 affects this package: high ▼ security
- CVE-2026-118782 affects this package: high ▼ security
- Known CVEs: unverified → fail ▼ security
- Dependency health: unverified → 0.81 ▲ functional
- 3 Nov 26 69
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Analysed npm/@foreverworks/mcp-bitwarden@0.2.1
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | npm |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | foreverworks/mcps |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/foreverworks/mcps/.github/workflows/release.yml@refs/tags/release-2026-11-03.2 |
| Rekor log index | 3658005087 |
| Predicate type | SLSA build provenance https://slsa.dev/provenance/v1 |
| Subject digest | sha512:fb6bbfbea5c02c6c9d36d70ca8d4321098c07a983826292efbede7e4a1d5998779474d5ec97c85d301fd6ced8cbb0eca9976ea86af0f55f49fb73d93f |
Background: How many MCP packages publish verified provenance →
Vulnerabilities 16 findings
| ID | CVE | Severity | Vector | Fix available |
|---|---|---|---|---|
| GHSA-3pph-fpjx-jg34 | CVE-2026-88932 | medium | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L | yes |
| GHSA-q7qp-rjg7-q26m | CVE-2026-113872 | high | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | yes |
| GHSA-4487-j8r4-4g2f | CVE-2026-118780 | low | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L | yes |
| GHSA-4642-5mcj-2rqw | CVE-2026-118775 | low | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N | yes |
| GHSA-525v-9gp9-w22h | CVE-2026-118778 | medium | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H | yes |
| GHSA-5cwg-6vw7-rj6p | CVE-2026-119186 | medium | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N | yes |
| GHSA-5x38-2vff-x55p | CVE-2026-119190 | high | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N | yes |
| GHSA-6wvx-3r32-xmcg | CVE-2026-118777 | medium | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L | yes |
| GHSA-7wch-p9px-956x | CVE-2026-118779 | high | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | yes |
| GHSA-86w9-cpqp-85rv | CVE-2026-33894 | high | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N | no |
| GHSA-8hrf-8g6f-7xwp | CVE-2026-119188 | high | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | yes |
| GHSA-h6cr-wjv9-3cpp | CVE-2026-118781 | low | CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L | yes |
| GHSA-hqq3-7jhf-c5jx | CVE-2026-119187 | high | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | yes |
| GHSA-jc66-7q78-782g | CVE-2026-118782 | high | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N | yes |
| GHSA-52f5-9888-hmc6 | CVE-2025-54798 | low | CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N | yes |
| GHSA-ph9p-34f9-6g65 | CVE-2026-44705 | high | yes |
Background: What a vulnerability scan can and cannot prove →
Dependencies 237 packages
| Packages resolved | 237 |
|---|---|
| Deprecated | 1 |
| Stale | 94 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
assert_passkey Sign in with a passkey ~307
Sign a WebAuthn sign-in, as an authenticator does for navigator.credentials.get(): authenticator data and an ES256 signature over it and the client data's hash, with the vault's passkey for the site, plus the credential id and user handle a browser returns. With allow_credentials, only a passkey those ids name; without (a discoverable request), any discoverable passkey for the RP ID. When several can answer, the call is refused as several with the candidates: call again with credential_id. No passkey for the site is refused as no_credential. Hand the result only to the page that asked; the key never leaves this server.
| Name | Type | Req | Description |
|---|---|---|---|
| allow_credentials | array | – | The request's allowCredentials ids; empty for a discoverable request. |
| client_data_hash | string | yes | SHA-256 of the client data JSON the browser (or the program in its place) built for this request, base64url (43 characters). |
| credential_id | string | – | The passkey to sign with, from an earlier answer's candidates or list_passkeys. |
| rp_id | string | yes | The RP ID: the site's domain the passkey is bound to, e.g. example.com or login.example.com. |
| user_verified | boolean | – | Whether the user was verified for this request, which sets the UV flag. True only when the caller verified them: an agent signing in as its own identity, or a person who approved the request. |
No output schema declared.
No examples provided.
check_exposed Check a password against breaches ~143
Whether a login's password appears in Have I Been Pwned's list of passwords seen in data breaches, and how many times. Only the first five hex characters of the password's SHA-1 leave this server (k-anonymity); the password and its full hash never do, and the answer is a count. A count above 0 means the password is known to attackers: rotate it (update_login with rotate_password, then change it on the site). With previous, the password the current one replaced.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | The item id, from find_logins. |
| previous | boolean | – | Check the password before the current one instead. |
| Name | Type | Req | Description |
|---|---|---|---|
| count | integer | yes | How many times the password was seen in breaches; 0 when it was not |
| exposed | boolean | yes | – |
| id | string | yes | – |
| name | string | yes | – |
| previous | boolean | – | – |
| username | string|null | yes | – |
No examples provided.
create_login Create login ~488
Save a new login. Without `password` or `password_file` a strong one is generated here and stored; nothing returns it, so call get_password when you type it into the signup form. Create the login BEFORE submitting a signup, so the password is never lost. Filed into the account's own vault, outside any collection unless `collection` names another.
| Name | Type | Req | Description |
|---|---|---|---|
| collection | string | – | A collection name from health. Default: the account's own vault, outside any collection. |
| length | integer | – | Length of a generated password. Default 24. |
| name | string | yes | What the account is, e.g. 'GitHub (example-bot)'. |
| notes | string | – | Free text kept with the login: recovery codes, security answers, what the account is for. |
| password | string | – | A password the account already has, exactly as you were given it. Leave it out to have a strong one generated here; a secret that is already in a file goes as password_file instead, so it is never re… |
| password_file | object | – | A password the account already has, from a file holding just it (one line; a final line ending is dropped): a downloaded key or a generated credential, which is safer read than retyped. Delete the fi… |
| symbols | boolean | – | Whether a generated password contains symbols (!@#$%^&*-_=+). Default true; turn off for sites that refuse them. |
| totp_secret | string | – | The site's authenticator key: the base32 secret shown under the 2FA QR code, or the otpauth://totp/ URI it encodes. Store it BEFORE confirming 2FA on the site, then confirm with the code this call re… |
| url | string | – | The site's URL, e.g. https://github.com/login; its host is what find_logins' url matches. |
| username | string | – | The login name or email the site knows the account by. |
No output schema declared.
No examples provided.
create_note Create secure note ~266
Save a secret that is not a login as a new secure note: a service account's key file, an API token, a licence key. Each secret goes in a field of its own, hidden by default, typed (value) or read from a file (file), with no password length limit: up to what Bitwarden stores in a field. Nothing returns the secret: the result names each field with its length, and a file's SHA-256 and size (compare them with the source's). get_field hands a value out; get_login names the fields. Filed into the account's own vault, outside any collection unless `collection` names another. If a call fails without saying whether the note was saved, find_logins by its name before trying again.
| Name | Type | Req | Description |
|---|---|---|---|
| collection | string | – | A collection name from health. Default: the account's own vault, outside any collection. |
| fields | array | yes | The secrets, one field each, and any plain details beside them. |
| name | string | yes | What the secret is, e.g. 'Play service account key (example-app)'. |
| notes | string | – | Plain text anyone reading the note sees (get_login shows it): what the secret is for, where it is used. Never the secret itself. |
No output schema declared.
No examples provided.
create_passkey Create passkey ~507
Register a new passkey, as an authenticator does for WebAuthn's navigator.credentials.create(): an ES256 (P-256) key pair is made here, the private key stored in the vault exactly as Bitwarden's own apps store a passkey (so they can sign with it too), and the answer is what a browser needs to finish the registration: the credential id, the attestation object (format none), the authenticator data and the public key (SPKI). The private key is never in the answer. It goes into the login item_id names, else into the one login already saved for this site with this username and no passkey, else into a new login named after the site (filed like create_login). Refused as excluded when the site's exclude list names a passkey the vault holds, and as unsupported when the site accepts no ES256 key. Use it for an agent's own identity; a person's own passkeys belong on their own devices.
| Name | Type | Req | Description |
|---|---|---|---|
| algorithms | array | – | The COSE algorithm ids in the request's pubKeyCredParams, e.g. [-7, -257]. Empty means the default, which includes ES256 (-7). |
| client_data_hash | string | yes | SHA-256 of the client data JSON for this request, base64url. An attestation of format none signs nothing, so it is only checked. |
| collection | string | – | For a new login: a collection name from health. |
| exclude_credentials | array | – | The request's excludeCredentials ids: passkeys the site already holds for this account. |
| item_id | string | – | The login to put it in: one without a passkey, or whose passkey is for the same account on this site (it is replaced). |
| resident_key | boolean | – | Whether the passkey is discoverable (a resident key), as the request's authenticatorSelection asks. |
| rp_id | string | yes | The RP ID: the site's domain the passkey is bound to, e.g. example.com or login.example.com. |
| rp_name | string | – | The site's name as the request gives it (rp.name). |
| user | object | yes | The account, as the request's `user`. |
| user_verified | boolean | – | Whether the user was verified for this request, which sets the UV flag. True only when the caller verified them: an agent signing in as its own identity, or a person who approved the request. |
No output schema declared.
No examples provided.
delete_passkey Delete passkey ~113
Remove one passkey from its login. The login and everything else in it (username, password, 2FA key) stay. The site keeps its copy of the public key, so remove the passkey there too if it should stop being offered. Not undone by anything here.
| Name | Type | Req | Description |
|---|---|---|---|
| credential_id | string | yes | The passkey's credential id, base64url, as list_passkeys gives it. |
| item_id | string | yes | The login's item id, from list_passkeys or find_logins. |
No output schema declared.
No examples provided.
find_logins Find logins ~164
Search the vault's logins and secure notes (`kind` says which). `search` matches name, username and URL; `url` finds the logins saved for a site (its host, as Bitwarden's autofill matches). Returns ids, names, usernames and URLs, and whether each has a password and an authenticator key, never the secrets themselves. Syncs first, so an item just added in the web vault shows up.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Return at most this many; `count` says how many matched. |
| search | string | – | Words in the name, username or URL. |
| url | string | – | The site's URL, e.g. https://github.com/login; its host is what find_logins' url matches. |
No output schema declared.
No examples provided.
get_field Get field ~126
One custom field's value, hidden ones included, from a login or a secure note: a secret that is not a password, such as a licence key or an API token, kept where a person put it. get_login names an item's fields. Use it only to type or pipe the value where it goes: never write it into a file, a commit, a message, a log or a reply.
| Name | Type | Req | Description |
|---|---|---|---|
| field | string | yes | The field's name as get_login lists it (case does not matter). |
| id | string | yes | The item id, from find_logins. |
No output schema declared.
No examples provided.
get_login Get login ~60
One login or secure note in full except its secrets: name, username, URLs, collections, notes, custom fields (hidden ones by name only) and when the password last changed.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | The item id, from find_logins. |
No output schema declared.
No examples provided.
get_password Get password ~108
The login's password, with its username and URLs, for typing into the site. Use it only for that: never write it into a file, a commit, a message, a log or a reply. With `previous`, the password the current one replaced, from the item's history: for when a site refused a rotation that is already stored.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | The item id, from find_logins. |
| previous | boolean | – | Return the password before the current one instead. |
No output schema declared.
No examples provided.
health Health ~61
Check that the vault is reachable and unlocked, and say as whom: the account, the server, when it last synced, how many logins and passkeys it holds, and the organizations and collections it can file into. Run this before concluding the MCP is broken.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
import_passkeys Import passkeys ~232
Import the logins that carry passkeys from a Bitwarden JSON export (not encrypted), or from one exported item: each becomes a new login here with its username, password, 2FA key, URLs, notes, custom fields and passkeys, filed like create_login. A passkey the vault already holds is skipped, and so is one this server cannot sign with (only ES256 P-256 keys sign, as in Bitwarden's apps). The answer lists what was imported and what was skipped with the reason, and the file's SHA-256 and size: compare them with the source, then delete the file, which holds private keys.
| Name | Type | Req | Description |
|---|---|---|---|
| collection | string | – | A collection name from health, for every imported login. Default: as create_login. |
| file | object | yes | The export. Never type or paste a file's base64 yourself: a retyped file can arrive changed. Give the path of a file in your workspace folders (the roots this client shares; without them /workdir), o… |
No output schema declared.
No examples provided.
list_passkeys List passkeys ~165
The passkeys the vault holds, each with its site (rpId and name), account (userName, userDisplayName, userHandle), credential id (base64url), counter, whether it is discoverable, when it was made, its login (itemId, itemName), the login's collections, and whether a person shared it with this account rather than the account keeping it as its own. Never a key. Syncs first.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Return at most this many; `count` says how many matched. |
| rp_id | string | – | Only the passkeys for this RP ID, e.g. example.com. |
| search | string | – | Words in the site, its name, the account's names or the login's name. |
No output schema declared.
No examples provided.
move_item Move item ~161
Put a login or secure note in one collection: its collections become exactly the one named. Only between the collections of the item's own organization; an item in the account's own vault, or a collection of another organization, is refused with what to do instead. An item already in exactly that collection is left as it is (moved: false). After a move the vault is synced and the item read back, so the answer, its collections before and after, is what Bitwarden holds. Returns no secret. Nothing is deleted or copied.
| Name | Type | Req | Description |
|---|---|---|---|
| collection | string | yes | The collection to put it in: its name as health lists it (case does not matter), or its id. |
| id | string | yes | The item id, from find_logins. |
| Name | Type | Req | Description |
|---|---|---|---|
| collections | array | yes | The item's collections now, by name |
| id | string | yes | – |
| kind | string | yes | – |
| moved | boolean | yes | false when the item was already in exactly that collection, and nothing was sent |
| name | string | yes | – |
| previousCollections | array | yes | Its collections before the call, by name |
No examples provided.
sync Sync ~36
Pull the vault from Bitwarden now. Reads already sync every 30 seconds; this is for right after someone changed something in the web vault.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
totp Current 2FA code ~65
The login's current authenticator (TOTP) code and how many seconds it stays valid, computed from the key stored on the login. If fewer than 5 seconds are left, wait and call again.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | The item id, from find_logins. |
No output schema declared.
No examples provided.
update_login Update login ~595
Change a login: only what is named changes. `rotate_password` generates a new password and stores it at once; change it on the site right after, with get_password, and if the site refuses, get_password with previous: true still has the old one. `url` becomes the first URL and the others stay. `append_notes` adds to the notes (recovery codes, answers) where `notes` replaces them. Set `totp_secret` when you turn on 2FA at a site, before confirming it there: the result carries the current code from the stored key. A different key already on the login is replaced only with `replace_totp`, and kept in a hidden field.
| Name | Type | Req | Description |
|---|---|---|---|
| append_notes | string | – | Added after the current notes on a new line; nothing is lost. |
| id | string | yes | The item id, from find_logins. |
| length | integer | – | Length of a generated password. Default 24. |
| name | string | – | A new name. |
| notes | string | – | Replaces the notes. |
| password | string | – | A password the account already has, exactly as you were given it. Leave it out to have a strong one generated here; a secret that is already in a file goes as password_file instead, so it is never re… |
| password_file | object | – | A password the account already has, from a file holding just it (one line; a final line ending is dropped): a downloaded key or a generated credential, which is safer read than retyped. Delete the fi… |
| replace_totp | boolean | – | Replace a DIFFERENT authenticator key the login already has (or clear it with an empty totp_secret). |
| rotate_password | boolean | – | Generate a new password (with `length` and `symbols`). |
| symbols | boolean | – | Whether a generated password contains symbols (!@#$%^&*-_=+). Default true; turn off for sites that refuse them. |
| totp_secret | string | – | The site's authenticator key: the base32 secret shown under the 2FA QR code, or the otpauth://totp/ URI it encodes. Store it BEFORE confirming 2FA on the site, then confirm with the code this call re… |
| url | string | – | The site's URL, e.g. https://github.com/login; its host is what find_logins' url matches. |
| username | string | – | The login name or email the site knows the account by. |
No output schema declared.
No examples provided.
How do I install the Bitwarden MCP server?
Bitwarden runs locally as an npm package, launched with npx -y @foreverworks/mcp-bitwarden. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · @foreverworks/mcp-bitwarden
claude mcp add com-foreverworks-bitwarden -- npx -y @foreverworks/mcp-bitwarden
What is the Bitwarden MCP server?
Bitwarden is an MCP server listed in the public MCP registry as com.foreverworks/bitwarden. Give your assistant its own Bitwarden vault for logins, passwords, 2FA codes and passkeys. This page covers its npm package (@foreverworks/mcp-bitwarden).
Is the Bitwarden MCP server safe to use?
Bitwarden scores 76 out of 100 on VerifyMCP. We recorded 16 known advisories against it as of 5 November 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Bitwarden MCP server expose?
Bitwarden exposes 17 tools: assert_passkey, check_exposed, create_login, create_note, create_passkey, and 12 more. Their descriptions and schemas cost roughly 3,597 tokens of context every time the server is loaded.
Is the Bitwarden MCP server still maintained?
Bitwarden is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Bitwarden MCP server under?
Bitwarden declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.