mcp-to-cli 0.1.0__tar.gz

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.
Files changed (89) hide show
  1. mcp_to_cli-0.1.0/.gitignore +43 -0
  2. mcp_to_cli-0.1.0/CLAUDE.md +9 -0
  3. mcp_to_cli-0.1.0/LICENSE +21 -0
  4. mcp_to_cli-0.1.0/PKG-INFO +191 -0
  5. mcp_to_cli-0.1.0/README.md +164 -0
  6. mcp_to_cli-0.1.0/mcp2cli/__init__.py +3 -0
  7. mcp_to_cli-0.1.0/mcp2cli/cli/__init__.py +0 -0
  8. mcp_to_cli-0.1.0/mcp2cli/cli/mapping.py +82 -0
  9. mcp_to_cli-0.1.0/mcp2cli/cli/resolver.py +342 -0
  10. mcp_to_cli-0.1.0/mcp2cli/config/__init__.py +0 -0
  11. mcp_to_cli-0.1.0/mcp2cli/config/models.py +153 -0
  12. mcp_to_cli-0.1.0/mcp2cli/config/reader.py +132 -0
  13. mcp_to_cli-0.1.0/mcp2cli/config/tool_store.py +32 -0
  14. mcp_to_cli-0.1.0/mcp2cli/constants.py +47 -0
  15. mcp_to_cli-0.1.0/mcp2cli/converter/__init__.py +0 -0
  16. mcp_to_cli-0.1.0/mcp2cli/converter/config_disabler.py +91 -0
  17. mcp_to_cli-0.1.0/mcp2cli/converter/config_extractor.py +66 -0
  18. mcp_to_cli-0.1.0/mcp2cli/daemon/__init__.py +0 -0
  19. mcp_to_cli-0.1.0/mcp2cli/daemon/client.py +98 -0
  20. mcp_to_cli-0.1.0/mcp2cli/daemon/lifecycle.py +113 -0
  21. mcp_to_cli-0.1.0/mcp2cli/daemon/pool.py +144 -0
  22. mcp_to_cli-0.1.0/mcp2cli/daemon/server.py +168 -0
  23. mcp_to_cli-0.1.0/mcp2cli/generator/__init__.py +0 -0
  24. mcp_to_cli-0.1.0/mcp2cli/generator/cli_gen.py +202 -0
  25. mcp_to_cli-0.1.0/mcp2cli/generator/llm_backend.py +361 -0
  26. mcp_to_cli-0.1.0/mcp2cli/generator/skill_gen.py +295 -0
  27. mcp_to_cli-0.1.0/mcp2cli/generator/templates/cli_gen_example.md +235 -0
  28. mcp_to_cli-0.1.0/mcp2cli/generator/templates/cli_gen_skill.md +136 -0
  29. mcp_to_cli-0.1.0/mcp2cli/generator/templates/skill_gen_example.md +217 -0
  30. mcp_to_cli-0.1.0/mcp2cli/generator/templates/skill_gen_skill.md +112 -0
  31. mcp_to_cli-0.1.0/mcp2cli/generator/validator.py +210 -0
  32. mcp_to_cli-0.1.0/mcp2cli/installer/__init__.py +0 -0
  33. mcp_to_cli-0.1.0/mcp2cli/installer/ai_search.py +233 -0
  34. mcp_to_cli-0.1.0/mcp2cli/installer/interactive.py +65 -0
  35. mcp_to_cli-0.1.0/mcp2cli/installer/pipeline.py +161 -0
  36. mcp_to_cli-0.1.0/mcp2cli/installer/servers_writer.py +70 -0
  37. mcp_to_cli-0.1.0/mcp2cli/installer/skill_sync.py +87 -0
  38. mcp_to_cli-0.1.0/mcp2cli/main.py +890 -0
  39. mcp_to_cli-0.1.0/mcp2cli/preset/__init__.py +0 -0
  40. mcp_to_cli-0.1.0/mcp2cli/preset/checker.py +67 -0
  41. mcp_to_cli-0.1.0/mcp2cli/preset/downloader.py +158 -0
  42. mcp_to_cli-0.1.0/mcp2cli/preset/exporter.py +79 -0
  43. mcp_to_cli-0.1.0/mcp2cli/preset/github.py +88 -0
  44. mcp_to_cli-0.1.0/mcp2cli/preset/local.py +27 -0
  45. mcp_to_cli-0.1.0/mcp2cli/preset/models.py +126 -0
  46. mcp_to_cli-0.1.0/mcp2cli/preset/pusher.py +232 -0
  47. mcp_to_cli-0.1.0/mcp2cli/preset/registry.py +112 -0
  48. mcp_to_cli-0.1.0/mcp2cli/preset/version.py +41 -0
  49. mcp_to_cli-0.1.0/mcp2cli/remover/__init__.py +0 -0
  50. mcp_to_cli-0.1.0/mcp2cli/remover/cleaner.py +109 -0
  51. mcp_to_cli-0.1.0/mcp2cli/remover/config_re_enabler.py +92 -0
  52. mcp_to_cli-0.1.0/mcp2cli/remover/package_purger.py +73 -0
  53. mcp_to_cli-0.1.0/mcp2cli/remover/pipeline.py +96 -0
  54. mcp_to_cli-0.1.0/mcp2cli/remover/scanner.py +146 -0
  55. mcp_to_cli-0.1.0/mcp2cli/scanner.py +70 -0
  56. mcp_to_cli-0.1.0/mcp2cli/ui/__init__.py +0 -0
  57. mcp_to_cli-0.1.0/mcp2cli/ui/progress.py +118 -0
  58. mcp_to_cli-0.1.0/mcp2cli/updater/__init__.py +0 -0
  59. mcp_to_cli-0.1.0/mcp2cli/updater/diff.py +81 -0
  60. mcp_to_cli-0.1.0/mcp2cli/updater/pipeline.py +184 -0
  61. mcp_to_cli-0.1.0/mcp2cli/utils/__init__.py +18 -0
  62. mcp_to_cli-0.1.0/mcp2cli/utils/file_ops.py +87 -0
  63. mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/cli.yaml +38 -0
  64. mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/manifest.json +15 -0
  65. mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/SKILL.md +44 -0
  66. mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/reference/diagram.md +61 -0
  67. mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/reference/session.md +11 -0
  68. mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/users/.gitkeep +0 -0
  69. mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/users/SKILL.md +4 -0
  70. mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/tools.json +110 -0
  71. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/cli.yaml +281 -0
  72. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/manifest.json +21 -0
  73. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/SKILL.md +56 -0
  74. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/confluence-attachment.md +47 -0
  75. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/confluence-page.md +81 -0
  76. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/confluence.md +52 -0
  77. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-board.md +22 -0
  78. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-issue.md +162 -0
  79. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-misc.md +74 -0
  80. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-project.md +33 -0
  81. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-sprint.md +45 -0
  82. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/users/.gitkeep +0 -0
  83. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/users/SKILL.md +4 -0
  84. mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/tools.json +2003 -0
  85. mcp_to_cli-0.1.0/pyproject.toml +51 -0
  86. mcp_to_cli-0.1.0/tests/__init__.py +0 -0
  87. mcp_to_cli-0.1.0/tests/test_dynamic_cli.py +23 -0
  88. mcp_to_cli-0.1.0/tests/test_preset_version.py +178 -0
  89. mcp_to_cli-0.1.0/uv.lock +740 -0
@@ -0,0 +1,43 @@
1
+ # IDE
2
+ .idea/
3
+ .vscode/
4
+ *.swp
5
+ *.swo
6
+
7
+ # Python
8
+ __pycache__/
9
+ *.py[cod]
10
+ *$py.class
11
+ *.so
12
+ *.egg-info/
13
+ *.egg
14
+ dist/
15
+ build/
16
+ .eggs/
17
+
18
+ # Virtual environments
19
+ .venv/
20
+ venv/
21
+ ENV/
22
+
23
+ # Testing
24
+ .pytest_cache/
25
+ .coverage
26
+ htmlcov/
27
+ .tox/
28
+ .nox/
29
+
30
+ # Type checking
31
+ .mypy_cache/
32
+ .pytype/
33
+
34
+ # Distribution
35
+ *.tar.gz
36
+ *.whl
37
+
38
+ # OS
39
+ .DS_Store
40
+ Thumbs.db
41
+
42
+ # Design Doc
43
+ design/
@@ -0,0 +1,9 @@
1
+ # CLAUDE.md
2
+
3
+ ## Design Document Rules
4
+
5
+ 1. **After modifying any sub-design MD file under `design/`, you must also update `design/0.0-design-overview.md`** to keep the overview consistent with the sub-documents. Design documents are written in Chinese.
6
+
7
+ ## Language Rules
8
+
9
+ 1. **Everything outside the `design/` folder must be written in English**, including code comments, examples, commit messages, etc.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mengxiangyu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-to-cli
3
+ Version: 0.1.0
4
+ Summary: Convert MCP server tools into hierarchical CLI commands and agent Skills
5
+ Project-URL: Homepage, https://github.com/makabakaxy/mcp2skill
6
+ Project-URL: Repository, https://github.com/makabakaxy/mcp2skill
7
+ Project-URL: Issues, https://github.com/makabakaxy/mcp2skill/issues
8
+ Author: oliver.mengxy@gmail.com
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,ai-tools,cli,llm,mcp,model-context-protocol,skill
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: click>=8.1
24
+ Requires-Dist: mcp>=1.0
25
+ Requires-Dist: pyyaml>=6.0
26
+ Description-Content-Type: text/markdown
27
+
28
+ <!-- Keywords: mcp2cli mcp2skill mcp-to-skill mcp-to-cli mcpcli mcp to skill mcp to cli mcp 2 cli mcp 2 skill -->
29
+
30
+ # mcp2cli
31
+
32
+ > Also known as: **mcp2skill** · **mcp-to-cli** · **mcp-to-skill** · **mcpcli**
33
+
34
+ Convert MCP servers into CLI commands and compact AI agent skills.
35
+
36
+ ## Why
37
+
38
+ For example, install [zereight/gitlab-mcp](https://github.com/zereight/gitlab-mcp) — it exposes **122 tools** across 14 categories (merge requests, issues, pipelines, wikis, etc.). Every tool schema gets injected into your AI conversation context on every request. We measured this directly against the Claude API:
39
+
40
+ | Per-request input tokens | Before (raw MCP) | After (mcp2cli) |
41
+ |---|---|---|
42
+ | Your message | 20 | 20 |
43
+ | Tool definitions (122 tools) | 27,969 | — |
44
+ | Skill file (1 file) | — | ~800 |
45
+ | **Total** | **27,989** | **~820** |
46
+ | **Reduction** | | **~97%** |
47
+
48
+ After `mcp2cli convert`, your AI agent stops seeing 122 tool definitions. Instead, it reads one small skill file, and calls CLI commands like `mcp2cli gitlab mr create --project-id 123 --title "Fix bug"` to get the job done.
49
+
50
+ Beyond token savings, some projects maintain both a CLI and an MCP server in parallel (e.g. the GitLab MCP server vs. the `glab` CLI). Keeping two interfaces in sync is a maintenance burden and inevitably leads to feature drift. mcp2cli eliminates the need — one MCP server, one generated CLI, always consistent.
51
+
52
+ ## Quick Start
53
+
54
+ ```bash
55
+ pip install mcp2skill
56
+ ```
57
+
58
+ If you already have an MCP server configured in Claude, Cursor, or Codex:
59
+
60
+ ```bash
61
+ mcp2cli list # See which MCP servers are available
62
+ mcp2cli convert gitlab-mcp
63
+ ```
64
+
65
+ That's it. Your MCP server is now a CLI, and the compressed skill files are synced to your AI clients.
66
+
67
+ ## How It Works
68
+
69
+ `mcp2cli convert gitlab-mcp` runs a 3-phase pipeline:
70
+
71
+ ```
72
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
73
+ │ 1. Extract │─────>│ 2. Generate │─────>│ 3. Sync │
74
+ │ │ │ │ │ │
75
+ │ Read config │ │ AI-generate │ │ Copy skills, │
76
+ │ from Claude,│ │ CLI + skill │ │ disable MCP │
77
+ │ Cursor,Codex│ │ │ │ │
78
+ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
79
+ v v v
80
+ mcp_servers.json cli.yaml + SKILL.md ~/.claude/skills/
81
+ ```
82
+
83
+ 1. **Extract** — Reads your MCP server config from Claude (`~/.claude.json`) / Cursor (`~/.cursor/mcp.json`) / Codex (`~/.codex/config.toml`)
84
+ 2. **Generate** — Connects to the MCP server, discovers all tools, and uses AI to generate a CLI command tree (`cli.yaml`) and a compressed skill file (`SKILL.md`)
85
+ 3. **Sync** — Copies skill files to your AI clients and disables the raw MCP server
86
+
87
+ Each skill directory contains a `users/` subdirectory where you can add your own notes and workflows. This directory is never overwritten by `mcp2cli`.
88
+
89
+ At runtime, the generated CLI resolves commands to MCP tool calls through a lightweight daemon:
90
+
91
+ ```
92
+ mcp2cli gitlab mr list --project-id 123
93
+
94
+ │ resolve via cli.yaml
95
+ v
96
+ tool: gitlab_list_merge_requests(project_id=123)
97
+
98
+ v
99
+ ┌─────────┐ MCP protocol ┌────────────┐
100
+ │ mcp2cli │ ──────────────────> │ MCP Server │
101
+ │ daemon │ <────────────────── │ (gitlab) │
102
+ └─────────┘ JSON result └────────────┘
103
+ ```
104
+
105
+ The daemon starts automatically on first use and stops when idle.
106
+
107
+ ## Presets — Pre-built Skills, Download in Seconds
108
+
109
+ Don't want to wait for AI generation (~2-3 min)? Use **presets** — pre-built CLI mappings + skill files shared by the community. Downloads in ~10 seconds.
110
+
111
+ ```bash
112
+ mcp2cli preset list # Browse available presets
113
+ mcp2cli preset pull mcp-atlassian # Download + sync to AI clients
114
+ mcp2cli preset pull mcp-atlassian@1.2.3 # Pin a specific version
115
+ mcp2cli preset push gitlab-mcp # Share your result with others
116
+ ```
117
+
118
+ During `convert` and `install`, presets are checked automatically — if one exists, you can skip AI generation entirely:
119
+
120
+ ```
121
+ mcp2cli convert/install
122
+ |
123
+ preset-check ─── found? ─── yes ──→ download preset (~10s)
124
+ | |
125
+ no |
126
+ | |
127
+ scan → generate cli → generate skill |
128
+ (~2-3 min) |
129
+ | |
130
+ └──────────────→ skill sync ←──────────┘
131
+ ```
132
+
133
+ Custom registry for private/team use:
134
+
135
+ ```bash
136
+ mcp2cli preset registry set https://github.com/your-org/mcp2cli-presets
137
+ ```
138
+
139
+ ## Install — Add New MCP Servers
140
+
141
+ `convert` works with servers already configured in your AI clients. For MCP servers you haven't set up yet, use `install` — it searches the internet for installation info, prompts for env vars, then runs the full conversion pipeline:
142
+
143
+ ```bash
144
+ mcp2cli install mcp-atlassian
145
+ ```
146
+
147
+ ## Usage Examples
148
+
149
+ ```bash
150
+ # List all configured local MCP servers
151
+ mcp2cli list
152
+
153
+ # Convert a server (auto-detects config from all clients)
154
+ mcp2cli convert gitlab-mcp
155
+
156
+ # Use the generated CLI
157
+ mcp2cli gitlab mr list --project-id 123
158
+ mcp2cli gitlab issue create --title "Fix login bug" --project-id 123
159
+
160
+ # Update when the MCP server adds new tools
161
+ mcp2cli update gitlab-mcp
162
+
163
+ # Remove everything (CLI, skills, config)
164
+ mcp2cli remove gitlab-mcp
165
+ ```
166
+
167
+ ## Commands
168
+
169
+ | Command | Description |
170
+ |---------|-------------|
171
+ | `convert <server>` | Convert an MCP server to skill-based usage |
172
+ | `install <server>` | Install a new MCP server and generate skills |
173
+ | `update <server>` | Update tools and regenerate CLI + skills |
174
+ | `remove <server>` | Remove a server and all generated artifacts |
175
+ | `list` | List all configured MCP servers |
176
+ | `scan <server>` | Discover all tools from an MCP server |
177
+ | `tools <server>` | List tools or show tool details |
178
+ | `call <server> <tool>` | Call an MCP tool directly |
179
+ | `generate cli <server>` | (Re)generate the CLI command tree |
180
+ | `generate skill <server>` | (Re)generate skill files |
181
+ | `skill sync <server>` | Sync skill files to AI clients |
182
+ | `skill unsync <server>` | Remove synced skills and re-enable MCP server |
183
+ | `preset list [server]` | Browse available presets (local + remote) |
184
+ | `preset pull <name[@ver]>` | Download a preset, skip AI generation |
185
+ | `preset export <server>` | Export a preset bundle to a local directory |
186
+ | `preset push <server>` | Push local preset to community registry |
187
+ | `validate <server>` | Validate CLI mapping and skill files |
188
+
189
+ ## License
190
+
191
+ MIT
@@ -0,0 +1,164 @@
1
+ <!-- Keywords: mcp2cli mcp2skill mcp-to-skill mcp-to-cli mcpcli mcp to skill mcp to cli mcp 2 cli mcp 2 skill -->
2
+
3
+ # mcp2cli
4
+
5
+ > Also known as: **mcp2skill** · **mcp-to-cli** · **mcp-to-skill** · **mcpcli**
6
+
7
+ Convert MCP servers into CLI commands and compact AI agent skills.
8
+
9
+ ## Why
10
+
11
+ For example, install [zereight/gitlab-mcp](https://github.com/zereight/gitlab-mcp) — it exposes **122 tools** across 14 categories (merge requests, issues, pipelines, wikis, etc.). Every tool schema gets injected into your AI conversation context on every request. We measured this directly against the Claude API:
12
+
13
+ | Per-request input tokens | Before (raw MCP) | After (mcp2cli) |
14
+ |---|---|---|
15
+ | Your message | 20 | 20 |
16
+ | Tool definitions (122 tools) | 27,969 | — |
17
+ | Skill file (1 file) | — | ~800 |
18
+ | **Total** | **27,989** | **~820** |
19
+ | **Reduction** | | **~97%** |
20
+
21
+ After `mcp2cli convert`, your AI agent stops seeing 122 tool definitions. Instead, it reads one small skill file, and calls CLI commands like `mcp2cli gitlab mr create --project-id 123 --title "Fix bug"` to get the job done.
22
+
23
+ Beyond token savings, some projects maintain both a CLI and an MCP server in parallel (e.g. the GitLab MCP server vs. the `glab` CLI). Keeping two interfaces in sync is a maintenance burden and inevitably leads to feature drift. mcp2cli eliminates the need — one MCP server, one generated CLI, always consistent.
24
+
25
+ ## Quick Start
26
+
27
+ ```bash
28
+ pip install mcp2skill
29
+ ```
30
+
31
+ If you already have an MCP server configured in Claude, Cursor, or Codex:
32
+
33
+ ```bash
34
+ mcp2cli list # See which MCP servers are available
35
+ mcp2cli convert gitlab-mcp
36
+ ```
37
+
38
+ That's it. Your MCP server is now a CLI, and the compressed skill files are synced to your AI clients.
39
+
40
+ ## How It Works
41
+
42
+ `mcp2cli convert gitlab-mcp` runs a 3-phase pipeline:
43
+
44
+ ```
45
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
46
+ │ 1. Extract │─────>│ 2. Generate │─────>│ 3. Sync │
47
+ │ │ │ │ │ │
48
+ │ Read config │ │ AI-generate │ │ Copy skills, │
49
+ │ from Claude,│ │ CLI + skill │ │ disable MCP │
50
+ │ Cursor,Codex│ │ │ │ │
51
+ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
52
+ v v v
53
+ mcp_servers.json cli.yaml + SKILL.md ~/.claude/skills/
54
+ ```
55
+
56
+ 1. **Extract** — Reads your MCP server config from Claude (`~/.claude.json`) / Cursor (`~/.cursor/mcp.json`) / Codex (`~/.codex/config.toml`)
57
+ 2. **Generate** — Connects to the MCP server, discovers all tools, and uses AI to generate a CLI command tree (`cli.yaml`) and a compressed skill file (`SKILL.md`)
58
+ 3. **Sync** — Copies skill files to your AI clients and disables the raw MCP server
59
+
60
+ Each skill directory contains a `users/` subdirectory where you can add your own notes and workflows. This directory is never overwritten by `mcp2cli`.
61
+
62
+ At runtime, the generated CLI resolves commands to MCP tool calls through a lightweight daemon:
63
+
64
+ ```
65
+ mcp2cli gitlab mr list --project-id 123
66
+
67
+ │ resolve via cli.yaml
68
+ v
69
+ tool: gitlab_list_merge_requests(project_id=123)
70
+
71
+ v
72
+ ┌─────────┐ MCP protocol ┌────────────┐
73
+ │ mcp2cli │ ──────────────────> │ MCP Server │
74
+ │ daemon │ <────────────────── │ (gitlab) │
75
+ └─────────┘ JSON result └────────────┘
76
+ ```
77
+
78
+ The daemon starts automatically on first use and stops when idle.
79
+
80
+ ## Presets — Pre-built Skills, Download in Seconds
81
+
82
+ Don't want to wait for AI generation (~2-3 min)? Use **presets** — pre-built CLI mappings + skill files shared by the community. Downloads in ~10 seconds.
83
+
84
+ ```bash
85
+ mcp2cli preset list # Browse available presets
86
+ mcp2cli preset pull mcp-atlassian # Download + sync to AI clients
87
+ mcp2cli preset pull mcp-atlassian@1.2.3 # Pin a specific version
88
+ mcp2cli preset push gitlab-mcp # Share your result with others
89
+ ```
90
+
91
+ During `convert` and `install`, presets are checked automatically — if one exists, you can skip AI generation entirely:
92
+
93
+ ```
94
+ mcp2cli convert/install
95
+ |
96
+ preset-check ─── found? ─── yes ──→ download preset (~10s)
97
+ | |
98
+ no |
99
+ | |
100
+ scan → generate cli → generate skill |
101
+ (~2-3 min) |
102
+ | |
103
+ └──────────────→ skill sync ←──────────┘
104
+ ```
105
+
106
+ Custom registry for private/team use:
107
+
108
+ ```bash
109
+ mcp2cli preset registry set https://github.com/your-org/mcp2cli-presets
110
+ ```
111
+
112
+ ## Install — Add New MCP Servers
113
+
114
+ `convert` works with servers already configured in your AI clients. For MCP servers you haven't set up yet, use `install` — it searches the internet for installation info, prompts for env vars, then runs the full conversion pipeline:
115
+
116
+ ```bash
117
+ mcp2cli install mcp-atlassian
118
+ ```
119
+
120
+ ## Usage Examples
121
+
122
+ ```bash
123
+ # List all configured local MCP servers
124
+ mcp2cli list
125
+
126
+ # Convert a server (auto-detects config from all clients)
127
+ mcp2cli convert gitlab-mcp
128
+
129
+ # Use the generated CLI
130
+ mcp2cli gitlab mr list --project-id 123
131
+ mcp2cli gitlab issue create --title "Fix login bug" --project-id 123
132
+
133
+ # Update when the MCP server adds new tools
134
+ mcp2cli update gitlab-mcp
135
+
136
+ # Remove everything (CLI, skills, config)
137
+ mcp2cli remove gitlab-mcp
138
+ ```
139
+
140
+ ## Commands
141
+
142
+ | Command | Description |
143
+ |---------|-------------|
144
+ | `convert <server>` | Convert an MCP server to skill-based usage |
145
+ | `install <server>` | Install a new MCP server and generate skills |
146
+ | `update <server>` | Update tools and regenerate CLI + skills |
147
+ | `remove <server>` | Remove a server and all generated artifacts |
148
+ | `list` | List all configured MCP servers |
149
+ | `scan <server>` | Discover all tools from an MCP server |
150
+ | `tools <server>` | List tools or show tool details |
151
+ | `call <server> <tool>` | Call an MCP tool directly |
152
+ | `generate cli <server>` | (Re)generate the CLI command tree |
153
+ | `generate skill <server>` | (Re)generate skill files |
154
+ | `skill sync <server>` | Sync skill files to AI clients |
155
+ | `skill unsync <server>` | Remove synced skills and re-enable MCP server |
156
+ | `preset list [server]` | Browse available presets (local + remote) |
157
+ | `preset pull <name[@ver]>` | Download a preset, skip AI generation |
158
+ | `preset export <server>` | Export a preset bundle to a local directory |
159
+ | `preset push <server>` | Push local preset to community registry |
160
+ | `validate <server>` | Validate CLI mapping and skill files |
161
+
162
+ ## License
163
+
164
+ MIT
@@ -0,0 +1,3 @@
1
+ """mcp2cli - Convert MCP server tools into hierarchical CLI commands and agent Skills."""
2
+
3
+ __version__ = "0.1.0"
File without changes
@@ -0,0 +1,82 @@
1
+ """Read and write CLI mapping YAML files."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ from pathlib import Path
7
+
8
+ import yaml
9
+
10
+ from mcp2cli.constants import CLI_DIR
11
+ from mcp2cli.utils import safe_filename
12
+
13
+
14
+ def cli_path(server_name: str) -> Path:
15
+ return CLI_DIR / f"{safe_filename(server_name)}.yaml"
16
+
17
+
18
+ def load_cli_yaml(server_name: str) -> dict | None:
19
+ path = cli_path(server_name)
20
+ if not path.exists():
21
+ return None
22
+ try:
23
+ return yaml.safe_load(path.read_text(encoding="utf-8"))
24
+ except yaml.YAMLError:
25
+ return None
26
+
27
+
28
+ def save_cli_yaml(server_name: str, data: dict) -> Path:
29
+ CLI_DIR.mkdir(parents=True, exist_ok=True)
30
+ path = cli_path(server_name)
31
+ path.write_text(yaml.dump(data, allow_unicode=True, default_flow_style=False, sort_keys=False), encoding="utf-8")
32
+ return path
33
+
34
+
35
+ def cli_yaml_hash(server_name: str) -> str | None:
36
+ """Compute SHA-256 first 8 hex chars of cli/<server>.yaml content."""
37
+ path = cli_path(server_name)
38
+ if not path.exists():
39
+ return None
40
+ content = path.read_bytes()
41
+ return hashlib.sha256(content).hexdigest()[:8]
42
+
43
+
44
+ def extract_tools_from_yaml(data: dict) -> set[str]:
45
+ """Extract all _tool values from a CLI YAML dict."""
46
+ tools: set[str] = set()
47
+
48
+ def _walk(node: dict) -> None:
49
+ for key, value in node.items():
50
+ if key.startswith("_"):
51
+ if key == "_tool" and isinstance(value, str):
52
+ tools.add(value)
53
+ continue
54
+ if isinstance(value, dict):
55
+ _walk(value)
56
+
57
+ commands = data.get("commands", {})
58
+ if isinstance(commands, dict):
59
+ _walk(commands)
60
+ return tools
61
+
62
+
63
+ def print_command_tree(data: dict, server_name: str) -> None:
64
+ """Print a visual command tree."""
65
+ commands = data.get("commands", {})
66
+
67
+ def _print_node(node: dict, prefix: str = "", is_last: bool = True, parent_prefix: str = "") -> None:
68
+ items = [(k, v) for k, v in node.items() if not k.startswith("_") and isinstance(v, dict)]
69
+ for i, (key, value) in enumerate(items):
70
+ last = i == len(items) - 1
71
+ connector = "└── " if last else "├── "
72
+ child_prefix = parent_prefix + (" " if last else "│ ")
73
+
74
+ tool = value.get("_tool")
75
+ if tool:
76
+ print(f"{parent_prefix}{connector}{key:<15} → {tool}")
77
+ else:
78
+ print(f"{parent_prefix}{connector}{key}")
79
+ _print_node(value, prefix=key, is_last=last, parent_prefix=child_prefix)
80
+
81
+ print(server_name)
82
+ _print_node(commands)