@icoretech/warden-mcp 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -1,10 +1,14 @@
1
1
  # warden-mcp
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/%40icoretech%2Fwarden-mcp?logo=npm)](https://www.npmjs.com/package/@icoretech/warden-mcp)
4
+ [![CI](https://img.shields.io/github/actions/workflow/status/icoretech/warden-mcp/ci.yml?branch=main&label=ci)](https://github.com/icoretech/warden-mcp/actions/workflows/ci.yml)
5
+ [![license](https://img.shields.io/github/license/icoretech/warden-mcp)](LICENSE)
6
+
3
7
  Programmatic Vaultwarden/Bitwarden vault management over MCP (Model Context Protocol), backed by the official Bitwarden CLI (`bw`).
4
8
 
5
9
  This project exists to let agents and automation **create/search/read/update/move** vault items without re-implementing Bitwarden’s client-side crypto.
6
10
 
7
- Published package: `@icoretech/warden-mcp`
11
+ Published package: [`@icoretech/warden-mcp`](https://www.npmjs.com/package/@icoretech/warden-mcp)
8
12
 
9
13
  ## Highlights
10
14
 
@@ -15,11 +19,306 @@ Published package: `@icoretech/warden-mcp`
15
19
  - Organization + collection helpers (list + org-collection CRUD)
16
20
  - Safe-by-default: item reads are **redacted** unless explicitly revealed; secret helper tools return `null` unless `reveal: true`
17
21
 
22
+ ## Runtime Requirement
23
+
24
+ This package shells out to the official Bitwarden CLI, `bw`.
25
+
26
+ Runtime resolution order:
27
+
28
+ - `BW_BIN` if you set it explicitly
29
+ - bundled `@bitwarden/cli` optional dependency if it is present
30
+ - system `bw` from `PATH`
31
+
32
+ That means package installation can succeed even when the optional dependency is skipped by the environment. In that case you must install `bw` separately or point `BW_BIN` to it.
33
+
34
+ Explicit fallback install:
35
+
36
+ ```bash
37
+ npm install -g @bitwarden/cli
38
+ ```
39
+
40
+ Or run with an explicit binary path:
41
+
42
+ ```bash
43
+ BW_BIN=/absolute/path/to/bw npx -y @icoretech/warden-mcp
44
+ ```
45
+
46
+ ## Install And Run
47
+
48
+ ### Choose a transport
49
+
50
+ - Use `--stdio` when you want a local MCP host to spawn `warden-mcp` directly with one fixed Bitwarden profile
51
+ - Use default HTTP mode when you want one running `warden-mcp` service to serve multiple clients or multiple Bitwarden profiles via per-request `X-BW-*` headers
52
+
53
+ ### Local stdio mode
54
+
55
+ ```bash
56
+ npx -y @icoretech/warden-mcp --stdio
57
+ ```
58
+
59
+ For stdio mode, you must provide Bitwarden credentials up front via env vars:
60
+
61
+ ```bash
62
+ BW_HOST=https://vaultwarden.example.com \
63
+ BW_USER=user@example.com \
64
+ BW_PASSWORD='your-master-password' \
65
+ npx -y @icoretech/warden-mcp --stdio
66
+ ```
67
+
68
+ API key login works too:
69
+
70
+ ```bash
71
+ BW_HOST=https://vaultwarden.example.com \
72
+ BW_CLIENTID=user.xxxxx \
73
+ BW_CLIENTSECRET=xxxxx \
74
+ BW_PASSWORD='your-master-password' \
75
+ npx -y @icoretech/warden-mcp --stdio
76
+ ```
77
+
78
+ ### Shared HTTP mode
79
+
80
+ Start one long-lived MCP server:
81
+
82
+ ```bash
83
+ npx -y @icoretech/warden-mcp
84
+ ```
85
+
86
+ Verify it is up:
87
+
88
+ ```bash
89
+ curl -fsS http://localhost:3005/healthz
90
+ ```
91
+
92
+ This mode is what makes `warden-mcp` different from a simple local wrapper:
93
+
94
+ - the server stays stateless at the HTTP boundary
95
+ - Bitwarden/Vaultwarden credentials are sent per request via `X-BW-*` headers
96
+ - one running server can front different vault hosts or different identities without restarting
97
+ - it fits shared-agent and gateway setups much better than per-client local processes
98
+
99
+ ### Global install
100
+
101
+ ```bash
102
+ npm install -g @icoretech/warden-mcp
103
+ warden-mcp
104
+ ```
105
+
106
+ ## Connect From MCP Hosts
107
+
108
+ For local MCP hosts, stdio is the most portable option.
109
+
110
+ ```bash
111
+ npx -y @icoretech/warden-mcp --stdio
112
+ ```
113
+
114
+ The examples below use Bitwarden API-key auth. If you prefer username/password login, replace `BW_CLIENTID` + `BW_CLIENTSECRET` with `BW_USER`.
115
+
116
+ ### CLI-based hosts
117
+
118
+ These hosts let you register `warden-mcp` directly from the command line:
119
+
120
+ ```bash
121
+ # Codex
122
+ codex mcp add warden \
123
+ --env BW_HOST=https://vaultwarden.example.com \
124
+ --env BW_CLIENTID=user.xxxxx \
125
+ --env BW_CLIENTSECRET=xxxxx \
126
+ --env BW_PASSWORD='your-master-password' \
127
+ -- npx -y @icoretech/warden-mcp --stdio
128
+
129
+ # Claude Code
130
+ claude mcp add-json warden '{"command":"npx","args":["-y","@icoretech/warden-mcp","--stdio"],"env":{"BW_HOST":"https://vaultwarden.example.com","BW_CLIENTID":"user.xxxxx","BW_CLIENTSECRET":"xxxxx","BW_PASSWORD":"your-master-password"}}'
131
+
132
+ # Qwen Code
133
+ qwen mcp add warden \
134
+ -e BW_HOST=https://vaultwarden.example.com \
135
+ -e BW_CLIENTID=user.xxxxx \
136
+ -e BW_CLIENTSECRET=xxxxx \
137
+ -e BW_PASSWORD=your-master-password \
138
+ npx -y @icoretech/warden-mcp --stdio
139
+ ```
140
+
141
+ ### JSON config hosts
142
+
143
+ These hosts all use the same stdio payload shape. Only the config file location changes:
144
+
145
+ - Codex: `~/.codex/config.toml`
146
+ - Cursor: `~/.cursor/mcp.json` or `.cursor/mcp.json`
147
+ - Claude Desktop: `~/Library/Application Support/Claude/claude_desktop_config.json`
148
+ - Qwen Code: `~/.qwen/settings.json` or `.qwen/settings.json`
149
+
150
+ Shared JSON shape:
151
+
152
+ ```json
153
+ {
154
+ "mcpServers": {
155
+ "warden": {
156
+ "command": "npx",
157
+ "args": ["-y", "@icoretech/warden-mcp", "--stdio"],
158
+ "env": {
159
+ "BW_HOST": "https://vaultwarden.example.com",
160
+ "BW_CLIENTID": "user.xxxxx",
161
+ "BW_CLIENTSECRET": "xxxxx",
162
+ "BW_PASSWORD": "your-master-password"
163
+ }
164
+ }
165
+ }
166
+ }
167
+ ```
168
+
169
+ Codex uses TOML instead of JSON:
170
+
171
+ ```toml
172
+ [mcp_servers.warden]
173
+ command = "npx"
174
+ args = ["-y", "@icoretech/warden-mcp", "--stdio"]
175
+
176
+ [mcp_servers.warden.env]
177
+ BW_HOST = "https://vaultwarden.example.com"
178
+ BW_CLIENTID = "user.xxxxx"
179
+ BW_CLIENTSECRET = "xxxxx"
180
+ BW_PASSWORD = "your-master-password"
181
+ ```
182
+
183
+ ### Windsurf
184
+
185
+ Windsurf uses the same stdio idea but stores it in `~/.codeium/windsurf/mcp_config.json`:
186
+
187
+ ```json
188
+ {
189
+ "mcpServers": {
190
+ "warden": {
191
+ "command": "npx",
192
+ "args": ["-y", "@icoretech/warden-mcp", "--stdio"],
193
+ "env": {
194
+ "BW_HOST": "https://vaultwarden.example.com",
195
+ "BW_CLIENTID": "user.xxxxx",
196
+ "BW_CLIENTSECRET": "xxxxx",
197
+ "BW_PASSWORD": "your-master-password"
198
+ }
199
+ }
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### Shared HTTP connections
205
+
206
+ If your MCP host supports Streamable HTTP with custom headers, you can connect to one long-lived `warden-mcp` service instead of spawning a local stdio process.
207
+
208
+ Start the shared server:
209
+
210
+ ```bash
211
+ npx -y @icoretech/warden-mcp
212
+ ```
213
+
214
+ Every MCP request must include:
215
+
216
+ - `X-BW-Host`
217
+ - `X-BW-Password`
218
+ - either `X-BW-ClientId` + `X-BW-ClientSecret`, or `X-BW-User`
219
+
220
+ Example health check:
221
+
222
+ ```bash
223
+ curl -fsS \
224
+ -H 'X-BW-Host: https://vaultwarden.example.com' \
225
+ -H 'X-BW-ClientId: user.xxxxx' \
226
+ -H 'X-BW-ClientSecret: xxxxx' \
227
+ -H 'X-BW-Password: your-master-password' \
228
+ http://localhost:3005/healthz
229
+ ```
230
+
231
+ Example MCP endpoint:
232
+
233
+ ```text
234
+ http://localhost:3005/sse?v=2
235
+ ```
236
+
237
+ This shared-server mode is useful when:
238
+
239
+ - one MCP gateway needs to front multiple Bitwarden profiles
240
+ - you want to rotate vault credentials per request instead of per process
241
+ - you are integrating from a custom client or agent host that can attach HTTP headers
242
+ - you want one always-on service instead of each editor spawning its own `bw`-backed subprocess
243
+
244
+ Client examples for shared HTTP mode:
245
+
246
+ ```bash
247
+ # Claude Code
248
+ claude mcp add-json warden '{"type":"http","url":"http://localhost:3005/sse?v=2","headers":{"X-BW-Host":"https://vaultwarden.example.com","X-BW-ClientId":"user.xxxxx","X-BW-ClientSecret":"xxxxx","X-BW-Password":"your-master-password"}}'
249
+ ```
250
+
251
+ ```json
252
+ // Cursor (~/.cursor/mcp.json)
253
+ {
254
+ "mcpServers": {
255
+ "warden": {
256
+ "url": "http://localhost:3005/sse?v=2",
257
+ "headers": {
258
+ "X-BW-Host": "https://vaultwarden.example.com",
259
+ "X-BW-ClientId": "user.xxxxx",
260
+ "X-BW-ClientSecret": "xxxxx",
261
+ "X-BW-Password": "your-master-password"
262
+ }
263
+ }
264
+ }
265
+ }
266
+ ```
267
+
268
+ ```json
269
+ // Qwen Code (~/.qwen/settings.json)
270
+ {
271
+ "mcpServers": {
272
+ "warden": {
273
+ "httpUrl": "http://localhost:3005/sse?v=2",
274
+ "headers": {
275
+ "X-BW-Host": "https://vaultwarden.example.com",
276
+ "X-BW-ClientId": "user.xxxxx",
277
+ "X-BW-ClientSecret": "xxxxx",
278
+ "X-BW-Password": "your-master-password"
279
+ }
280
+ }
281
+ }
282
+ }
283
+ ```
284
+
285
+ ```json
286
+ // Windsurf (~/.codeium/windsurf/mcp_config.json)
287
+ {
288
+ "mcpServers": {
289
+ "warden": {
290
+ "serverUrl": "http://localhost:3005/sse?v=2",
291
+ "headers": {
292
+ "X-BW-Host": "https://vaultwarden.example.com",
293
+ "X-BW-ClientId": "user.xxxxx",
294
+ "X-BW-ClientSecret": "xxxxx",
295
+ "X-BW-Password": "your-master-password"
296
+ }
297
+ }
298
+ }
299
+ }
300
+ ```
301
+
302
+ Codex currently fits better with stdio here, because its MCP config supports a bearer token env var for remote servers but not arbitrary custom `X-BW-*` header injection.
303
+
304
+ ### Verify bw is available
305
+
306
+ ```bash
307
+ bw --version
308
+ ```
309
+
310
+ If that fails after install, your environment likely skipped the optional `@bitwarden/cli` dependency. Install it explicitly:
311
+
312
+ ```bash
313
+ npm install -g @bitwarden/cli
314
+ ```
315
+
18
316
  ## How It Works
19
317
 
20
318
  The server executes `bw` commands on your behalf:
21
319
 
22
- - Bitwarden/Vaultwarden connection + credentials are provided via **HTTP headers** per request.
320
+ - In HTTP mode, Bitwarden/Vaultwarden connection + credentials are provided via **HTTP headers** per request.
321
+ - In stdio mode, Bitwarden/Vaultwarden credentials are loaded once from `BW_*` env vars at startup.
23
322
  - The server maintains per-profile `bw` state under `KEYCHAIN_BW_HOME_ROOT` to avoid session/config clashes.
24
323
  - Writes can optionally call `bw sync` (internal; not exposed as an MCP tool).
25
324
 
@@ -64,7 +363,18 @@ Reveal rules:
64
363
 
65
364
  ## Quick Start
66
365
 
67
- ### Docker Compose (recommended)
366
+ ### Minimal local run
367
+
368
+ Run the published package in HTTP mode and verify the server is up:
369
+
370
+ ```bash
371
+ npx -y @icoretech/warden-mcp
372
+ curl -fsS http://localhost:3005/healthz
373
+ ```
374
+
375
+ ## Local Development
376
+
377
+ ### Docker Compose
68
378
 
69
379
  Starts a local Vaultwarden + HTTPS proxy (for `bw`), bootstraps a test user, and runs the MCP server.
70
380
 
@@ -86,7 +396,7 @@ Run session flood regression locally (guardrail sanity):
86
396
  npm run test:session-regression
87
397
  ```
88
398
 
89
- ### Local Dev (host)
399
+ ### Local dev (host)
90
400
 
91
401
  ```bash
92
402
  npm install
@@ -94,13 +404,6 @@ cp .env.example .env
94
404
  npm run dev
95
405
  ```
96
406
 
97
- ### Run via npx
98
-
99
- ```bash
100
- npx -y @icoretech/warden-mcp
101
- npx -y @icoretech/warden-mcp --stdio
102
- ```
103
-
104
407
  ## Tool Reference (v1)
105
408
 
106
409
  Vault/session:
@@ -5,8 +5,12 @@ import { runBw } from './bwCli.js';
5
5
  import { Mutex } from './mutex.js';
6
6
  function requiredEnv(name) {
7
7
  const v = process.env[name];
8
- if (!v)
9
- throw new Error(`Missing required env var: ${name}`);
8
+ if (!v) {
9
+ throw new Error(`Missing required env var for stdio mode: ${name}. ` +
10
+ 'For --stdio, set BW_HOST, BW_PASSWORD, and either ' +
11
+ 'BW_CLIENTID+BW_CLIENTSECRET or BW_USER/BW_USERNAME. ' +
12
+ 'For HTTP mode, omit --stdio and send X-BW-* headers per request.');
13
+ }
10
14
  return v;
11
15
  }
12
16
  export function readBwEnv() {
package/package.json CHANGED
@@ -1,9 +1,20 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@icoretech/warden-mcp",
4
- "version": "0.1.0",
4
+ "version": "0.1.2",
5
5
  "type": "module",
6
+ "license": "MIT",
6
7
  "description": "Vaultwarden/Bitwarden MCP server backed by Bitwarden CLI (bw).",
8
+ "keywords": [
9
+ "mcp",
10
+ "model-context-protocol",
11
+ "bitwarden",
12
+ "vaultwarden",
13
+ "password-manager",
14
+ "secrets",
15
+ "automation",
16
+ "sse"
17
+ ],
7
18
  "repository": {
8
19
  "type": "git",
9
20
  "url": "git+https://github.com/icoretech/warden-mcp.git"
@@ -15,7 +26,12 @@
15
26
  "bin": {
16
27
  "warden-mcp": "bin/warden-mcp.js"
17
28
  },
18
- "files": ["dist/", "bin/", "!dist/**/*.test.js", "!dist/integration/"],
29
+ "files": [
30
+ "dist/",
31
+ "bin/",
32
+ "!dist/**/*.test.js",
33
+ "!dist/integration/"
34
+ ],
19
35
  "scripts": {
20
36
  "dev": "tsx watch --clear-screen=false src/server.ts",
21
37
  "build": "tsc -p .",
@@ -26,18 +42,18 @@
26
42
  "lint": "biome check --write --assist-enabled=true . && tsc --noEmit"
27
43
  },
28
44
  "dependencies": {
29
- "@modelcontextprotocol/sdk": "^1.26.0",
45
+ "@modelcontextprotocol/sdk": "^1.27.1",
30
46
  "express": "^5.2.1",
31
- "jose": "^6.1.3",
47
+ "jose": "^6.2.2",
32
48
  "zod": "^4.3.6"
33
49
  },
34
50
  "optionalDependencies": {
35
- "@bitwarden/cli": "2026.1.0"
51
+ "@bitwarden/cli": "2026.2.0"
36
52
  },
37
53
  "devDependencies": {
38
- "@biomejs/biome": "^2.3.15",
54
+ "@biomejs/biome": "^2.4.8",
39
55
  "@types/express": "^5.0.6",
40
- "@types/node": "^25.2.3",
56
+ "@types/node": "^25.5.0",
41
57
  "playwright": "1.58.2",
42
58
  "tsx": "^4.21.0",
43
59
  "typescript": "^5.9.3"
@@ -47,6 +63,6 @@
47
63
  "access": "public"
48
64
  },
49
65
  "engines": {
50
- "node": ">=24.0.0"
66
+ "node": ">=24.14.0"
51
67
  }
52
68
  }