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.
- mcp_to_cli-0.1.0/.gitignore +43 -0
- mcp_to_cli-0.1.0/CLAUDE.md +9 -0
- mcp_to_cli-0.1.0/LICENSE +21 -0
- mcp_to_cli-0.1.0/PKG-INFO +191 -0
- mcp_to_cli-0.1.0/README.md +164 -0
- mcp_to_cli-0.1.0/mcp2cli/__init__.py +3 -0
- mcp_to_cli-0.1.0/mcp2cli/cli/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/cli/mapping.py +82 -0
- mcp_to_cli-0.1.0/mcp2cli/cli/resolver.py +342 -0
- mcp_to_cli-0.1.0/mcp2cli/config/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/config/models.py +153 -0
- mcp_to_cli-0.1.0/mcp2cli/config/reader.py +132 -0
- mcp_to_cli-0.1.0/mcp2cli/config/tool_store.py +32 -0
- mcp_to_cli-0.1.0/mcp2cli/constants.py +47 -0
- mcp_to_cli-0.1.0/mcp2cli/converter/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/converter/config_disabler.py +91 -0
- mcp_to_cli-0.1.0/mcp2cli/converter/config_extractor.py +66 -0
- mcp_to_cli-0.1.0/mcp2cli/daemon/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/daemon/client.py +98 -0
- mcp_to_cli-0.1.0/mcp2cli/daemon/lifecycle.py +113 -0
- mcp_to_cli-0.1.0/mcp2cli/daemon/pool.py +144 -0
- mcp_to_cli-0.1.0/mcp2cli/daemon/server.py +168 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/cli_gen.py +202 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/llm_backend.py +361 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/skill_gen.py +295 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/templates/cli_gen_example.md +235 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/templates/cli_gen_skill.md +136 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/templates/skill_gen_example.md +217 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/templates/skill_gen_skill.md +112 -0
- mcp_to_cli-0.1.0/mcp2cli/generator/validator.py +210 -0
- mcp_to_cli-0.1.0/mcp2cli/installer/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/installer/ai_search.py +233 -0
- mcp_to_cli-0.1.0/mcp2cli/installer/interactive.py +65 -0
- mcp_to_cli-0.1.0/mcp2cli/installer/pipeline.py +161 -0
- mcp_to_cli-0.1.0/mcp2cli/installer/servers_writer.py +70 -0
- mcp_to_cli-0.1.0/mcp2cli/installer/skill_sync.py +87 -0
- mcp_to_cli-0.1.0/mcp2cli/main.py +890 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/checker.py +67 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/downloader.py +158 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/exporter.py +79 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/github.py +88 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/local.py +27 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/models.py +126 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/pusher.py +232 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/registry.py +112 -0
- mcp_to_cli-0.1.0/mcp2cli/preset/version.py +41 -0
- mcp_to_cli-0.1.0/mcp2cli/remover/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/remover/cleaner.py +109 -0
- mcp_to_cli-0.1.0/mcp2cli/remover/config_re_enabler.py +92 -0
- mcp_to_cli-0.1.0/mcp2cli/remover/package_purger.py +73 -0
- mcp_to_cli-0.1.0/mcp2cli/remover/pipeline.py +96 -0
- mcp_to_cli-0.1.0/mcp2cli/remover/scanner.py +146 -0
- mcp_to_cli-0.1.0/mcp2cli/scanner.py +70 -0
- mcp_to_cli-0.1.0/mcp2cli/ui/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/ui/progress.py +118 -0
- mcp_to_cli-0.1.0/mcp2cli/updater/__init__.py +0 -0
- mcp_to_cli-0.1.0/mcp2cli/updater/diff.py +81 -0
- mcp_to_cli-0.1.0/mcp2cli/updater/pipeline.py +184 -0
- mcp_to_cli-0.1.0/mcp2cli/utils/__init__.py +18 -0
- mcp_to_cli-0.1.0/mcp2cli/utils/file_ops.py +87 -0
- mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/cli.yaml +38 -0
- mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/manifest.json +15 -0
- mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/SKILL.md +44 -0
- mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/reference/diagram.md +61 -0
- mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/reference/session.md +11 -0
- mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/users/.gitkeep +0 -0
- mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/skills/users/SKILL.md +4 -0
- mcp_to_cli-0.1.0/presets/dayuanjiang-next-ai-draw-io/0.1.2/tools.json +110 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/cli.yaml +281 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/manifest.json +21 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/SKILL.md +56 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/confluence-attachment.md +47 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/confluence-page.md +81 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/confluence.md +52 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-board.md +22 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-issue.md +162 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-misc.md +74 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-project.md +33 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/reference/jira-sprint.md +45 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/users/.gitkeep +0 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/skills/users/SKILL.md +4 -0
- mcp_to_cli-0.1.0/presets/mcp-atlassian/2.14.6/tools.json +2003 -0
- mcp_to_cli-0.1.0/pyproject.toml +51 -0
- mcp_to_cli-0.1.0/tests/__init__.py +0 -0
- mcp_to_cli-0.1.0/tests/test_dynamic_cli.py +23 -0
- mcp_to_cli-0.1.0/tests/test_preset_version.py +178 -0
- 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.
|
mcp_to_cli-0.1.0/LICENSE
ADDED
|
@@ -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
|
|
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)
|