projectpulse-mcp 1.6.14 → 1.7.0
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/README.md +31 -0
- package/dist/index.js +102 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -221,6 +221,37 @@ Simple connectivity check. Returns "pong" with your message. Use to verify the M
|
|
|
221
221
|
|
|
222
222
|
## 🆕 What's New
|
|
223
223
|
|
|
224
|
+
### HTTP Transport (v1.7.0)
|
|
225
|
+
|
|
226
|
+
ProjectPulse now supports **Streamable HTTP transport** in addition to stdio. This enables running as a standalone HTTP server — ideal for Docker containers, remote deployments, and cross-runtime integrations (e.g., .NET clients consuming Node.js MCP tools over the network).
|
|
227
|
+
|
|
228
|
+
**Default behavior is unchanged** — `npx projectpulse-mcp` still uses stdio. To activate HTTP mode:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
MCP_TRANSPORT=http MCP_PORT=3000 node dist/index.js
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
| Env Variable | Default | Description |
|
|
235
|
+
| --- | --- | --- |
|
|
236
|
+
| `MCP_TRANSPORT` | `stdio` | Transport mode: `stdio` or `http` |
|
|
237
|
+
| `MCP_PORT` | `3000` | HTTP server port (only used when `MCP_TRANSPORT=http`) |
|
|
238
|
+
|
|
239
|
+
**Docker example:**
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
projectpulse:
|
|
243
|
+
image: node:22-slim
|
|
244
|
+
command: >-
|
|
245
|
+
sh -c "npm install -g projectpulse-mcp &&
|
|
246
|
+
node /usr/local/lib/node_modules/projectpulse-mcp/dist/index.js"
|
|
247
|
+
environment:
|
|
248
|
+
- MCP_TRANSPORT=http
|
|
249
|
+
- MCP_PORT=3000
|
|
250
|
+
- GITHUB_TOKEN=${GITHUB_TOKEN}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Health check endpoint available at `GET /` (returns JSON with server name and version). MCP protocol endpoint at `POST /mcp`.
|
|
254
|
+
|
|
224
255
|
### OpenSSF Scorecard Integration
|
|
225
256
|
|
|
226
257
|
Security score now blends **Dependabot alerts** (60%) with **OpenSSF Scorecard** checks (40%) for a more complete picture. 12 security-relevant checks are evaluated — repos without a scorecard gracefully fall back to Dependabot-only scoring.
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { createServer } from "node:http";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
3
7
|
import { registerCheckCiStatus } from "./tools/check-ci-status.js";
|
|
4
8
|
import { registerGetRepoHealth } from "./tools/get-repo-health.js";
|
|
5
9
|
import { registerAnalyzeDependencies } from "./tools/analyze-dependencies.js";
|
|
@@ -12,14 +16,102 @@ import { join, dirname } from "path";
|
|
|
12
16
|
import { fileURLToPath } from "url";
|
|
13
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
18
|
const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
function createMcpServer() {
|
|
20
|
+
const server = new McpServer({ name: "projectpulse-mcp", version: pkg.version });
|
|
21
|
+
registerCheckCiStatus(server);
|
|
22
|
+
registerGetRepoHealth(server);
|
|
23
|
+
registerAnalyzeDependencies(server);
|
|
24
|
+
registerAnalyzeCodeScanning(server);
|
|
25
|
+
registerGetHealthScore(server);
|
|
26
|
+
registerGetDoraMetrics(server);
|
|
27
|
+
registerCompareRepos(server);
|
|
28
|
+
return server;
|
|
29
|
+
}
|
|
30
|
+
// --- Transport selection ---
|
|
31
|
+
// Default: stdio (backward compatible, per uso locale e npx)
|
|
32
|
+
// MCP_TRANSPORT=http: Streamable HTTP server (per Docker e remote clients)
|
|
33
|
+
const transportMode = (process.env.MCP_TRANSPORT ?? "stdio").toLowerCase();
|
|
34
|
+
if (transportMode === "http") {
|
|
35
|
+
const port = parseInt(process.env.MCP_PORT ?? "3000", 10);
|
|
36
|
+
const transports = new Map();
|
|
37
|
+
const httpServer = createServer(async (req, res) => {
|
|
38
|
+
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
39
|
+
// Only handle /mcp path — MCP protocol endpoint
|
|
40
|
+
if (url.pathname !== "/mcp") {
|
|
41
|
+
// Health check on root
|
|
42
|
+
if (url.pathname === "/" && req.method === "GET") {
|
|
43
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
44
|
+
res.end(JSON.stringify({ status: "ok", server: "projectpulse-mcp", version: pkg.version }));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
res.writeHead(404);
|
|
48
|
+
res.end("Not Found");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Parse JSON body for POST requests
|
|
52
|
+
if (req.method === "POST") {
|
|
53
|
+
const chunks = [];
|
|
54
|
+
for await (const chunk of req)
|
|
55
|
+
chunks.push(chunk);
|
|
56
|
+
const body = JSON.parse(Buffer.concat(chunks).toString());
|
|
57
|
+
req.body = body;
|
|
58
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
59
|
+
if (sessionId && transports.has(sessionId)) {
|
|
60
|
+
// Existing session — reuse transport
|
|
61
|
+
await transports.get(sessionId).handleRequest(req, res, body);
|
|
62
|
+
}
|
|
63
|
+
else if (!sessionId && isInitializeRequest(body)) {
|
|
64
|
+
// New session — create transport + server
|
|
65
|
+
const transport = new StreamableHTTPServerTransport({
|
|
66
|
+
sessionIdGenerator: () => randomUUID(),
|
|
67
|
+
onsessioninitialized: (sid) => {
|
|
68
|
+
transports.set(sid, transport);
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
transport.onclose = () => {
|
|
72
|
+
const sid = transport.sessionId;
|
|
73
|
+
if (sid)
|
|
74
|
+
transports.delete(sid);
|
|
75
|
+
};
|
|
76
|
+
const server = createMcpServer();
|
|
77
|
+
await server.connect(transport);
|
|
78
|
+
await transport.handleRequest(req, res, body);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
82
|
+
res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32000, message: "Bad Request: No valid session ID" }, id: null }));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else if (req.method === "GET" || req.method === "DELETE") {
|
|
86
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
87
|
+
if (!sessionId || !transports.has(sessionId)) {
|
|
88
|
+
res.writeHead(400);
|
|
89
|
+
res.end("Invalid or missing session ID");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
await transports.get(sessionId).handleRequest(req, res);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
res.writeHead(405);
|
|
96
|
+
res.end("Method Not Allowed");
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
httpServer.listen(port, "0.0.0.0", () => {
|
|
100
|
+
console.log(`ProjectPulse MCP server (HTTP) listening on http://0.0.0.0:${port}/mcp`);
|
|
101
|
+
});
|
|
102
|
+
process.on("SIGINT", async () => {
|
|
103
|
+
for (const [, transport] of transports) {
|
|
104
|
+
await transport.close();
|
|
105
|
+
}
|
|
106
|
+
transports.clear();
|
|
107
|
+
httpServer.close();
|
|
108
|
+
process.exit(0);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Default: stdio transport (backward compatible)
|
|
113
|
+
const server = createMcpServer();
|
|
114
|
+
const transport = new StdioServerTransport();
|
|
115
|
+
await server.connect(transport);
|
|
116
|
+
}
|
|
25
117
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED