plati-mcp-server 0.1.1 → 0.1.3

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.
package/mcp_server.py CHANGED
@@ -21,21 +21,47 @@ except Exception as e: # pragma: no cover - defensive path
21
21
 
22
22
 
23
23
  def _read_message() -> Dict[str, Any]:
24
+ # Dual framing support:
25
+ # 1) MCP/LSP-style Content-Length headers + JSON body
26
+ # 2) NDJSON (one JSON message per line)
27
+ #
28
+ # We auto-detect by first line and keep response framing symmetrical.
29
+ first = sys.stdin.buffer.readline()
30
+ if not first:
31
+ raise EOFError
32
+
33
+ # NDJSON path.
34
+ stripped = first.strip()
35
+ if stripped.startswith(b"{"):
36
+ _STATE["framing"] = "ndjson"
37
+ return json.loads(stripped.decode("utf-8"))
38
+
39
+ # Content-Length path.
24
40
  headers: Dict[str, str] = {}
41
+ line = first
25
42
  while True:
26
- line = sys.stdin.buffer.readline()
27
- if not line:
28
- raise EOFError
29
43
  if line in (b"\r\n", b"\n"):
30
44
  break
31
- key, value = line.decode("utf-8").split(":", 1)
45
+ decoded = line.decode("utf-8")
46
+ if ":" not in decoded:
47
+ raise ValueError("Invalid header line")
48
+ key, value = decoded.split(":", 1)
32
49
  headers[key.strip().lower()] = value.strip()
50
+ line = sys.stdin.buffer.readline()
51
+ if not line:
52
+ raise EOFError
33
53
  content_length = int(headers.get("content-length", "0"))
34
54
  payload = sys.stdin.buffer.read(content_length)
55
+ _STATE["framing"] = "content-length"
35
56
  return json.loads(payload.decode("utf-8"))
36
57
 
37
58
 
38
59
  def _write_message(msg: Dict[str, Any]) -> None:
60
+ if _STATE.get("framing") == "ndjson":
61
+ line = json.dumps(msg, ensure_ascii=False) + "\n"
62
+ sys.stdout.write(line)
63
+ sys.stdout.flush()
64
+ return
39
65
  data = json.dumps(msg, ensure_ascii=False).encode("utf-8")
40
66
  header = f"Content-Length: {len(data)}\r\n\r\n".encode("utf-8")
41
67
  sys.stdout.buffer.write(header)
@@ -138,6 +164,8 @@ TOOL_SCHEMA = {
138
164
  },
139
165
  }
140
166
 
167
+ _STATE: Dict[str, str] = {"framing": "content-length"}
168
+
141
169
 
142
170
  def _handle_request(msg: Dict[str, Any]) -> Dict[str, Any]:
143
171
  method = msg.get("method")
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "plati-mcp-server",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "MCP stdio server for finding cheapest reliable subscription offers on Plati.",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
7
7
  "bin": {
8
- "plati-mcp-server": "bin/plati-mcp-server.js"
8
+ "plati-mcp-server": "mcp_server.py"
9
9
  },
10
10
  "files": [
11
- "bin/plati-mcp-server.js",
12
11
  "mcp_server.py",
13
12
  "plati_scrape.py",
14
13
  "README.md"
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env node
2
- const { spawn } = require("node:child_process");
3
- const fs = require("node:fs");
4
- const path = require("node:path");
5
-
6
- const projectRoot = path.resolve(__dirname, "..");
7
- const serverPath = path.join(projectRoot, "mcp_server.py");
8
- const args = process.argv.slice(2);
9
-
10
- if (!fs.existsSync(serverPath)) {
11
- console.error(`Error: mcp_server.py not found at ${serverPath}`);
12
- process.exit(1);
13
- }
14
-
15
- const child = spawn("python3", [serverPath, ...args], {
16
- stdio: "inherit",
17
- env: process.env,
18
- });
19
-
20
- child.on("error", (err) => {
21
- if (err && err.code === "ENOENT") {
22
- console.error("Error: python3 is not installed or not in PATH.");
23
- } else {
24
- console.error(`Error starting server: ${err.message}`);
25
- }
26
- process.exit(1);
27
- });
28
-
29
- child.on("exit", (code, signal) => {
30
- if (signal) {
31
- process.kill(process.pid, signal);
32
- return;
33
- }
34
- process.exit(code ?? 0);
35
- });