@icoretech/warden-mcp 0.1.0 → 0.1.1

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
@@ -15,11 +15,306 @@ Published package: `@icoretech/warden-mcp`
15
15
  - Organization + collection helpers (list + org-collection CRUD)
16
16
  - Safe-by-default: item reads are **redacted** unless explicitly revealed; secret helper tools return `null` unless `reveal: true`
17
17
 
18
+ ## Runtime Requirement
19
+
20
+ This package shells out to the official Bitwarden CLI, `bw`.
21
+
22
+ Runtime resolution order:
23
+
24
+ - `BW_BIN` if you set it explicitly
25
+ - bundled `@bitwarden/cli` optional dependency if it is present
26
+ - system `bw` from `PATH`
27
+
28
+ 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.
29
+
30
+ Explicit fallback install:
31
+
32
+ ```bash
33
+ npm install -g @bitwarden/cli
34
+ ```
35
+
36
+ Or run with an explicit binary path:
37
+
38
+ ```bash
39
+ BW_BIN=/absolute/path/to/bw npx -y @icoretech/warden-mcp
40
+ ```
41
+
42
+ ## Install And Run
43
+
44
+ ### Choose a transport
45
+
46
+ - Use `--stdio` when you want a local MCP host to spawn `warden-mcp` directly with one fixed Bitwarden profile
47
+ - 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
48
+
49
+ ### Local stdio mode
50
+
51
+ ```bash
52
+ npx -y @icoretech/warden-mcp --stdio
53
+ ```
54
+
55
+ For stdio mode, you must provide Bitwarden credentials up front via env vars:
56
+
57
+ ```bash
58
+ BW_HOST=https://vaultwarden.example.com \
59
+ BW_USER=user@example.com \
60
+ BW_PASSWORD='your-master-password' \
61
+ npx -y @icoretech/warden-mcp --stdio
62
+ ```
63
+
64
+ API key login works too:
65
+
66
+ ```bash
67
+ BW_HOST=https://vaultwarden.example.com \
68
+ BW_CLIENTID=user.xxxxx \
69
+ BW_CLIENTSECRET=xxxxx \
70
+ BW_PASSWORD='your-master-password' \
71
+ npx -y @icoretech/warden-mcp --stdio
72
+ ```
73
+
74
+ ### Shared HTTP mode
75
+
76
+ Start one long-lived MCP server:
77
+
78
+ ```bash
79
+ npx -y @icoretech/warden-mcp
80
+ ```
81
+
82
+ Verify it is up:
83
+
84
+ ```bash
85
+ curl -fsS http://localhost:3005/healthz
86
+ ```
87
+
88
+ This mode is what makes `warden-mcp` different from a simple local wrapper:
89
+
90
+ - the server stays stateless at the HTTP boundary
91
+ - Bitwarden/Vaultwarden credentials are sent per request via `X-BW-*` headers
92
+ - one running server can front different vault hosts or different identities without restarting
93
+ - it fits shared-agent and gateway setups much better than per-client local processes
94
+
95
+ ### Global install
96
+
97
+ ```bash
98
+ npm install -g @icoretech/warden-mcp
99
+ warden-mcp
100
+ ```
101
+
102
+ ## Connect From MCP Hosts
103
+
104
+ For local MCP hosts, stdio is the most portable option.
105
+
106
+ ```bash
107
+ npx -y @icoretech/warden-mcp --stdio
108
+ ```
109
+
110
+ The examples below use Bitwarden API-key auth. If you prefer username/password login, replace `BW_CLIENTID` + `BW_CLIENTSECRET` with `BW_USER`.
111
+
112
+ ### CLI-based hosts
113
+
114
+ These hosts let you register `warden-mcp` directly from the command line:
115
+
116
+ ```bash
117
+ # Codex
118
+ codex mcp add warden \
119
+ --env BW_HOST=https://vaultwarden.example.com \
120
+ --env BW_CLIENTID=user.xxxxx \
121
+ --env BW_CLIENTSECRET=xxxxx \
122
+ --env BW_PASSWORD='your-master-password' \
123
+ -- npx -y @icoretech/warden-mcp --stdio
124
+
125
+ # Claude Code
126
+ 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"}}'
127
+
128
+ # Qwen Code
129
+ qwen mcp add warden \
130
+ -e BW_HOST=https://vaultwarden.example.com \
131
+ -e BW_CLIENTID=user.xxxxx \
132
+ -e BW_CLIENTSECRET=xxxxx \
133
+ -e BW_PASSWORD=your-master-password \
134
+ npx -y @icoretech/warden-mcp --stdio
135
+ ```
136
+
137
+ ### JSON config hosts
138
+
139
+ These hosts all use the same stdio payload shape. Only the config file location changes:
140
+
141
+ - Codex: `~/.codex/config.toml`
142
+ - Cursor: `~/.cursor/mcp.json` or `.cursor/mcp.json`
143
+ - Claude Desktop: `~/Library/Application Support/Claude/claude_desktop_config.json`
144
+ - Qwen Code: `~/.qwen/settings.json` or `.qwen/settings.json`
145
+
146
+ Shared JSON shape:
147
+
148
+ ```json
149
+ {
150
+ "mcpServers": {
151
+ "warden": {
152
+ "command": "npx",
153
+ "args": ["-y", "@icoretech/warden-mcp", "--stdio"],
154
+ "env": {
155
+ "BW_HOST": "https://vaultwarden.example.com",
156
+ "BW_CLIENTID": "user.xxxxx",
157
+ "BW_CLIENTSECRET": "xxxxx",
158
+ "BW_PASSWORD": "your-master-password"
159
+ }
160
+ }
161
+ }
162
+ }
163
+ ```
164
+
165
+ Codex uses TOML instead of JSON:
166
+
167
+ ```toml
168
+ [mcp_servers.warden]
169
+ command = "npx"
170
+ args = ["-y", "@icoretech/warden-mcp", "--stdio"]
171
+
172
+ [mcp_servers.warden.env]
173
+ BW_HOST = "https://vaultwarden.example.com"
174
+ BW_CLIENTID = "user.xxxxx"
175
+ BW_CLIENTSECRET = "xxxxx"
176
+ BW_PASSWORD = "your-master-password"
177
+ ```
178
+
179
+ ### Windsurf
180
+
181
+ Windsurf uses the same stdio idea but stores it in `~/.codeium/windsurf/mcp_config.json`:
182
+
183
+ ```json
184
+ {
185
+ "mcpServers": {
186
+ "warden": {
187
+ "command": "npx",
188
+ "args": ["-y", "@icoretech/warden-mcp", "--stdio"],
189
+ "env": {
190
+ "BW_HOST": "https://vaultwarden.example.com",
191
+ "BW_CLIENTID": "user.xxxxx",
192
+ "BW_CLIENTSECRET": "xxxxx",
193
+ "BW_PASSWORD": "your-master-password"
194
+ }
195
+ }
196
+ }
197
+ }
198
+ ```
199
+
200
+ ### Shared HTTP connections
201
+
202
+ 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.
203
+
204
+ Start the shared server:
205
+
206
+ ```bash
207
+ npx -y @icoretech/warden-mcp
208
+ ```
209
+
210
+ Every MCP request must include:
211
+
212
+ - `X-BW-Host`
213
+ - `X-BW-Password`
214
+ - either `X-BW-ClientId` + `X-BW-ClientSecret`, or `X-BW-User`
215
+
216
+ Example health check:
217
+
218
+ ```bash
219
+ curl -fsS \
220
+ -H 'X-BW-Host: https://vaultwarden.example.com' \
221
+ -H 'X-BW-ClientId: user.xxxxx' \
222
+ -H 'X-BW-ClientSecret: xxxxx' \
223
+ -H 'X-BW-Password: your-master-password' \
224
+ http://localhost:3005/healthz
225
+ ```
226
+
227
+ Example MCP endpoint:
228
+
229
+ ```text
230
+ http://localhost:3005/sse?v=2
231
+ ```
232
+
233
+ This shared-server mode is useful when:
234
+
235
+ - one MCP gateway needs to front multiple Bitwarden profiles
236
+ - you want to rotate vault credentials per request instead of per process
237
+ - you are integrating from a custom client or agent host that can attach HTTP headers
238
+ - you want one always-on service instead of each editor spawning its own `bw`-backed subprocess
239
+
240
+ Client examples for shared HTTP mode:
241
+
242
+ ```bash
243
+ # Claude Code
244
+ 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"}}'
245
+ ```
246
+
247
+ ```json
248
+ // Cursor (~/.cursor/mcp.json)
249
+ {
250
+ "mcpServers": {
251
+ "warden": {
252
+ "url": "http://localhost:3005/sse?v=2",
253
+ "headers": {
254
+ "X-BW-Host": "https://vaultwarden.example.com",
255
+ "X-BW-ClientId": "user.xxxxx",
256
+ "X-BW-ClientSecret": "xxxxx",
257
+ "X-BW-Password": "your-master-password"
258
+ }
259
+ }
260
+ }
261
+ }
262
+ ```
263
+
264
+ ```json
265
+ // Qwen Code (~/.qwen/settings.json)
266
+ {
267
+ "mcpServers": {
268
+ "warden": {
269
+ "httpUrl": "http://localhost:3005/sse?v=2",
270
+ "headers": {
271
+ "X-BW-Host": "https://vaultwarden.example.com",
272
+ "X-BW-ClientId": "user.xxxxx",
273
+ "X-BW-ClientSecret": "xxxxx",
274
+ "X-BW-Password": "your-master-password"
275
+ }
276
+ }
277
+ }
278
+ }
279
+ ```
280
+
281
+ ```json
282
+ // Windsurf (~/.codeium/windsurf/mcp_config.json)
283
+ {
284
+ "mcpServers": {
285
+ "warden": {
286
+ "serverUrl": "http://localhost:3005/sse?v=2",
287
+ "headers": {
288
+ "X-BW-Host": "https://vaultwarden.example.com",
289
+ "X-BW-ClientId": "user.xxxxx",
290
+ "X-BW-ClientSecret": "xxxxx",
291
+ "X-BW-Password": "your-master-password"
292
+ }
293
+ }
294
+ }
295
+ }
296
+ ```
297
+
298
+ 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.
299
+
300
+ ### Verify bw is available
301
+
302
+ ```bash
303
+ bw --version
304
+ ```
305
+
306
+ If that fails after install, your environment likely skipped the optional `@bitwarden/cli` dependency. Install it explicitly:
307
+
308
+ ```bash
309
+ npm install -g @bitwarden/cli
310
+ ```
311
+
18
312
  ## How It Works
19
313
 
20
314
  The server executes `bw` commands on your behalf:
21
315
 
22
- - Bitwarden/Vaultwarden connection + credentials are provided via **HTTP headers** per request.
316
+ - In HTTP mode, Bitwarden/Vaultwarden connection + credentials are provided via **HTTP headers** per request.
317
+ - In stdio mode, Bitwarden/Vaultwarden credentials are loaded once from `BW_*` env vars at startup.
23
318
  - The server maintains per-profile `bw` state under `KEYCHAIN_BW_HOME_ROOT` to avoid session/config clashes.
24
319
  - Writes can optionally call `bw sync` (internal; not exposed as an MCP tool).
25
320
 
@@ -64,7 +359,18 @@ Reveal rules:
64
359
 
65
360
  ## Quick Start
66
361
 
67
- ### Docker Compose (recommended)
362
+ ### Minimal local run
363
+
364
+ Run the published package in HTTP mode and verify the server is up:
365
+
366
+ ```bash
367
+ npx -y @icoretech/warden-mcp
368
+ curl -fsS http://localhost:3005/healthz
369
+ ```
370
+
371
+ ## Local Development
372
+
373
+ ### Docker Compose
68
374
 
69
375
  Starts a local Vaultwarden + HTTPS proxy (for `bw`), bootstraps a test user, and runs the MCP server.
70
376
 
@@ -86,7 +392,7 @@ Run session flood regression locally (guardrail sanity):
86
392
  npm run test:session-regression
87
393
  ```
88
394
 
89
- ### Local Dev (host)
395
+ ### Local dev (host)
90
396
 
91
397
  ```bash
92
398
  npm install
@@ -94,13 +400,6 @@ cp .env.example .env
94
400
  npm run dev
95
401
  ```
96
402
 
97
- ### Run via npx
98
-
99
- ```bash
100
- npx -y @icoretech/warden-mcp
101
- npx -y @icoretech/warden-mcp --stdio
102
- ```
103
-
104
403
  ## Tool Reference (v1)
105
404
 
106
405
  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.1",
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 .",