Skip to content

Commit d825ae4

Browse files
rodaddyclaude
andauthored
feat: v1.3 advanced features + WebSocket transport + batch command (#12)
* feat: v1.3 advanced features -- schema caching, access control, gateway resilience, output formats, skill auto-regen Phase 15 - Schema Intelligence (ADV-01, ADV-02): - Schema caching with 24hr TTL at ~/.cache/mcp2cli/schemas/ - SHA-256 drift detection with per-tool change alerts - Cache clear/status commands, --fresh bypass flag Phase 16 - Access Control & Discovery (ADV-05, INFRA-03): - allowTools/blockTools glob patterns in services.json - Cross-service tool search via `mcp2cli grep` - TOOL_BLOCKED errors for policy-restricted tools Phase 17 - Gateway Resilience (INFRA-01, INFRA-02): - HTTP gateway with stdio fallback config - Circuit breaker (5 failures, 60s cooldown, disk-persisted) Phase 18 - Output Formats (ADV-03, ADV-04): - --format table/yaml/csv/ndjson alongside default json - Errors always JSON regardless of format flag Phase 19 - Skill Auto-Regeneration (ADV-06): - Drift-triggered skill file regeneration - Manual section preservation via MANUAL:START/END markers - --diff preview flag, access control integration Security hardening from agent swarm review: - Path traversal protection on cache/circuit-breaker file paths - Input validation on schema command service/tool names - ReDoS mitigation in glob patterns (collapse wildcards, length guard, cache) - Circuit breaker state enum validation - YAML key escaping for injection prevention - Exhaustiveness guard on format switch 678 tests, 0 failures, 0 TypeScript errors across 79 source files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add example configs, generated skills, and fix test cache isolation Examples: - examples/services-basic.json -- single service config - examples/services-multi.json -- multi-service with access control - examples/services-http-fallback.json -- HTTP gateway with stdio fallback - examples/skills/qmd/ -- real generated skill for QMD (6 tools, 247 tokens) - examples/skills/n8n/ -- real generated skill for n8n (20 tools, 467 tokens) - examples/skills/vaultwarden-secrets/ -- real generated skill (11 tools, 328 tokens) Test isolation: - Fix 4 daemon test files leaking cache artifacts into ~/.cache/mcp2cli/ - All tests now use isolated MCP2CLI_CACHE_DIR via mkdtemp README: - Add description fields to all example config blocks Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add WebSocket transport and batch command WebSocket transport: - New "websocket" backend type in services.json config - Uses SDK's built-in WebSocketClientTransport (persistent connection) - Fallback to stdio with circuit breaker (same as HTTP) - Wired into daemon pool, schema, service-help, tool-call, generate-skills Batch command: - `mcp2cli batch` reads NDJSON tool calls from stdin - Executes sequentially by default, --parallel for concurrent execution - Outputs NDJSON results with service.tool correlation - Individual errors don't abort the batch 703 tests, 0 failures, 0 TypeScript errors across 81 source files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use direct imports for WebSocket transport to avoid CI module resolution failure The barrel re-export from connection/index.ts caused a cascading module evaluation failure in CI when the SDK's WebSocket module couldn't load. Direct imports from websocket-transport.ts avoid this -- callers only load the module when a websocket backend is actually configured. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ci): use explicit LiteLLM model aliases in claude-code-review workflow The claude-code-action expands 'sonnet' to 'claude-sonnet-4-6' internally, which isn't a registered alias in our LiteLLM proxy. Using 'sonnet4.6' and 'opus4.6' directly matches the LiteLLM model registry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: retrigger PR checks after runner migration to dedicated LXC 106 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ae390e7 commit d825ae4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+7415
-36
lines changed

.github/workflows/claude-code-review.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ jobs:
1919
env:
2020
ANTHROPIC_BASE_URL: http://10.71.20.53:4000
2121
ANTHROPIC_API_KEY: ${{ secrets.LITELLM_API_KEY }}
22-
ANTHROPIC_MODEL: sonnet
23-
ANTHROPIC_DEFAULT_SONNET_MODEL: sonnet
24-
ANTHROPIC_DEFAULT_OPUS_MODEL: opus
22+
ANTHROPIC_MODEL: sonnet4.6
23+
ANTHROPIC_DEFAULT_SONNET_MODEL: sonnet4.6
24+
ANTHROPIC_DEFAULT_OPUS_MODEL: opus4.6
2525
ANTHROPIC_DEFAULT_HAIKU_MODEL: haiku
2626
steps:
2727
- name: Checkout
@@ -34,7 +34,7 @@ jobs:
3434
with:
3535
anthropic_api_key: ${{ secrets.LITELLM_API_KEY }}
3636
github_token: ${{ secrets.GITHUB_TOKEN }}
37-
model: "sonnet"
37+
model: "sonnet4.6"
3838
direct_prompt: |
3939
Review this PR for the mcp2cli project (CLI bridge for MCP servers). Focus on:
4040
1. Bugs and logic errors

README.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ mcp2cli discovers MCP servers from `~/.config/mcp2cli/services.json`:
5151
{
5252
"services": {
5353
"n8n": {
54+
"description": "n8n workflow automation",
5455
"backend": "stdio",
5556
"command": "npx",
5657
"args": ["-y", "@anthropic-ai/n8n-mcp"],
@@ -60,6 +61,7 @@ mcp2cli discovers MCP servers from `~/.config/mcp2cli/services.json`:
6061
}
6162
},
6263
"homekit": {
64+
"description": "HomeKit smart home control",
6365
"backend": "stdio",
6466
"command": "node",
6567
"args": ["/path/to/homekit-mcp/dist/index.js"],
@@ -249,6 +251,177 @@ mcp2cli n8n n8n_get_workflow --params '{"id": "abc123"}'
249251

250252
This pattern keeps MCP tool definitions out of the agent's system prompt entirely. The agent only pays context cost when it actually needs to call a tool, and even then only for the specific tool's schema -- not all tools from all servers.
251253

254+
## v1.3 Advanced Features
255+
256+
### Schema Caching
257+
258+
Schemas are cached locally to avoid re-fetching on every invocation. Cached schemas live at `~/.cache/mcp2cli/schemas/` with a 24-hour TTL. Cache drift is detected via SHA-256 hashing -- if the upstream schema changes, the cache is automatically invalidated.
259+
260+
```bash
261+
# Check cache status (age, TTL, drift)
262+
mcp2cli cache status
263+
264+
# Clear all cached schemas
265+
mcp2cli cache clear
266+
267+
# Clear cache for a specific service
268+
mcp2cli cache clear n8n
269+
270+
# Bypass cache for a single schema lookup
271+
mcp2cli schema n8n.n8n_list_workflows --fresh
272+
```
273+
274+
Override the cache directory with `MCP2CLI_CACHE_DIR`.
275+
276+
### Access Control
277+
278+
Restrict which tools are exposed per service using `allowTools` and `blockTools` in `services.json`. Both accept glob patterns.
279+
280+
```json
281+
{
282+
"services": {
283+
"n8n": {
284+
"description": "n8n workflow automation",
285+
"backend": "stdio",
286+
"command": "npx",
287+
"args": ["-y", "@anthropic/n8n-mcp"],
288+
"allowTools": ["n8n_list_*", "n8n_get_*"],
289+
"blockTools": ["n8n_delete_*"]
290+
}
291+
}
292+
}
293+
```
294+
295+
When both are present, `allowTools` is evaluated first (whitelist), then `blockTools` removes matches from the allowed set.
296+
297+
#### Cross-Service Tool Search
298+
299+
Search for tools across all services using cached schemas:
300+
301+
```bash
302+
# Find all tools matching a pattern
303+
mcp2cli grep "workflow"
304+
305+
# Regex patterns work
306+
mcp2cli grep "delete|remove"
307+
```
308+
309+
This searches cached schemas only -- no MCP connections are made.
310+
311+
### WebSocket Transport
312+
313+
Connect to MCP servers over WebSocket. Supports optional stdio fallback and access control, same as HTTP.
314+
315+
```json
316+
{
317+
"services": {
318+
"remote-mcp": {
319+
"description": "Remote MCP server via WebSocket",
320+
"backend": "websocket",
321+
"url": "ws://mcp-gateway.local:3000/mcp",
322+
"fallback": {
323+
"command": "npx",
324+
"args": ["-y", "@anthropic/n8n-mcp"]
325+
}
326+
}
327+
}
328+
}
329+
```
330+
331+
WebSocket services benefit from the same circuit breaker and fallback behavior as HTTP services.
332+
333+
### Batch Tool Calls
334+
335+
Execute multiple tool calls in a single invocation by piping NDJSON to `mcp2cli batch`. Each line is a JSON object with `service`, `tool`, and `params` fields:
336+
337+
```bash
338+
# Sequential execution (default)
339+
cat <<EOF | mcp2cli batch
340+
{"service": "n8n", "tool": "n8n_list_workflows", "params": {}}
341+
{"service": "n8n", "tool": "n8n_get_workflow", "params": {"id": "1"}}
342+
EOF
343+
344+
# Parallel execution
345+
cat <<EOF | mcp2cli batch --parallel
346+
{"service": "n8n", "tool": "n8n_list_workflows", "params": {}}
347+
{"service": "n8n", "tool": "n8n_get_workflow", "params": {"id": "1"}}
348+
EOF
349+
```
350+
351+
Output is NDJSON -- one result per line with the original service/tool for correlation:
352+
353+
```json
354+
{"service":"n8n","tool":"n8n_list_workflows","success":true,"result":{...}}
355+
{"service":"n8n","tool":"n8n_get_workflow","success":true,"result":{...}}
356+
```
357+
358+
Errors for individual calls are reported inline without aborting the batch.
359+
360+
### Gateway Resilience
361+
362+
HTTP/SSE services can define a `fallback` stdio config. If the remote gateway is unreachable, mcp2cli transparently falls back to a local MCP server process.
363+
364+
```json
365+
{
366+
"services": {
367+
"n8n": {
368+
"description": "n8n via HTTP gateway with stdio fallback",
369+
"backend": "http",
370+
"url": "http://mcp-gateway:3000/n8n",
371+
"fallback": {
372+
"command": "npx",
373+
"args": ["-y", "@anthropic/n8n-mcp"]
374+
}
375+
}
376+
}
377+
}
378+
```
379+
380+
A circuit breaker protects against repeated failures: after 5 consecutive failures the circuit opens and routes directly to fallback for 60 seconds before re-probing the primary. Circuit state is persisted to `~/.cache/mcp2cli/circuit-breaker/` so it survives process restarts.
381+
382+
### Output Formats
383+
384+
Control output format with the `--format` flag:
385+
386+
```bash
387+
mcp2cli n8n n8n_list_workflows --params '{}' --format table
388+
mcp2cli n8n n8n_list_workflows --params '{}' --format yaml
389+
mcp2cli n8n n8n_list_workflows --params '{}' --format csv
390+
mcp2cli n8n n8n_list_workflows --params '{}' --format ndjson
391+
```
392+
393+
| Format | Description |
394+
|--------|-------------|
395+
| `json` | Default. Structured JSON (unchanged from v1.0) |
396+
| `table` | Aligned columns -- human-readable terminal output |
397+
| `yaml` | YAML output |
398+
| `csv` | RFC 4180 CSV -- pipe to spreadsheets or `csvtool` |
399+
| `ndjson` | One JSON object per line -- for streaming pipelines |
400+
401+
Error responses are always JSON regardless of the `--format` flag.
402+
403+
### Skill Auto-Regeneration
404+
405+
Generated skill files can be previewed and kept in sync with upstream schema changes:
406+
407+
```bash
408+
# Preview what would change without writing
409+
mcp2cli generate-skills --diff n8n
410+
411+
# Regenerate (preserves manual sections)
412+
mcp2cli generate-skills n8n
413+
```
414+
415+
Manual edits inside `MANUAL:START` / `MANUAL:END` markers are preserved across regeneration. When schema drift is detected (via the caching layer), skill regeneration can be triggered automatically.
416+
417+
## v1.3 Environment Variables
418+
419+
In addition to the variables listed above, v1.3 adds:
420+
421+
| Variable | Default | Description |
422+
|----------|---------|-------------|
423+
| `MCP2CLI_CACHE_DIR` | `~/.cache/mcp2cli` | Base directory for schema cache and circuit breaker state |
424+
252425
## Development
253426

254427
```bash

examples/services-basic.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"services": {
3+
"n8n": {
4+
"description": "n8n workflow automation",
5+
"backend": "stdio",
6+
"command": "npx",
7+
"args": ["-y", "@anthropic/n8n-mcp"]
8+
}
9+
}
10+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"services": {
3+
"n8n": {
4+
"description": "n8n via HTTP gateway with stdio fallback",
5+
"backend": "http",
6+
"url": "http://mcp-gateway.local:3000/n8n",
7+
"fallback": {
8+
"command": "npx",
9+
"args": ["-y", "@anthropic/n8n-mcp"]
10+
}
11+
}
12+
}
13+
}

examples/services-multi.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"services": {
3+
"n8n": {
4+
"description": "n8n workflow automation",
5+
"backend": "stdio",
6+
"command": "npx",
7+
"args": ["-y", "@anthropic/n8n-mcp"],
8+
"allowTools": ["n8n_list_*", "n8n_get_*", "n8n_search_*"],
9+
"blockTools": ["n8n_delete_*"]
10+
},
11+
"qmd": {
12+
"description": "QMD document search and retrieval",
13+
"backend": "stdio",
14+
"command": "qmd",
15+
"args": ["mcp"]
16+
}
17+
}
18+
}

examples/services-websocket.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"services": {
3+
"remote-mcp": {
4+
"description": "Remote MCP server via WebSocket",
5+
"backend": "websocket",
6+
"url": "ws://mcp-gateway.local:3000/mcp",
7+
"fallback": {
8+
"command": "npx",
9+
"args": ["-y", "@anthropic/n8n-mcp"]
10+
}
11+
}
12+
}
13+
}

examples/skills/n8n/SKILL.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
name: n8n
3+
description: MCP tools for n8n
4+
triggers:
5+
- n8n
6+
- workflow
7+
- node
8+
- detail
9+
- levels
10+
- multiple
11+
- modes
12+
- template
13+
---
14+
15+
# n8n
16+
17+
MCP tools for n8n
18+
19+
<!-- AUTO-GENERATED:START -->
20+
21+
## Quick Reference
22+
23+
| Tool | Description |
24+
|------|-------------|
25+
| get_node | Get node info with progressive detail levels and multiple modes. |
26+
| get_template | Get template by ID. |
27+
| n8n_autofix_workflow | Automatically fix common workflow validation errors. |
28+
| n8n_create_workflow | Create workflow. |
29+
| n8n_delete_workflow | Permanently delete a workflow. |
30+
| n8n_deploy_template | Deploy a workflow template from n8n. |
31+
| n8n_executions | Manage workflow executions: get details, list, or delete. |
32+
| n8n_get_workflow | Get workflow by ID with different detail levels. |
33+
| n8n_health_check | Check n8n instance health and API connectivity. |
34+
| n8n_list_workflows | List workflows (minimal metadata only). |
35+
| n8n_test_workflow | Test/trigger workflow execution. |
36+
| n8n_update_full_workflow | Full workflow update. |
37+
| n8n_update_partial_workflow | Update workflow incrementally with diff operations. |
38+
| n8n_validate_workflow | Validate workflow by ID. |
39+
| n8n_workflow_versions | Manage workflow version history, rollback, and cleanup. |
40+
| search_nodes | Search n8n nodes by keyword with optional real-world examples. |
41+
| search_templates | Search templates with multiple modes. |
42+
| tools_documentation | Get documentation for n8n MCP tools. |
43+
| validate_node | Validate n8n node configuration. |
44+
| validate_workflow | Full workflow validation: structure, connections, expressions, AI tools. |
45+
46+
## Usage
47+
48+
```bash
49+
mcp2cli n8n <tool> --params '{...}'
50+
```
51+
52+
See `references/` for detailed parameter docs per tool.
53+
54+
<!-- AUTO-GENERATED:END -->
55+
56+
## Notes
57+
58+
<!-- MANUAL:START -->
59+
<!-- Add your custom notes, examples, or overrides here -->
60+
<!-- MANUAL:END -->

0 commit comments

Comments
 (0)