@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 +314 -11
- package/dist/bw/bwSession.js +6 -2
- package/package.json +24 -8
package/README.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# warden-mcp
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@icoretech/warden-mcp)
|
|
4
|
+
[](https://github.com/icoretech/warden-mcp/actions/workflows/ci.yml)
|
|
5
|
+
[](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
|
-
###
|
|
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
|
|
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:
|
package/dist/bw/bwSession.js
CHANGED
|
@@ -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.
|
|
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": [
|
|
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.
|
|
45
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
30
46
|
"express": "^5.2.1",
|
|
31
|
-
"jose": "^6.
|
|
47
|
+
"jose": "^6.2.2",
|
|
32
48
|
"zod": "^4.3.6"
|
|
33
49
|
},
|
|
34
50
|
"optionalDependencies": {
|
|
35
|
-
"@bitwarden/cli": "2026.
|
|
51
|
+
"@bitwarden/cli": "2026.2.0"
|
|
36
52
|
},
|
|
37
53
|
"devDependencies": {
|
|
38
|
-
"@biomejs/biome": "^2.
|
|
54
|
+
"@biomejs/biome": "^2.4.8",
|
|
39
55
|
"@types/express": "^5.0.6",
|
|
40
|
-
"@types/node": "^25.
|
|
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.
|
|
66
|
+
"node": ">=24.14.0"
|
|
51
67
|
}
|
|
52
68
|
}
|