cli2mcp 0.1.1__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.
- cli2mcp-0.1.1/.gitignore +7 -0
- cli2mcp-0.1.1/DEBUGGING.md +164 -0
- cli2mcp-0.1.1/LICENSE +674 -0
- cli2mcp-0.1.1/PKG-INFO +153 -0
- cli2mcp-0.1.1/README.md +144 -0
- cli2mcp-0.1.1/examples/curl.tools.json +89 -0
- cli2mcp-0.1.1/examples/debug_demo.sh +86 -0
- cli2mcp-0.1.1/examples/git.tools.json +2345 -0
- cli2mcp-0.1.1/examples/requests/1_initialize.json +13 -0
- cli2mcp-0.1.1/examples/requests/2_initialized.json +4 -0
- cli2mcp-0.1.1/examples/requests/3_list_tools.json +5 -0
- cli2mcp-0.1.1/examples/requests/4_call_tool.json +11 -0
- cli2mcp-0.1.1/pyproject.toml +19 -0
- cli2mcp-0.1.1/src/cli2mcp/__init__.py +3 -0
- cli2mcp-0.1.1/src/cli2mcp/__main__.py +5 -0
- cli2mcp-0.1.1/src/cli2mcp/cli.py +94 -0
- cli2mcp-0.1.1/src/cli2mcp/parser.py +30 -0
- cli2mcp-0.1.1/src/cli2mcp/parsers/__init__.py +6 -0
- cli2mcp-0.1.1/src/cli2mcp/parsers/cobra.py +175 -0
- cli2mcp-0.1.1/src/cli2mcp/parsers/common.py +42 -0
- cli2mcp-0.1.1/src/cli2mcp/parsers/gnu.py +142 -0
- cli2mcp-0.1.1/src/cli2mcp/parsers/plain.py +112 -0
- cli2mcp-0.1.1/src/cli2mcp/scanner.py +89 -0
- cli2mcp-0.1.1/src/cli2mcp/server.py +164 -0
- cli2mcp-0.1.1/uv.lock +976 -0
cli2mcp-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Debugging the MCP Server
|
|
2
|
+
|
|
3
|
+
## MCP transports
|
|
4
|
+
|
|
5
|
+
MCP defines two standard transports:
|
|
6
|
+
|
|
7
|
+
| Transport | When to use | How it works |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| **stdio** | Local — IDE spawns the server as a child process | JSON-RPC over stdin/stdout pipes |
|
|
10
|
+
| **Streamable HTTP** | Remote — server is a standalone HTTP service | JSON-RPC via POST to a single `/mcp` endpoint |
|
|
11
|
+
|
|
12
|
+
**Streamable HTTP** is the easiest to debug with `curl` because it is plain
|
|
13
|
+
HTTP: you POST JSON-RPC messages and read the response. The server replies
|
|
14
|
+
with either `application/json` or an SSE stream (`text/event-stream`);
|
|
15
|
+
the Python MCP SDK currently always uses SSE, so we extract the `data:`
|
|
16
|
+
line from each response.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Start the servers
|
|
21
|
+
|
|
22
|
+
Terminal 1 — a tiny target server so the demo is fully self-contained:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
python3 -c '
|
|
26
|
+
from http.server import HTTPServer, BaseHTTPRequestHandler
|
|
27
|
+
class H(BaseHTTPRequestHandler):
|
|
28
|
+
def do_GET(s): s.send_response(200); s.end_headers(); s.wfile.write(b"Hello, world!\n")
|
|
29
|
+
def log_message(s, *a): pass
|
|
30
|
+
HTTPServer(("127.0.0.1", 9000), H).serve_forever()
|
|
31
|
+
'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Terminal 2 — the MCP server:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv run cli2mcp serve examples/curl.tools.json -t streamable-http
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Leave both running. All commands below run in a **third terminal**
|
|
41
|
+
(or just run the script: `./examples/debug_demo.sh`).
|
|
42
|
+
|
|
43
|
+
## 1. Initialize a session
|
|
44
|
+
|
|
45
|
+
Every MCP conversation starts with a handshake.
|
|
46
|
+
|
|
47
|
+
`examples/requests/1_initialize.json`:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"jsonrpc": "2.0",
|
|
52
|
+
"id": 1,
|
|
53
|
+
"method": "initialize",
|
|
54
|
+
"params": {
|
|
55
|
+
"protocolVersion": "2025-06-18",
|
|
56
|
+
"capabilities": {},
|
|
57
|
+
"clientInfo": {
|
|
58
|
+
"name": "debug",
|
|
59
|
+
"version": "1.0"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Send it and capture the session ID:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
SESSION=$(curl -s -D- -X POST http://localhost:8000/mcp \
|
|
69
|
+
-H 'Content-Type: application/json' \
|
|
70
|
+
-H 'Accept: application/json, text/event-stream' \
|
|
71
|
+
-d @examples/requests/1_initialize.json \
|
|
72
|
+
| grep -i mcp-session-id | awk '{print $2}' | tr -d '\r')
|
|
73
|
+
|
|
74
|
+
echo "Session: $SESSION"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 2. Confirm the handshake
|
|
78
|
+
|
|
79
|
+
`examples/requests/2_initialized.json`:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"jsonrpc": "2.0",
|
|
84
|
+
"method": "notifications/initialized"
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
curl -s -X POST http://localhost:8000/mcp \
|
|
90
|
+
-H 'Content-Type: application/json' \
|
|
91
|
+
-H 'Accept: application/json, text/event-stream' \
|
|
92
|
+
-H "Mcp-Session-Id: $SESSION" \
|
|
93
|
+
-d @examples/requests/2_initialized.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
This is a notification (no `id` field), so the server returns an empty
|
|
97
|
+
HTTP 202 response.
|
|
98
|
+
|
|
99
|
+
## 3. List available tools
|
|
100
|
+
|
|
101
|
+
`examples/requests/3_list_tools.json`:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"jsonrpc": "2.0",
|
|
106
|
+
"id": 2,
|
|
107
|
+
"method": "tools/list"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
curl -s -X POST http://localhost:8000/mcp \
|
|
113
|
+
-H 'Content-Type: application/json' \
|
|
114
|
+
-H 'Accept: application/json, text/event-stream' \
|
|
115
|
+
-H "Mcp-Session-Id: $SESSION" \
|
|
116
|
+
-d @examples/requests/3_list_tools.json \
|
|
117
|
+
| grep '^data:' | sed 's/^data: //' | python3 -m json.tool
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Expected: a `tools` array with `curl` and its `inputSchema` listing
|
|
121
|
+
all available arguments (`data`, `output`, `url`, etc.).
|
|
122
|
+
|
|
123
|
+
## 4. Call the tool to fetch a web page
|
|
124
|
+
|
|
125
|
+
`examples/requests/4_call_tool.json`:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"jsonrpc": "2.0",
|
|
130
|
+
"id": 3,
|
|
131
|
+
"method": "tools/call",
|
|
132
|
+
"params": {
|
|
133
|
+
"name": "curl",
|
|
134
|
+
"arguments": {
|
|
135
|
+
"url": "http://127.0.0.1:9000"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
curl -s -X POST http://localhost:8000/mcp \
|
|
143
|
+
-H 'Content-Type: application/json' \
|
|
144
|
+
-H 'Accept: application/json, text/event-stream' \
|
|
145
|
+
-H "Mcp-Session-Id: $SESSION" \
|
|
146
|
+
-d @examples/requests/4_call_tool.json \
|
|
147
|
+
| grep '^data:' | sed 's/^data: //' | python3 -m json.tool
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Expected: `content[0].text` contains `Hello, world!`.
|
|
151
|
+
|
|
152
|
+
## What just happened
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
You (curl) ---> MCP server (:8000) ---> curl ---> hello_server (:9000)
|
|
156
|
+
HTTP POST reads tools.json subprocess "Hello, world!"
|
|
157
|
+
JSON-RPC builds command runs it returned
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
1. Your curl sent a JSON-RPC `tools/call` to the MCP server over **Streamable HTTP**
|
|
161
|
+
2. The server looked up `curl` in `examples/curl.tools.json`
|
|
162
|
+
3. It built the command: `curl http://127.0.0.1:9000`
|
|
163
|
+
4. It ran it with `subprocess.run()`
|
|
164
|
+
5. It returned stdout (`Hello, world!`) as MCP tool output wrapped in an SSE `data:` line
|