@mcpskillsio/server 2.0.0 → 2.1.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 (3) hide show
  1. package/README.md +37 -5
  2. package/index.js +235 -52
  3. package/package.json +6 -4
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Trust-score any AI skill or MCP server from inside Claude Code, Cursor, or any MCP client.
4
4
 
5
- 12 signals across 4 dimensions with safety scanning for prompt injection, credential theft, and supply chain attacks.
5
+ 14 signals across 4 dimensions with safety scanning for prompt injection, credential theft, and supply chain attacks.
6
6
 
7
7
  ## Install
8
8
 
@@ -68,11 +68,43 @@ Browse curated, pre-scored skill packages organized by use case.
68
68
  "Show me safe AI skill packages for full-stack development"
69
69
  ```
70
70
 
71
+ ### `get_badge`
72
+
73
+ Generate an SVG trust badge URL for your README.
74
+
75
+ ```
76
+ "Get a trust badge for my repo anthropics/anthropic-sdk-typescript"
77
+ ```
78
+
79
+ ### `watch_repo`
80
+
81
+ Start monitoring a repo for trust score changes (requires API key).
82
+
83
+ ```
84
+ "Watch modelcontextprotocol/servers for score changes"
85
+ ```
86
+
87
+ ### `batch_check`
88
+
89
+ Score up to 5 repos in a single call (Pro tier).
90
+
91
+ ```
92
+ "Batch check these repos: anthropics/anthropic-sdk-typescript, langchain-ai/langchainjs"
93
+ ```
94
+
95
+ ### `auto_gate`
96
+
97
+ Get a boolean go/no-go decision with reasoning.
98
+
99
+ ```
100
+ "Should I install this MCP server? 21st-dev/magic-mcp"
101
+ ```
102
+
71
103
  ## Full Reports
72
104
 
73
105
  Free tier returns trust tier + dimension scores (same as mcpskills.io free scans).
74
106
 
75
- For full 12-signal reports with detailed safety findings inside your IDE, set your API key:
107
+ For full 14-signal reports with detailed safety findings inside your IDE, set your API key:
76
108
 
77
109
  ```bash
78
110
  export MCPSKILLS_API_KEY=your_key_here
@@ -85,10 +117,10 @@ Get your API key at [mcpskills.io/api](https://mcpskills.io/api).
85
117
  The server calls the mcpskills.io trust scoring API, which:
86
118
 
87
119
  1. Fetches repo data from GitHub API and OpenSSF Scorecard
88
- 2. Scores 12 signals across 4 dimensions (Alive, Legit, Solid, Usable)
89
- 3. Detects AI skills/MCP servers and activates Skills Mode
120
+ 2. Scores 14 signals across 4 dimensions (Alive, Legit, Solid, Usable)
121
+ 3. Detects AI skills/MCP servers and activates Skills Mode (+2 bonus signals)
90
122
  4. Runs 5 safety scans based on ClawHavoc and ToxicSkills attack patterns
91
- 5. Assigns a trust tier: Verified (7.5), Established (4.5), New, or Blocked
123
+ 5. Assigns a trust tier: Verified (>=7.0), Established (>=4.5), New, or Blocked
92
124
 
93
125
  ## License
94
126
 
package/index.js CHANGED
@@ -10,10 +10,15 @@
10
10
  * - check_trust_score: Score any GitHub repo
11
11
  * - scan_safety: Run safety-only scan for AI skills
12
12
  * - list_packages: Browse curated safe skill packages
13
+ * - get_badge: Get trust badge URL for READMEs
14
+ * - watch_repo: Monitor a repo for score changes
15
+ * - check_watched: Re-scan all watched repos
16
+ * - batch_check: Check up to 5 repos in one call (Pro)
17
+ * - auto_gate: "Should I install this?" → boolean + reason
13
18
  *
14
- * Free tier returns tier + dimension scores.
15
- * Full reports (all 12 signals + safety findings) require an API key.
16
- * Get your key at https://mcpskills.io/api
19
+ * Free tier returns compact agent response.
20
+ * Full reports require MCPSKILLS_API_KEY env var.
21
+ * Get your key at https://mcpskills.io
17
22
  */
18
23
 
19
24
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -29,7 +34,10 @@ const PACKAGES_URL = "https://mcpskills.io/.netlify/functions/packages";
29
34
  // --- API Client ---
30
35
 
31
36
  async function fetchScore(repo, apiKey) {
32
- const headers = { "Content-Type": "application/json" };
37
+ const headers = {
38
+ "Content-Type": "application/json",
39
+ "Accept": "application/json",
40
+ };
33
41
  if (apiKey) headers["X-API-Key"] = apiKey;
34
42
 
35
43
  const res = await fetch(`${API_BASE}/score`, {
@@ -38,6 +46,16 @@ async function fetchScore(repo, apiKey) {
38
46
  body: JSON.stringify({ repo }),
39
47
  });
40
48
 
49
+ if (res.status === 429) {
50
+ const err = await res.json().catch(() => ({}));
51
+ throw new Error(`Rate limit exceeded. ${err.upgrade || 'Set MCPSKILLS_API_KEY for more scans.'}`);
52
+ }
53
+
54
+ if (res.status === 401 || res.status === 403) {
55
+ const err = await res.json().catch(() => ({}));
56
+ throw new Error(err.error || `Auth error: ${res.status}`);
57
+ }
58
+
41
59
  if (!res.ok) {
42
60
  const err = await res.json().catch(() => ({ error: res.statusText }));
43
61
  throw new Error(err.error || `API error: ${res.status}`);
@@ -60,11 +78,12 @@ function formatTier(tier) {
60
78
  }
61
79
 
62
80
  function formatDimensions(dims) {
81
+ if (!dims) return " (dimensions unavailable)";
63
82
  return [
64
- ` Alive: ${dims.alive}/10 (maintained?)`,
65
- ` Legit: ${dims.legit}/10 (credible author?)`,
66
- ` Solid: ${dims.solid}/10 (secure?)`,
67
- ` Usable: ${dims.usable}/10 (good docs?)`,
83
+ ` Alive: ${dims.alive ?? '?'}/10 (maintained?)`,
84
+ ` Legit: ${dims.legit ?? '?'}/10 (credible author?)`,
85
+ ` Solid: ${dims.solid ?? '?'}/10 (secure?)`,
86
+ ` Usable: ${dims.usable ?? '?'}/10 (good docs?)`,
68
87
  ].join("\n");
69
88
  }
70
89
 
@@ -94,39 +113,33 @@ function formatRecommendations(recs) {
94
113
  return lines;
95
114
  }
96
115
 
97
- function formatFreeResult(data) {
116
+ // --- Agent Response Formatting ---
117
+
118
+ function formatAgentResponse(data) {
119
+ // Compact agent response (from free tier API)
120
+ const rec = data.recommendation || (data.safe ? 'install' : 'caution');
121
+ const icon = data.safe ? '✅' : data.recommendation === 'blocked' ? '🚫' : '⚠️';
122
+
98
123
  const lines = [
99
- `# Trust Score: ${data.repo}`,
100
- "",
101
- `**Score:** ${data.composite}/10`,
102
- `**Tier:** ${formatTier(data.tier)}`,
103
- `**Mode:** ${data.mode === "skills" ? "Skills Mode (AI skill detected)" : "Standard Mode"}`,
104
- "",
105
- `## Dimensions`,
106
- formatDimensions(data.dimensions),
107
- "",
108
- `⭐ ${data.meta.stars.toLocaleString()} stars | 🍴 ${data.meta.forks.toLocaleString()} forks | 📄 ${data.meta.license}`,
124
+ `${icon} ${data.safe ? 'SAFE to install' : 'CAUTION'} — ${formatTier(data.tier)} (${data.score}/10)`,
125
+ `Recommendation: ${rec}`,
109
126
  ];
110
127
 
111
- if (data.mode === "skills" && data.skill) {
112
- lines.push("", `## Skill Info`);
113
- lines.push(` Type: ${data.skill.type}`);
114
- lines.push(` Safety: ${data.skill.safety?.summary || "Not scanned"}`);
128
+ if (data.flags?.length > 0) {
129
+ lines.push(`Flags: ${data.flags.join(', ')}`);
115
130
  }
116
131
 
117
- // Recommendations
118
- if (data.recommendations) {
119
- lines.push(...formatRecommendations(data.recommendations));
132
+ if (data.reasoning) {
133
+ lines.push(`Analysis: ${data.reasoning}`);
120
134
  }
121
135
 
122
- lines.push(
123
- "",
124
- "---",
125
- "🔒 Full report (all signals + safety findings) → https://mcpskills.io",
126
- "Set MCPSKILLS_API_KEY for full reports in-context."
127
- );
136
+ if (data.certified) {
137
+ lines.push('🏅 Certified Safe by MCP Skills');
138
+ }
128
139
 
129
- return lines.join("\n");
140
+ lines.push('', 'Set MCPSKILLS_API_KEY for full 14-signal breakdown.');
141
+
142
+ return lines.join('\n');
130
143
  }
131
144
 
132
145
  function formatFullResult(data) {
@@ -161,21 +174,38 @@ function formatFullResult(data) {
161
174
  supply_chain_safety: "Supply Chain Safety",
162
175
  };
163
176
 
164
- for (const [key, val] of Object.entries(data.signals)) {
177
+ for (const [key, val] of Object.entries(data.signals || {})) {
165
178
  const label = signalLabels[key] || key;
166
- const bar = "█".repeat(Math.round(val)) + "░".repeat(10 - Math.round(val));
167
- lines.push(` ${bar} ${val}/10 ${label}`);
179
+ const v = typeof val === 'number' && !isNaN(val) ? val : 0;
180
+ const bar = "█".repeat(Math.round(v)) + "░".repeat(10 - Math.round(v));
181
+ lines.push(` ${bar} ${v}/10 ${label}`);
168
182
  }
169
183
 
170
184
  lines.push(
171
185
  "",
172
- `⭐ ${data.meta.stars.toLocaleString()} stars | 🍴 ${data.meta.forks.toLocaleString()} forks | 📄 ${data.meta.license}`
186
+ `⭐ ${(data.meta?.stars || 0).toLocaleString()} stars | 🍴 ${(data.meta?.forks || 0).toLocaleString()} forks | 📄 ${data.meta?.license || 'Unknown'}`
173
187
  );
174
188
 
175
189
  if (data.mode === "skills" && data.skill) {
176
190
  lines.push("", `## Skill Details`);
177
191
  lines.push(` Type: ${data.skill.type}`);
178
- lines.push(` Indicators: ${data.skill.indicators.join(", ")}`);
192
+ if (data.skill.indicators) lines.push(` Indicators: ${data.skill.indicators.join(", ")}`);
193
+
194
+ // OpenClaw frontmatter
195
+ if (data.skill.frontmatter) {
196
+ lines.push("", ` ### SKILL.md Frontmatter`);
197
+ const fm = data.skill.frontmatter;
198
+ if (fm.name) lines.push(` Name: ${fm.name}`);
199
+ if (fm.version) lines.push(` Version: ${fm.version}`);
200
+ if (fm.description) lines.push(` Description: ${fm.description}`);
201
+ if (data.skill.transparency?.bonus > 0) {
202
+ lines.push(` 🛡️ Transparency bonus: +${data.skill.transparency.bonus} to tool_safety`);
203
+ const d = data.skill.transparency.details;
204
+ if (d.hasSecuritySection) lines.push(` ✓ Declares security posture`);
205
+ if (d.hasAllowedTools) lines.push(` ✓ Lists allowed tools (${d.allowedToolsCount})`);
206
+ if (d.hasRequires) lines.push(` ✓ Declares requirements`);
207
+ }
208
+ }
179
209
 
180
210
  if (data.skill.specChecks) {
181
211
  lines.push("", ` ### Spec Compliance`);
@@ -201,7 +231,6 @@ function formatFullResult(data) {
201
231
  lines.push("", `## ⚠️ Disqualifiers: ${data.disqualifiers.join(", ")}`);
202
232
  }
203
233
 
204
- // Recommendations
205
234
  if (data.recommendations) {
206
235
  lines.push(...formatRecommendations(data.recommendations));
207
236
  }
@@ -214,14 +243,15 @@ function formatFullResult(data) {
214
243
 
215
244
  function formatSafetyResult(data) {
216
245
  if (data.mode !== "skills" || !data.skill) {
246
+ const score = data.composite ?? data.score ?? '?';
217
247
  return [
218
248
  `# Safety Scan: ${data.repo}`,
219
249
  "",
220
250
  "This repo was not detected as an AI skill or MCP server.",
221
251
  "Safety scanning only runs on repos identified as skills.",
222
252
  "",
223
- `Mode: ${data.mode}`,
224
- `Score: ${data.composite}/10 | Tier: ${formatTier(data.tier)}`,
253
+ `Mode: ${data.mode || 'standard'}`,
254
+ `Score: ${score}/10 | Tier: ${formatTier(data.tier)}`,
225
255
  ].join("\n");
226
256
  }
227
257
 
@@ -229,7 +259,7 @@ function formatSafetyResult(data) {
229
259
  `# Safety Scan: ${data.repo}`,
230
260
  "",
231
261
  `**Skill Type:** ${data.skill.type}`,
232
- `**Safety Score:** ${data.signals.tool_safety}/10`,
262
+ `**Safety Score:** ${data.signals?.tool_safety ?? '?'}/10`,
233
263
  `**Status:** ${data.skill.safety?.summary || "Unknown"}`,
234
264
  "",
235
265
  ];
@@ -278,7 +308,7 @@ function formatSafetyResult(data) {
278
308
  const server = new Server(
279
309
  {
280
310
  name: "mcpskills",
281
- version: "2.0.0",
311
+ version: "2.1.0",
282
312
  },
283
313
  {
284
314
  capabilities: {
@@ -294,7 +324,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
294
324
  {
295
325
  name: "check_trust_score",
296
326
  description:
297
- "Score any GitHub repo for trustworthiness. Returns a trust score (0-10) across 4 dimensions: Alive (maintained?), Legit (credible author?), Solid (secure?), Usable (good docs?). AI skills and MCP servers get enhanced scanning with 5 safety checks. Set MCPSKILLS_API_KEY env var for full 12-signal reports.",
327
+ "Score any GitHub repo for trustworthiness. Returns a trust score (0-10) across 4 dimensions: Alive (maintained?), Legit (credible author?), Solid (secure?), Usable (good docs?). AI skills and MCP servers get enhanced scanning with 5 safety checks. Set MCPSKILLS_API_KEY env var for full 14-signal reports.",
298
328
  inputSchema: {
299
329
  type: "object",
300
330
  properties: {
@@ -356,7 +386,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
356
386
  {
357
387
  name: "watch_repo",
358
388
  description:
359
- "Start monitoring a repo for trust score changes. You'll be alerted when a repo's score changes significantly (±0.3 points or tier change). Free tier: up to 20 repos.",
389
+ "Start monitoring a repo for trust score changes. You'll be alerted when a repo's score changes significantly (±0.3 points or tier change). Requires a paid API key.",
360
390
  inputSchema: {
361
391
  type: "object",
362
392
  properties: {
@@ -387,6 +417,37 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
387
417
  required: ["email"],
388
418
  },
389
419
  },
420
+ {
421
+ name: "batch_check",
422
+ description:
423
+ "Check up to 5 repos in one call. Returns a trust assessment for each repo. Requires a Pro API key (MCPSKILLS_API_KEY). Great for bulk-vetting dependencies.",
424
+ inputSchema: {
425
+ type: "object",
426
+ properties: {
427
+ repos: {
428
+ type: "array",
429
+ items: { type: "string" },
430
+ description: 'Array of GitHub repos in "owner/repo" format (max 5)',
431
+ },
432
+ },
433
+ required: ["repos"],
434
+ },
435
+ },
436
+ {
437
+ name: "auto_gate",
438
+ description:
439
+ 'Should I install this? Returns a simple go/no-go decision with reasoning. The fastest way to check if a repo is safe to use. Returns { proceed: true/false, reason: "..." }.',
440
+ inputSchema: {
441
+ type: "object",
442
+ properties: {
443
+ repo: {
444
+ type: "string",
445
+ description: 'GitHub repo in "owner/repo" format',
446
+ },
447
+ },
448
+ required: ["repo"],
449
+ },
450
+ },
390
451
  ],
391
452
  };
392
453
  });
@@ -413,9 +474,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
413
474
  }
414
475
 
415
476
  const data = await fetchScore(repo, apiKey);
416
- const formatted = apiKey
417
- ? formatFullResult(data)
418
- : formatFreeResult(data);
477
+
478
+ // Determine if we got a full response or agent compact response
479
+ let formatted;
480
+ if (data.signals && data.dimensions) {
481
+ // Full paid response
482
+ formatted = formatFullResult(data);
483
+ } else if (data.safe !== undefined) {
484
+ // Agent compact response
485
+ formatted = formatAgentResponse(data);
486
+ } else {
487
+ // Human free response — format it for the agent
488
+ formatted = `${formatTier(data.tier)} ${data.repo} — ${data.composite}/10\n\nSet MCPSKILLS_API_KEY for full signal breakdown.`;
489
+ }
419
490
 
420
491
  return { content: [{ type: "text", text: formatted }] };
421
492
  }
@@ -471,9 +542,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
471
542
  lines.push("");
472
543
  const items = pkg.skills || pkg.repos || [];
473
544
  for (const item of items) {
474
- const name = item.name || `${item.owner}/${item.repo}`;
545
+ const itemName = item.name || `${item.owner}/${item.repo}`;
475
546
  const desc = item.description || item.role || "";
476
- lines.push(` - **${name}** — ${desc}`);
547
+ lines.push(` - **${itemName}** — ${desc}`);
477
548
  }
478
549
  lines.push("");
479
550
  }
@@ -535,13 +606,23 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
535
606
  };
536
607
  }
537
608
 
609
+ const headers = { "Content-Type": "application/json" };
610
+ if (apiKey) headers["X-API-Key"] = apiKey;
611
+
538
612
  const res = await fetch(`${API_BASE}/monitor`, {
539
613
  method: "POST",
540
- headers: { "Content-Type": "application/json" },
614
+ headers,
541
615
  body: JSON.stringify({ action: "watch", repo, email }),
542
616
  });
543
617
  const data = await res.json();
544
618
 
619
+ if (res.status === 403) {
620
+ return {
621
+ content: [{ type: "text", text: data.error || "Monitoring requires a paid plan. Get one at https://mcpskills.io" }],
622
+ isError: true,
623
+ };
624
+ }
625
+
545
626
  const lines = [
546
627
  `# Watching ${repo}`,
547
628
  "",
@@ -566,9 +647,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
566
647
  };
567
648
  }
568
649
 
650
+ const headers = { "Content-Type": "application/json" };
651
+ if (apiKey) headers["X-API-Key"] = apiKey;
652
+
569
653
  const res = await fetch(`${API_BASE}/monitor`, {
570
654
  method: "POST",
571
- headers: { "Content-Type": "application/json" },
655
+ headers,
572
656
  body: JSON.stringify({ action: "check", email }),
573
657
  });
574
658
  const data = await res.json();
@@ -599,6 +683,105 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
599
683
  return { content: [{ type: "text", text: lines.join("\n") }] };
600
684
  }
601
685
 
686
+ case "batch_check": {
687
+ const repos = args.repos;
688
+ if (!Array.isArray(repos) || repos.length === 0) {
689
+ return {
690
+ content: [{ type: "text", text: "Provide an array of repos to check." }],
691
+ isError: true,
692
+ };
693
+ }
694
+
695
+ if (!apiKey) {
696
+ return {
697
+ content: [{ type: "text", text: "batch_check requires a Pro API key. Set MCPSKILLS_API_KEY env var.\nGet one at https://mcpskills.io" }],
698
+ isError: true,
699
+ };
700
+ }
701
+
702
+ const batch = repos.slice(0, 5);
703
+ const results = [];
704
+
705
+ for (const repo of batch) {
706
+ if (!repo.includes("/")) {
707
+ results.push(`❌ ${repo} — invalid format`);
708
+ continue;
709
+ }
710
+ try {
711
+ const data = await fetchScore(repo, apiKey);
712
+ if (data.safe !== undefined) {
713
+ const icon = data.safe ? '✅' : data.recommendation === 'blocked' ? '🚫' : '⚠️';
714
+ results.push(`${icon} ${repo} — ${data.tier} (${data.score}/10) → ${data.recommendation}`);
715
+ } else if (data.signals) {
716
+ results.push(`${formatTier(data.tier)} ${repo} — ${data.composite}/10`);
717
+ } else {
718
+ results.push(`${formatTier(data.tier)} ${repo} — ${data.composite}/10`);
719
+ }
720
+ } catch (err) {
721
+ results.push(`❌ ${repo} — ${err.message}`);
722
+ }
723
+ }
724
+
725
+ const lines = [
726
+ `# Batch Trust Check (${batch.length} repos)`,
727
+ "",
728
+ ...results,
729
+ "",
730
+ `Checked ${batch.length} of ${repos.length} repos.`,
731
+ ];
732
+
733
+ if (repos.length > 5) {
734
+ lines.push(`⚠️ Max 5 per batch. ${repos.length - 5} skipped.`);
735
+ }
736
+
737
+ lines.push("", "---", "Powered by mcpskills.io");
738
+ return { content: [{ type: "text", text: lines.join("\n") }] };
739
+ }
740
+
741
+ case "auto_gate": {
742
+ const repo = args.repo;
743
+ if (!repo || !repo.includes("/")) {
744
+ return {
745
+ content: [{ type: "text", text: 'Invalid repo format. Use "owner/repo".' }],
746
+ isError: true,
747
+ };
748
+ }
749
+
750
+ const data = await fetchScore(repo, apiKey);
751
+
752
+ let proceed, reason;
753
+
754
+ if (data.safe !== undefined) {
755
+ // Agent compact response
756
+ proceed = data.safe || data.certified;
757
+ if (data.certified) {
758
+ reason = `Certified Safe — verified by MCP Skills (${data.score}/10)`;
759
+ } else if (data.safe) {
760
+ reason = `${data.tier} (${data.score}/10). ${data.reasoning || 'No disqualifiers.'}`;
761
+ } else {
762
+ reason = `${data.recommendation}: ${data.flags?.join(', ') || data.reasoning || 'Review needed.'}`;
763
+ }
764
+ } else {
765
+ // Full or human response — derive go/no-go
766
+ const tier = data.tier;
767
+ const disqualifiers = data.disqualifiers || [];
768
+ proceed = (tier === 'verified' || tier === 'established') && disqualifiers.length === 0;
769
+ const score = data.composite ?? data.score;
770
+ reason = proceed
771
+ ? `${tier} (${score}/10). Safe to install.`
772
+ : `${tier} (${score}/10). ${disqualifiers.length ? 'Disqualifiers: ' + disqualifiers.join(', ') : 'Review recommended.'}`;
773
+ }
774
+
775
+ const icon = proceed ? '✅' : '🚫';
776
+ const text = [
777
+ `${icon} ${proceed ? 'PROCEED' : 'DO NOT INSTALL'} — ${repo}`,
778
+ '',
779
+ reason,
780
+ ].join('\n');
781
+
782
+ return { content: [{ type: "text", text }] };
783
+ }
784
+
602
785
  default:
603
786
  return {
604
787
  content: [{ type: "text", text: `Unknown tool: ${name}` }],
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "@mcpskillsio/server",
3
- "version": "2.0.0",
4
- "description": "Trust-score any AI skill or MCP server from inside Claude Code, Cursor, or any MCP client. 14 signals, safety scanning, recommendations, badges, and monitoring.",
3
+ "version": "2.1.1",
4
+ "description": "Trust-score any AI skill or MCP server from inside Claude Code, Cursor, or any MCP client. 14 signals, safety scanning, recommendations, badges, monitoring, batch checking, and auto-gate decisions.",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "bin": {
8
8
  "mcpskills": "index.js"
9
9
  },
10
10
  "scripts": {
11
- "start": "node index.js"
11
+ "start": "node index.js",
12
+ "test": "node --test test/"
12
13
  },
13
14
  "keywords": [
14
15
  "mcp",
@@ -24,7 +25,8 @@
24
25
  "license": "MIT",
25
26
  "repository": {
26
27
  "type": "git",
27
- "url": "https://github.com/bebravebekind/mcpskills-server"
28
+ "url": "https://github.com/BeBraveBeKind/mcpskills.git",
29
+ "directory": "mcp-server"
28
30
  },
29
31
  "homepage": "https://mcpskills.io",
30
32
  "engines": {