@crabeye-ai/crabeye-mcp-bridge 0.4.0 → 1.0.0

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
@@ -47,7 +47,13 @@ Say your MCP client config looks like this today:
47
47
  }
48
48
  ```
49
49
 
50
- To use the bridge, rename `mcpServers` to `upstreamMcpServers` and add the bridge as the only entry in `mcpServers`:
50
+ First, store your secrets in the encrypted credential store:
51
+
52
+ ```bash
53
+ crabeye-mcp-bridge credential set github-pat ghp_abc123
54
+ ```
55
+
56
+ Then rename `mcpServers` to `upstreamMcpServers`, add the bridge, and replace hardcoded tokens with `${credential:key}` references:
51
57
 
52
58
  ```json
53
59
  {
@@ -66,7 +72,7 @@ To use the bridge, rename `mcpServers` to `upstreamMcpServers` and add the bridg
66
72
  "command": "npx",
67
73
  "args": ["-y", "@anthropic/github-mcp-server"],
68
74
  "env": {
69
- "GITHUB_TOKEN": "ghp_..."
75
+ "GITHUB_TOKEN": "${credential:github-pat}"
70
76
  }
71
77
  }
72
78
  }
@@ -75,7 +81,7 @@ To use the bridge, rename `mcpServers` to `upstreamMcpServers` and add the bridg
75
81
 
76
82
  That's it. Your AI assistant now has access to all tools from all configured servers through a single connection. The bridge automatically excludes itself from `mcpServers` to avoid recursion, so pointing `--config` at the same file is safe.
77
83
 
78
- The bridge also reads `servers` (VS Code Copilot) and `context_servers` (Zed) as input keys. On duplicate names, earlier sources win: `upstreamMcpServers` > `servers` > `context_servers` > `mcpServers`. Self-exclusion applies to `mcpServers` and `context_servers`.
84
+ The bridge also reads `upstreamServers` (shorthand), `servers` (VS Code Copilot), and `context_servers` (Zed) as input keys. On duplicate names, earlier sources win: `upstreamMcpServers` > `upstreamServers` > `servers` > `context_servers` > `mcpServers`. Self-exclusion applies to `mcpServers` and `context_servers`.
79
85
 
80
86
  Alternatively, you can add the bridge alongside your existing `mcpServers` entries without renaming anything:
81
87
 
@@ -94,7 +100,7 @@ Alternatively, you can add the bridge alongside your existing `mcpServers` entri
94
100
  "command": "npx",
95
101
  "args": ["-y", "@anthropic/github-mcp-server"],
96
102
  "env": {
97
- "GITHUB_TOKEN": "ghp_..."
103
+ "GITHUB_TOKEN": "${credential:github-pat}"
98
104
  }
99
105
  }
100
106
  }
@@ -118,6 +124,25 @@ The AI assistant calls `search_tools` automatically when it detects a relevant i
118
124
 
119
125
  When `search_tools` is called, the assistant receives the matching tools and their input schemas. The bridge also directly exposes the searched tools to the assistant so they can be called natively. Some assistants don't refresh their tool list mid-session, so they may not see the newly exposed tools — but they can still call them through `run_tool` and the call is executed exactly as if made directly on the original tool.
120
126
 
127
+ The bridge tracks how many tokens it saves compared to exposing all upstream tool definitions directly. Token savings are always logged to stderr after each search. To also include them in `search_tools` responses, pass `--stats`:
128
+
129
+ ```json
130
+ {
131
+ "session_stats": {
132
+ "tokens_saved": 11200,
133
+ "baseline_tokens": 14200,
134
+ "bridge_tokens": 3000
135
+ },
136
+ "results": [...]
137
+ }
138
+ ```
139
+
140
+ - **`baseline_tokens`** — estimated tokens if all upstream tool definitions were injected into context without the bridge
141
+ - **`bridge_tokens`** — cumulative tokens used by the bridge's two meta-tools plus all search results returned so far
142
+ - **`tokens_saved`** — the difference (baseline − bridge)
143
+
144
+ Token counts are estimated using a chars/4 heuristic.
145
+
121
146
  ## Examples
122
147
 
123
148
  ### Discovering providers
@@ -366,7 +391,46 @@ The assistant can then search by category: `{ "queries": [{ "category": "design"
366
391
 
367
392
  ### Authentication
368
393
 
369
- Static credentials (API keys, tokens) can be passed via `env` or `headers` in the server config. OAuth is not yet supported.
394
+ Secrets belong in the encrypted credential store, not in config files. Store a secret once, then reference it with `${credential:key}` in `env` or `headers`:
395
+
396
+ ```bash
397
+ # Store credentials
398
+ crabeye-mcp-bridge credential set github-pat ghp_abc123
399
+ crabeye-mcp-bridge credential set remote-api-key sk_live_xyz
400
+ ```
401
+
402
+ ```json
403
+ {
404
+ "upstreamMcpServers": {
405
+ "github": {
406
+ "command": "npx",
407
+ "args": ["-y", "@anthropic/github-mcp-server"],
408
+ "env": { "GITHUB_TOKEN": "${credential:github-pat}" }
409
+ },
410
+ "remote-api": {
411
+ "url": "https://mcp.example.com/sse",
412
+ "type": "sse",
413
+ "headers": { "Authorization": "Bearer ${credential:remote-api-key}" }
414
+ }
415
+ }
416
+ }
417
+ ```
418
+
419
+ Templates are resolved on every connect and reconnect, so rotating a credential takes effect without restarting the bridge.
420
+
421
+ **How it works:** Credentials are encrypted with AES-256-GCM. The master key is stored in your OS keychain (macOS Keychain, Linux secret-tool, Windows Credential Manager). Set `MCP_BRIDGE_MASTER_KEY` (64 hex chars) to use a static key instead.
422
+
423
+ **CLI commands:**
424
+
425
+ | Command | Description |
426
+ |---------|-------------|
427
+ | `credential set <key> [value]` | Store a plain string secret |
428
+ | `credential set <key> --json '<json>'` | Store a typed credential (bearer/oauth2/secret) |
429
+ | `credential get <key>` | Retrieve a credential (masked by default, `--show-secret` for full) |
430
+ | `credential delete <key>` | Delete a stored credential |
431
+ | `credential list` | List all stored credential keys |
432
+
433
+ Pipe-friendly: `echo "ghp_abc123" | crabeye-mcp-bridge credential set github-pat`
370
434
 
371
435
  ### Tool policies
372
436
 
@@ -406,18 +470,61 @@ Policies cascade in this order (first match wins):
406
470
 
407
471
  In this example, all Linear tools require confirmation except `list_issues` (runs freely) and `delete_issue` (blocked). Tools from other servers use the global default (`"always"`).
408
472
 
473
+ ### Rate limiting
474
+
475
+ Prevent the bridge from exceeding upstream API quotas by setting per-server rate limits. When the limit is hit, calls wait in a FIFO queue until the sliding window opens — the LLM just sees slightly higher latency instead of an error.
476
+
477
+ ```json
478
+ {
479
+ "upstreamMcpServers": {
480
+ "github": {
481
+ "command": "npx",
482
+ "args": ["-y", "@anthropic/github-mcp-server"],
483
+ "_bridge": {
484
+ "rateLimit": {
485
+ "maxCalls": 30,
486
+ "windowSeconds": 60
487
+ }
488
+ }
489
+ }
490
+ }
491
+ }
492
+ ```
493
+
494
+ In this example, the bridge allows at most 30 tool calls to the `github` server per 60-second sliding window. If a 31st call arrives before the window slides, it waits until a slot opens. If the wait exceeds 30 seconds, the call fails with an error.
495
+
496
+ Rate limit configuration is hot-reloadable — changes take effect without restarting the bridge.
497
+
498
+ ### Discovery mode
499
+
500
+ Control how searched tools are surfaced to the assistant with `--discovery-mode`:
501
+
502
+ - **`both`** (default) — Search results include tool names, descriptions, and full input schemas. Matching tools are also added to the MCP tools list so the assistant can call them directly.
503
+ - **`search`** — Search results include full tool details, but tools are NOT added to the MCP tools list. The assistant must use `run_tool` to execute them. Use this when your client doesn't handle dynamic tool list changes well.
504
+ - **`tools_list`** — Matching tools are added to the MCP tools list with full schemas, but search results omit `input_schema` to avoid duplication. The assistant calls discovered tools directly by their namespaced name, or via `run_tool`.
505
+
506
+ ```bash
507
+ npx @crabeye-ai/crabeye-mcp-bridge --config config.json --discovery-mode search
508
+ ```
509
+
409
510
  ## CLI
410
511
 
411
512
  ```
412
513
  npx @crabeye-ai/crabeye-mcp-bridge --config <path>
413
514
  ```
414
515
 
415
- | Flag | Description |
416
- |------|-------------|
516
+ | Flag / Subcommand | Description |
517
+ |-------------------|-------------|
417
518
  | `-c, --config <path>` | Path to config file (required, or set `MCP_BRIDGE_CONFIG`) |
418
519
  | `--validate` | Validate config and list upstream servers, then exit |
520
+ | `--stats` | Include `session_stats` in `search_tools` responses (always logged to stderr) |
521
+ | `--discovery-mode <mode>` | How searched tools are surfaced: `search`, `tools_list`, or `both` (default) |
419
522
  | `-V, --version` | Print version |
420
523
  | `-h, --help` | Print help |
524
+ | `credential set <key> [value]` | Store a credential (plain string, `--json` for typed, or pipe stdin) |
525
+ | `credential get <key>` | Retrieve a credential (`--show-secret` to unmask) |
526
+ | `credential delete <key>` | Delete a stored credential |
527
+ | `credential list` | List all stored credential keys |
421
528
 
422
529
  ### Validating your config
423
530