mcp-cli-skill 0.5.2__tar.gz → 0.5.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-cli-skill
3
- Version: 0.5.2
3
+ Version: 0.5.3
4
4
  Summary: Call any MCP server tool from the command line with shell composition support
5
5
  Project-URL: Homepage, https://github.com/wise-toddler/mcp-cli-skill
6
6
  Project-URL: Repository, https://github.com/wise-toddler/mcp-cli-skill
@@ -8,6 +8,7 @@ import sys
8
8
  import tempfile
9
9
  import re
10
10
  import shutil
11
+ import urllib.parse
11
12
  import urllib.request
12
13
  import urllib.error
13
14
 
@@ -213,6 +214,30 @@ class HttpSession:
213
214
  self.session_id = None
214
215
  self.extra_headers = {k: _expand_env(v) for k, v in (extra_headers or {}).items()}
215
216
 
217
+ def _send(self, data, headers, timeout=30, max_redirects=3):
218
+ """POST data and follow 307/308 redirects preserving method+body.
219
+
220
+ urllib's default HTTPRedirectHandler does NOT follow 307/308 on POST,
221
+ only on GET/HEAD. We handle them explicitly here.
222
+ """
223
+ url = self.url
224
+ for _ in range(max_redirects + 1):
225
+ req = urllib.request.Request(url, data=data, headers=headers)
226
+ try:
227
+ return urllib.request.urlopen(req, timeout=timeout)
228
+ except urllib.error.HTTPError as e:
229
+ if e.code in (307, 308) and e.headers.get("Location"):
230
+ new_url = urllib.parse.urljoin(url, e.headers["Location"])
231
+ try:
232
+ e.close()
233
+ except Exception:
234
+ pass
235
+ url = new_url
236
+ self.url = url # cache redirected URL for subsequent calls
237
+ continue
238
+ raise
239
+ raise urllib.error.HTTPError(url, 308, "Too many redirects", None, None)
240
+
216
241
  def rpc(self, method, params=None, msg_id=1):
217
242
  """Send JSON-RPC over HTTP and return response."""
218
243
  msg = {"jsonrpc": "2.0", "method": method, "id": msg_id}
@@ -227,9 +252,8 @@ class HttpSession:
227
252
  headers.update(self.extra_headers)
228
253
  if self.session_id:
229
254
  headers["Mcp-Session-Id"] = self.session_id
230
- req = urllib.request.Request(self.url, data=data, headers=headers)
231
255
  try:
232
- with urllib.request.urlopen(req, timeout=30) as resp:
256
+ with self._send(data, headers) as resp:
233
257
  # capture session ID from response
234
258
  sid = resp.headers.get("Mcp-Session-Id")
235
259
  if sid:
@@ -259,13 +283,12 @@ class HttpSession:
259
283
  if params:
260
284
  msg["params"] = params
261
285
  data = json.dumps(msg).encode()
262
- headers = {"Content-Type": "application/json"}
286
+ headers = {"Content-Type": "application/json", "User-Agent": "mcp-cli/1.0"}
263
287
  headers.update(self.extra_headers)
264
288
  if self.session_id:
265
289
  headers["Mcp-Session-Id"] = self.session_id
266
- req = urllib.request.Request(self.url, data=data, headers=headers)
267
290
  try:
268
- urllib.request.urlopen(req, timeout=10)
291
+ self._send(data, headers, timeout=10)
269
292
  except Exception:
270
293
  pass
271
294
 
@@ -1,2 +1,2 @@
1
1
  """MCP CLI - Call any MCP server tool from the command line."""
2
- __version__ = "0.5.2"
2
+ __version__ = "0.5.3"
@@ -8,6 +8,7 @@ import sys
8
8
  import tempfile
9
9
  import re
10
10
  import shutil
11
+ import urllib.parse
11
12
  import urllib.request
12
13
  import urllib.error
13
14
 
@@ -213,6 +214,30 @@ class HttpSession:
213
214
  self.session_id = None
214
215
  self.extra_headers = {k: _expand_env(v) for k, v in (extra_headers or {}).items()}
215
216
 
217
+ def _send(self, data, headers, timeout=30, max_redirects=3):
218
+ """POST data and follow 307/308 redirects preserving method+body.
219
+
220
+ urllib's default HTTPRedirectHandler does NOT follow 307/308 on POST,
221
+ only on GET/HEAD. We handle them explicitly here.
222
+ """
223
+ url = self.url
224
+ for _ in range(max_redirects + 1):
225
+ req = urllib.request.Request(url, data=data, headers=headers)
226
+ try:
227
+ return urllib.request.urlopen(req, timeout=timeout)
228
+ except urllib.error.HTTPError as e:
229
+ if e.code in (307, 308) and e.headers.get("Location"):
230
+ new_url = urllib.parse.urljoin(url, e.headers["Location"])
231
+ try:
232
+ e.close()
233
+ except Exception:
234
+ pass
235
+ url = new_url
236
+ self.url = url # cache redirected URL for subsequent calls
237
+ continue
238
+ raise
239
+ raise urllib.error.HTTPError(url, 308, "Too many redirects", None, None)
240
+
216
241
  def rpc(self, method, params=None, msg_id=1):
217
242
  """Send JSON-RPC over HTTP and return response."""
218
243
  msg = {"jsonrpc": "2.0", "method": method, "id": msg_id}
@@ -227,9 +252,8 @@ class HttpSession:
227
252
  headers.update(self.extra_headers)
228
253
  if self.session_id:
229
254
  headers["Mcp-Session-Id"] = self.session_id
230
- req = urllib.request.Request(self.url, data=data, headers=headers)
231
255
  try:
232
- with urllib.request.urlopen(req, timeout=30) as resp:
256
+ with self._send(data, headers) as resp:
233
257
  # capture session ID from response
234
258
  sid = resp.headers.get("Mcp-Session-Id")
235
259
  if sid:
@@ -259,13 +283,12 @@ class HttpSession:
259
283
  if params:
260
284
  msg["params"] = params
261
285
  data = json.dumps(msg).encode()
262
- headers = {"Content-Type": "application/json"}
286
+ headers = {"Content-Type": "application/json", "User-Agent": "mcp-cli/1.0"}
263
287
  headers.update(self.extra_headers)
264
288
  if self.session_id:
265
289
  headers["Mcp-Session-Id"] = self.session_id
266
- req = urllib.request.Request(self.url, data=data, headers=headers)
267
290
  try:
268
- urllib.request.urlopen(req, timeout=10)
291
+ self._send(data, headers, timeout=10)
269
292
  except Exception:
270
293
  pass
271
294
 
File without changes
File without changes