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 +32 -4
- package/package.json +2 -3
- package/bin/plati-mcp-server.js +0 -35
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
|
-
|
|
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.
|
|
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": "
|
|
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"
|
package/bin/plati-mcp-server.js
DELETED
|
@@ -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
|
-
});
|