projectpulse-mcp 1.4.1 → 1.5.1

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.
Files changed (57) hide show
  1. package/README.md +85 -95
  2. package/dist/scoring/health-score.d.ts +1 -1
  3. package/dist/scoring/health-score.d.ts.map +1 -1
  4. package/dist/scoring/health-score.js +17 -8
  5. package/dist/scoring/health-score.js.map +1 -1
  6. package/dist/security/openssf-client.d.ts +4 -0
  7. package/dist/security/openssf-client.d.ts.map +1 -0
  8. package/dist/security/openssf-client.js +34 -0
  9. package/dist/security/openssf-client.js.map +1 -0
  10. package/dist/security/types.d.ts +15 -0
  11. package/dist/security/types.d.ts.map +1 -0
  12. package/dist/security/types.js +2 -0
  13. package/dist/security/types.js.map +1 -0
  14. package/dist/tools/get-health-score.d.ts.map +1 -1
  15. package/dist/tools/get-health-score.js +5 -3
  16. package/dist/tools/get-health-score.js.map +1 -1
  17. package/package.json +6 -4
  18. package/dist/analytics/dora.test.d.ts +0 -2
  19. package/dist/analytics/dora.test.d.ts.map +0 -1
  20. package/dist/analytics/dora.test.js +0 -164
  21. package/dist/analytics/dora.test.js.map +0 -1
  22. package/dist/scoring/health-score.test.d.ts +0 -2
  23. package/dist/scoring/health-score.test.d.ts.map +0 -1
  24. package/dist/scoring/health-score.test.js +0 -210
  25. package/dist/scoring/health-score.test.js.map +0 -1
  26. package/dist/tools/analyze-code-scanning.test.d.ts +0 -2
  27. package/dist/tools/analyze-code-scanning.test.d.ts.map +0 -1
  28. package/dist/tools/analyze-code-scanning.test.js +0 -72
  29. package/dist/tools/analyze-code-scanning.test.js.map +0 -1
  30. package/dist/tools/analyze-dependencies.test.d.ts +0 -2
  31. package/dist/tools/analyze-dependencies.test.d.ts.map +0 -1
  32. package/dist/tools/analyze-dependencies.test.js +0 -65
  33. package/dist/tools/analyze-dependencies.test.js.map +0 -1
  34. package/dist/tools/check-ci-status.test.d.ts +0 -2
  35. package/dist/tools/check-ci-status.test.d.ts.map +0 -1
  36. package/dist/tools/check-ci-status.test.js +0 -90
  37. package/dist/tools/check-ci-status.test.js.map +0 -1
  38. package/dist/tools/compare-repos.test.d.ts +0 -2
  39. package/dist/tools/compare-repos.test.d.ts.map +0 -1
  40. package/dist/tools/compare-repos.test.js +0 -138
  41. package/dist/tools/compare-repos.test.js.map +0 -1
  42. package/dist/tools/get-dora-metrics.test.d.ts +0 -2
  43. package/dist/tools/get-dora-metrics.test.d.ts.map +0 -1
  44. package/dist/tools/get-dora-metrics.test.js +0 -71
  45. package/dist/tools/get-dora-metrics.test.js.map +0 -1
  46. package/dist/tools/get-health-score.test.d.ts +0 -2
  47. package/dist/tools/get-health-score.test.d.ts.map +0 -1
  48. package/dist/tools/get-health-score.test.js +0 -93
  49. package/dist/tools/get-health-score.test.js.map +0 -1
  50. package/dist/tools/get-repo-health.test.d.ts +0 -2
  51. package/dist/tools/get-repo-health.test.d.ts.map +0 -1
  52. package/dist/tools/get-repo-health.test.js +0 -80
  53. package/dist/tools/get-repo-health.test.js.map +0 -1
  54. package/dist/vitest.config.d.ts +0 -3
  55. package/dist/vitest.config.d.ts.map +0 -1
  56. package/dist/vitest.config.js +0 -7
  57. package/dist/vitest.config.js.map +0 -1
package/README.md CHANGED
@@ -1,39 +1,48 @@
1
- # ProjectPulse MCP
1
+ <h1 align="center">ProjectPulse MCP 🏥</h1>
2
2
 
3
- **Is that repo healthy, secure, and actively maintained? Ask your AI assistant — get a graded verdict in seconds.**
3
+ <p align="center">
4
+ <em>GitHub repository health monitoring for AI assistants — works with any language, any repo.</em>
5
+ </p>
4
6
 
5
- ProjectPulse is a Model Context Protocol (MCP) server that lets Claude, Cursor, VS Code Copilot, and any MCP-compatible assistant analyze the **health, security, and maintenance status of any GitHub repository** — directly inside your conversation.
6
-
7
- [![npm version](https://img.shields.io/npm/v/projectpulse-mcp)](https://www.npmjs.com/package/projectpulse-mcp)
8
- [![npm downloads](https://img.shields.io/npm/dm/projectpulse-mcp)](https://www.npmjs.com/package/projectpulse-mcp)
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
- [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/projectpulse-mcp"><img src="https://img.shields.io/npm/v/projectpulse-mcp.svg?color=blue" alt="npm version" /></a>
9
+ <a href="https://github.com/alexbypa/github-projectpulse-mcp/blob/main/LICENSE"><img src="https://img.shields.io/github/license/alexbypa/github-projectpulse-mcp" alt="license" /></a>
10
+ <a href="https://github.com/alexbypa/github-projectpulse-mcp/actions"><img src="https://img.shields.io/github/actions/workflow/status/alexbypa/github-projectpulse-mcp/ci.yml?label=tests" alt="tests" /></a>
11
+ <a href="https://github.com/alexbypa/github-projectpulse-mcp/stargazers"><img src="https://img.shields.io/github/stars/alexbypa/github-projectpulse-mcp" alt="stars" /></a>
12
+ <a href="https://www.npmjs.com/package/projectpulse-mcp"><img src="https://img.shields.io/npm/dt/projectpulse-mcp" alt="downloads" /></a>
13
+ </p>
11
14
 
12
15
  ---
13
16
 
14
- ## Why ProjectPulse?
17
+ This [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server gives AI assistants the ability to analyze health, security, CI/CD status, and delivery metrics of any GitHub repository — directly from your conversations.
18
+
19
+ ## ✨ Features
15
20
 
16
- The official GitHub MCP server manages repos. **ProjectPulse judges them.**
21
+ - 🏥 **Health Score** — comprehensive 0-100 score with grade (A-F), category breakdown, and improvement suggestions
22
+ - 🔒 **Security** — Dependabot alerts blended with [OpenSSF Scorecard](https://scorecard.dev/) checks (60/40 weighted)
23
+ - 📊 **DORA Metrics** — proxy [DORA metrics](https://dora.dev/) from GitHub data: deployment frequency, lead time, change failure rate, MTTR
24
+ - 🔍 **Code Scanning** — CodeQL and other code scanning alerts with severity, message, and creation date
25
+ - 📦 **Dependency Analysis** — Dependabot alerts with severity filtering
26
+ - ⚙️ **CI/CD Status** — recent GitHub Actions workflow runs and conclusions
27
+ - 📋 **Repository Info** — stars, forks, language, license, and general metadata
17
28
 
18
- - 🩺 **Graded verdicts, not raw data** — every check returns a 0–100 score, a letter grade (A–F), a per-category breakdown with weights, and a plain-language summary of the weaknesses. Judgment with receipts, never a black box.
19
- - 📊 **DORA metrics without enterprise tooling** — deployment frequency, lead time, change failure rate, and MTTR from any repo. No Datadog, no Harness, no GitHub App setup.
20
- - 🔒 **Security posture built in** — code scanning alerts (CodeQL) and dependency analysis are first-class tools, not an afterthought.
21
- - ⚖️ **Side-by-side comparison** — evaluating two libraries? Compare their pulse in one call.
22
- - 🆓 **Free, local, MIT** — runs via `npx`, your token never leaves your machine. No hosted service, no pay-per-usage.
29
+ ## 📸 Example
23
30
 
24
- ## Quick Start
31
+ ![Code Scanning Example](https://raw.githubusercontent.com/alexbypa/github-projectpulse-mcp/main/docs/images/code-scanning-example.png)
25
32
 
26
- Requires Node.js ≥ 18 and a [GitHub personal access token](https://github.com/settings/tokens) (read-only scopes are enough for public repos).
33
+ ## 🚀 Quick Start
27
34
 
28
- ### Claude Code
35
+ ### Claude Code (CLI)
29
36
 
30
37
  ```bash
31
- claude mcp add projectpulse --env GITHUB_TOKEN=ghp_your_token -- npx -y projectpulse-mcp
38
+ claude mcp add projectpulse -- npx projectpulse-mcp
32
39
  ```
33
40
 
41
+ > **Note:** You need a `.env` file with your `GITHUB_TOKEN` in the directory where you run Claude Code.
42
+
34
43
  ### Claude Desktop
35
44
 
36
- Add to `claude_desktop_config.json`:
45
+ Add to your `claude_desktop_config.json` (`%APPDATA%\Claude\` on Windows, `~/Library/Application Support/Claude/` on macOS):
37
46
 
38
47
  ```json
39
48
  {
@@ -42,108 +51,89 @@ Add to `claude_desktop_config.json`:
42
51
  "command": "npx",
43
52
  "args": ["-y", "projectpulse-mcp"],
44
53
  "env": {
45
- "GITHUB_TOKEN": "ghp_your_token"
54
+ "GITHUB_TOKEN": "your-github-personal-access-token"
46
55
  }
47
56
  }
48
57
  }
49
58
  }
50
59
  ```
51
60
 
52
- ### Cursor / VS Code
61
+ ### Other MCP Clients (Cursor, Windsurf, etc.)
53
62
 
54
- Add to `.mcp.json` (Cursor) or your MCP settings (VS Code):
63
+ Configure a new MCP server with:
64
+ - **Transport**: `stdio`
65
+ - **Command**: `npx`
66
+ - **Arguments**: `-y projectpulse-mcp`
67
+ - **Environment**: `GITHUB_TOKEN` = your GitHub PAT
55
68
 
56
- ```json
57
- {
58
- "servers": {
59
- "projectpulse": {
60
- "command": "npx",
61
- "args": ["-y", "projectpulse-mcp"],
62
- "env": {
63
- "GITHUB_TOKEN": "ghp_your_token"
64
- }
65
- }
66
- }
67
- }
68
- ```
69
+ ## 🛠️ Tools
69
70
 
70
- That's it. Now just ask:
71
+ | Tool | Description | Inputs |
72
+ | --- | --- | --- |
73
+ | `get_health_score` | 0-100 health score with grade (A-F), category breakdown, and suggestions | `owner`, `repo` |
74
+ | `get_dora_metrics` | DORA proxy metrics: deployment frequency, lead time, change failure rate, MTTR | `owner`, `repo`, `days?` (7-90, default 30) |
75
+ | `get_repo_health` | General metadata: stars, issues, language, license, etc. | `owner`, `repo` |
76
+ | `analyze_dependencies` | Dependabot alerts by severity | `owner`, `repo`, `severity?` |
77
+ | `check_ci_status` | Recent CI/CD workflow runs | `owner`, `repo`, `limit?` (default 10) |
78
+ | `analyze_code_scanning` | CodeQL / code scanning alerts | `owner`, `repo` |
79
+ | `ping` | Connectivity check | `message` |
71
80
 
72
- > *"Is `facebook/react` still actively maintained?"*
73
- > *"Compare the health of `vite` and `webpack` before I migrate."*
74
- > *"Show me the DORA metrics of my repo over the last 90 days."*
81
+ ## 🆕 What's New
75
82
 
76
- ## Tools
83
+ ### OpenSSF Scorecard Integration
77
84
 
78
- | Tool | Question it answers |
79
- |---|---|
80
- | `get_repo_health` | What is the overall state of this repo — activity, responsiveness, community? |
81
- | `get_health_score` | What's the grade, and exactly which categories produced it? |
82
- | `get_dora_metrics` | How elite is this team's delivery performance (frequency, lead time, CFR, MTTR)? |
83
- | `analyze_code_scanning` | Are there open CodeQL / code scanning security alerts? |
84
- | `analyze_dependencies` | How outdated or risky are the dependencies? |
85
- | `check_ci_status` | Is CI green, flaky, or silently broken? |
86
- | `compare_repos` | Which of these repos is the safer bet, dimension by dimension? |
85
+ 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.
87
86
 
88
- ## See it in action
87
+ ### DORA Metrics
89
88
 
90
- A real response to *"health score of `alexbypa/CSharp.Essentials`"*:
89
+ New `get_dora_metrics` tool calculates proxy [DORA metrics](https://dora.dev/) from public GitHub data:
91
90
 
92
- ![get_health_score — Score 93/100, Grade A, with per-category breakdown](docs/images/get-health-score-demo.png)
91
+ | Metric | Source | Unit |
92
+ | --- | --- | --- |
93
+ | Deployment Frequency | Releases | releases/week |
94
+ | Lead Time for Changes | PR created → merged | hours (median) |
95
+ | Change Failure Rate | CI workflow conclusions | percentage |
96
+ | Mean Time to Recovery | CI failure → next success | hours (median) |
93
97
 
94
- ```
95
- Score: 93/100 — Grade A
96
-
97
- | Category | Score | Weight | Detail |
98
- |-------------|-------|--------|----------------------------------------|
99
- | CI | 100 | 25% | 10/10 runs passed |
100
- | Freshness | 100 | 20% | Last push 2 days ago |
101
- | Security | 100 | 25% | Zero alerts across all severities |
102
- | Community | 50 | 15% | 5 open issues, 0 forks |
103
- | Maintenance | 100 | 15% | License, description, active — present |
104
-
105
- Only weakness: community score. No forks, some open issues.
106
- Everything else maxed out.
107
- ```
98
+ Metrics return `null` when insufficient data is available — works safely on any repository.
108
99
 
109
- Every answer includes the score, the weighted breakdown, the metric behind each category, and a narrative summary of what's dragging the grade down — so both you and the AI assistant can audit *why*.
100
+ ## ⚙️ Configuration
110
101
 
111
- ## How the health score works
102
+ ### GITHUB_TOKEN
112
103
 
113
- The score is a weighted composite of five categories, always the same, always disclosed:
104
+ Required to avoid rate limits and access security data (Dependabot, CodeQL alerts).
114
105
 
115
- | Category | Weight | What it measures |
116
- |---|---|---|
117
- | CI | 25% | Pass rate of recent workflow runs |
118
- | Security | 25% | Open code scanning alerts across severities |
119
- | Freshness | 20% | Recency of pushes and activity |
120
- | Community | 15% | Open issues, forks, adoption signals |
121
- | Maintenance | 15% | License, description, archived/active status |
106
+ **Option A: Fine-grained PAT (Recommended)**
107
+ 1. **Settings** > **Developer settings** > **Personal access tokens** > **Fine-grained tokens**
108
+ 2. Select target repositories
109
+ 3. Grant **Read-only** access to:
110
+ - `Code scanning alerts`
111
+ - `Dependabot alerts`
112
+ - `Metadata` (default)
122
113
 
123
- Weights are fixed and deterministic: the same repo state always yields the same score and grade. Full scoring logic in [`docs/architecture.md`](docs/architecture.md) and [`src/scoring/health-score.ts`](src/scoring/health-score.ts).
114
+ **Option B: Classic Token**
115
+ Generate with `repo` + `security_events` scopes.
124
116
 
125
- ## Configuration
117
+ **Providing the token:**
118
+ - **Claude Desktop**: set in `claude_desktop_config.json` (see Quick Start)
119
+ - **Claude Code / Local**: create a `.env` file:
120
+ ```env
121
+ GITHUB_TOKEN=ghp_your_token_here
122
+ ```
126
123
 
127
- | Variable | Required | Description |
128
- |---|---|---|
129
- | `GITHUB_TOKEN` | Recommended | GitHub PAT. Without it, you're limited to 60 requests/hour — fine for a quick look, tight for `compare_repos`. |
124
+ ## 👤 Author
130
125
 
131
- ## Development
126
+ **alexbypa** — [GitHub](https://github.com/alexbypa) · [npm](https://www.npmjs.com/~alexbypa)
132
127
 
133
- ```bash
134
- git clone https://github.com/alexbypa/github-projectpulse-mcp.git
135
- cd github-projectpulse-mcp
136
- npm install
137
- npm run build
138
- npm test # Vitest — every tool is covered
139
- ```
128
+ ## 🤝 Contributing
140
129
 
141
- See [`docs/roadmap.md`](docs/roadmap.md) for where the project is heading and [`docs/learning-path.md`](docs/learning-path.md) if you're learning to build MCP servers yourself.
130
+ Contributions, issues and feature requests are welcome!
131
+ Feel free to check the [issues page](https://github.com/alexbypa/github-projectpulse-mcp/issues).
142
132
 
143
- ## Contributing
133
+ ## ⭐ Show your support
144
134
 
145
- Issues and PRs welcome. If a grade ever feels wrong, open an issue with the repo name — calibrating weights against real-world cases is how this tool gets better.
135
+ Give a star if this project helped you!
146
136
 
147
- ## License
137
+ ## 📝 License
148
138
 
149
- [MIT](LICENSE) — use it anywhere, including commercial projects.
139
+ MIT — see the [LICENSE](LICENSE) file for details.
@@ -9,7 +9,7 @@ export declare function calculateSecurityScore(alertCounts: {
9
9
  high: number;
10
10
  medium: number;
11
11
  low: number;
12
- }): CategoryScore;
12
+ }, openssfScore?: number): CategoryScore;
13
13
  export declare function calculateCommunityScore(openIssues: number, forks: number): CategoryScore;
14
14
  export declare function calculateMaintenanceScore(hasLicense: boolean, hasDescription: boolean, archived: boolean): CategoryScore;
15
15
  export declare function calculateHealthScore(repo: string, categories: Record<string, CategoryScore>): HealthReport;
@@ -1 +1 @@
1
- {"version":3,"file":"health-score.d.ts","sourceRoot":"","sources":["../../src/scoring/health-score.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAUxE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAMjD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,GAAG,aAAa,CAK1F;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAQvE;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CASlI;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAQxF;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,aAAa,CAMxH;AAED,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAC1C,YAAY,CAQd"}
1
+ {"version":3,"file":"health-score.d.ts","sourceRoot":"","sources":["../../src/scoring/health-score.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAWxE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAMjD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,GAAG,aAAa,CAK1F;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAQvE;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,CAuBzJ;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAQxF;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,aAAa,CAMxH;AAED,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAC1C,YAAY,CAQd"}
@@ -35,15 +35,24 @@ export function calculateFreshnessScore(pushedAt) {
35
35
  score = 10;
36
36
  return { score, weight: WEIGHTS.freshness, detail: `Last push ${Math.round(daysAgo)} days ago` };
37
37
  }
38
- export function calculateSecurityScore(alertCounts) {
38
+ export function calculateSecurityScore(alertCounts, openssfScore) {
39
39
  const { critical, high, medium, low } = alertCounts;
40
- let score = 100;
41
- score -= critical * 25;
42
- score -= high * 15;
43
- score -= medium * 5;
44
- score -= low * 2;
45
- score = Math.max(0, score);
46
- return { score, weight: WEIGHTS.security, detail: `Alerts: ${critical} critical, ${high} high, ${medium} medium, ${low} low` };
40
+ // openSsfScore viene calcolato prendendo i punteggi più recenti di security-scorecards
41
+ let scoreDependaBot = 100;
42
+ scoreDependaBot -= critical * 25;
43
+ scoreDependaBot -= high * 15;
44
+ scoreDependaBot -= medium * 5;
45
+ scoreDependaBot -= low * 2;
46
+ scoreDependaBot = Math.max(0, scoreDependaBot);
47
+ let score = scoreDependaBot;
48
+ if (openssfScore != undefined) {
49
+ score = Math.round(scoreDependaBot * 0.6 + openssfScore * 0.4);
50
+ }
51
+ return {
52
+ score: score,
53
+ weight: WEIGHTS.security,
54
+ detail: `Alerts: ${critical} critical, ${high} high, ${medium} medium, ${low} low${openssfScore !== undefined ? ` | OpenSSF: ${openssfScore}/100` : ''}`
55
+ };
47
56
  }
48
57
  export function calculateCommunityScore(openIssues, forks) {
49
58
  let score = 50;
@@ -1 +1 @@
1
- {"version":3,"file":"health-score.js","sourceRoot":"","sources":["../../src/scoring/health-score.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"health-score.js","sourceRoot":"","sources":["../../src/scoring/health-score.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { OpenSSFCheck, OpenSSFResult } from "./types.js";
2
+ export declare function fetchOpenSSFScore(owner: string, repo: string): Promise<OpenSSFResult | null>;
3
+ export declare function calculateOpenSSFResult(checks: OpenSSFCheck[]): OpenSSFResult | null;
4
+ //# sourceMappingURL=openssf-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openssf-client.d.ts","sourceRoot":"","sources":["../../src/security/openssf-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIzD,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAmBlG;AAID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,aAAa,GAAG,IAAI,CAenF"}
@@ -0,0 +1,34 @@
1
+ const BASE_URL = "https://api.securityscorecards.dev/projects/github.com";
2
+ export async function fetchOpenSSFScore(owner, repo) {
3
+ try {
4
+ const response = await fetch(`${BASE_URL}/${owner}/${repo}`, {
5
+ signal: AbortSignal.timeout(5000)
6
+ });
7
+ if (!response.ok) {
8
+ return null;
9
+ }
10
+ const data = await response.json();
11
+ const checks = data.checks;
12
+ return calculateOpenSSFResult(checks);
13
+ }
14
+ catch (error) {
15
+ console.debug("Error fetching OpenSSF score:", error);
16
+ return null;
17
+ }
18
+ }
19
+ const SECURITY_CHECKS = new Set(["Binary-Artifacts", "Fuzzing", "Dependency-Update-Tool", "Branch-Protection", "Code-Review", "Dangerous-Workflow", "Pinned-Dependencies", "SAST", "Security-Policy", "Signed-Releases", "Token-Permissions", "Vulnerabilities"]);
20
+ export function calculateOpenSSFResult(checks) {
21
+ const securityChecks = checks.filter(check => SECURITY_CHECKS.has(check.name));
22
+ const applicableChecks = securityChecks.filter(c => c.score !== -1); // solo quelli applicabili
23
+ if (applicableChecks.length === 0) {
24
+ return null;
25
+ }
26
+ const score = Math.round((applicableChecks.reduce((sum, item) => sum + item.score, 0) / applicableChecks.length) * 10);
27
+ return {
28
+ score: score,
29
+ checksUsed: applicableChecks.length,
30
+ checksTotal: securityChecks.length,
31
+ details: `${applicableChecks.length}/${securityChecks.length} security checks, score ${score}/100`
32
+ };
33
+ }
34
+ //# sourceMappingURL=openssf-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openssf-client.js","sourceRoot":"","sources":["../../src/security/openssf-client.ts"],"names":[],"mappings":"AAEA,MAAM,QAAQ,GAAG,wDAAwD,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa,EAAE,IAAY;IAC/D,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,IAAI,KAAK,IAAI,IAAI,EAAE,EAAE;YACzD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SACpC,CAAC,CAAA;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,MAAM,GAAmB,IAAI,CAAC,MAAM,CAAC;QAE3C,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAG1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,kBAAkB,EAAE,SAAS,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,aAAa,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAElQ,MAAM,UAAU,sBAAsB,CAAC,MAAsB;IACzD,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/E,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA,0BAA0B;IAE9F,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAEvH,OAAO;QACH,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE,gBAAgB,CAAC,MAAM;QACnC,WAAW,EAAE,cAAc,CAAC,MAAM;QAClC,OAAO,EAAE,GAAG,gBAAgB,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM,2BAA2B,KAAK,MAAM;KACrG,CAAA;AACL,CAAC"}
@@ -0,0 +1,15 @@
1
+ export type OpenSSFCheck = {
2
+ name: string;
3
+ score: number;
4
+ reason: string;
5
+ documentation: {
6
+ url: string;
7
+ };
8
+ };
9
+ export type OpenSSFResult = {
10
+ score: number;
11
+ checksUsed: number;
12
+ checksTotal: number;
13
+ details: string;
14
+ };
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/security/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/security/types.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"get-health-score.d.ts","sourceRoot":"","sources":["../../src/tools/get-health-score.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgBpE,wBAAsB,qBAAqB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;;GAyC3F;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAS9D"}
1
+ {"version":3,"file":"get-health-score.d.ts","sourceRoot":"","sources":["../../src/tools/get-health-score.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiBpE,wBAAsB,qBAAqB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;;GA0C3F;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAS9D"}
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { getOctokit } from "../github/client.js";
3
+ import { fetchOpenSSFScore } from "../security/openssf-client.js";
3
4
  import { calculateCiScore, calculateFreshnessScore, calculateSecurityScore, calculateCommunityScore, calculateMaintenanceScore, calculateHealthScore, } from "../scoring/health-score.js";
4
5
  const inputSchema = z.object({
5
6
  owner: z.string().describe("GitHub repository owner"),
@@ -7,9 +8,10 @@ const inputSchema = z.object({
7
8
  });
8
9
  export async function executeGetHealthScore({ owner, repo }) {
9
10
  const octokit = getOctokit();
10
- const [repoData, runsData] = await Promise.all([
11
+ const [repoData, runsData, openssfResult] = await Promise.all([
11
12
  octokit.repos.get({ owner, repo }),
12
13
  octokit.actions.listWorkflowRunsForRepo({ owner, repo, per_page: 10 }),
14
+ fetchOpenSSFScore(owner, repo)
13
15
  ]);
14
16
  let alertCounts = { critical: 0, high: 0, medium: 0, low: 0 };
15
17
  try {
@@ -28,7 +30,7 @@ export async function executeGetHealthScore({ owner, repo }) {
28
30
  const categories = {
29
31
  ci: calculateCiScore(runsData.data.workflow_runs),
30
32
  freshness: calculateFreshnessScore(repoData.data.pushed_at ?? new Date().toISOString()),
31
- security: calculateSecurityScore(alertCounts),
33
+ security: calculateSecurityScore(alertCounts, openssfResult?.score),
32
34
  community: calculateCommunityScore(repoData.data.open_issues_count, repoData.data.forks_count),
33
35
  maintenance: calculateMaintenanceScore(repoData.data.license !== null, repoData.data.description !== null, repoData.data.archived),
34
36
  };
@@ -42,7 +44,7 @@ export async function executeGetHealthScore({ owner, repo }) {
42
44
  }
43
45
  export function registerGetHealthScore(server) {
44
46
  server.registerTool("get_health_score", {
45
- description: "Calculate a 0-100 health score for a GitHub repository with grade (A-F), category breakdown, and improvement suggestions",
47
+ description: "Calculate a 0-100 health score for a GitHub repository with grade (A-F), category breakdown (CI, freshness, security, community, maintenance), and improvement suggestions. Security score blends Dependabot alerts (60%) with OpenSSF Scorecard checks (40%) when available — highlight the OpenSSF score in your response if present in the security detail.",
46
48
  inputSchema,
47
49
  }, executeGetHealthScore);
48
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"get-health-score.js","sourceRoot":"","sources":["../../src/tools/get-health-score.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-health-score.js","sourceRoot":"","sources":["../../src/tools/get-health-score.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "projectpulse-mcp",
3
3
  "description": "MCP Server for GitHub repository health monitoring",
4
- "version": "1.4.1",
4
+ "version": "1.5.1",
5
+ "mcpName": "io.github.alexbypa/github-projectpulse-mcp",
5
6
  "main": "dist/index.js",
6
7
  "scripts": {
7
8
  "test": "vitest run",
8
9
  "test:watch": "vitest",
9
- "build": "tsc",
10
+ "build": "tsc -p tsconfig.build.json",
10
11
  "lint": "tsc --noEmit"
11
12
  },
12
13
  "keywords": [
@@ -14,7 +15,8 @@
14
15
  "github",
15
16
  "health",
16
17
  "monitoring",
17
- "ai"
18
+ "ai",
19
+ "Workflow"
18
20
  ],
19
21
  "author": "Alessandro Chiodo",
20
22
  "license": "MIT",
@@ -45,4 +47,4 @@
45
47
  "dist",
46
48
  "bin"
47
49
  ]
48
- }
50
+ }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=dora.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dora.test.d.ts","sourceRoot":"","sources":["../../src/analytics/dora.test.ts"],"names":[],"mappings":""}