skillmds 0.1.0 → 1.0.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 +128 -0
- package/bin/skillmd-mcp.mjs +35 -1
- package/bin/skillmd.mjs +3 -0
- package/dist/cli.js +933 -0
- package/package.json +38 -6
- package/vendor/index.js +7656 -0
package/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://skillmd.com/skillmd-banner.jpg" alt="SkillMD" width="640">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# skillmds
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/skillmds)
|
|
8
|
+
[](https://www.npmjs.com/package/skillmds)
|
|
9
|
+
[](#license)
|
|
10
|
+
|
|
11
|
+
> SkillMD for agents — the official **MCP server** *and* the **`skillmd` CLI** for **[SkillMD](https://skillmd.com)**, the open, verified registry of Agent Skills.
|
|
12
|
+
|
|
13
|
+
This one package ships two tools:
|
|
14
|
+
|
|
15
|
+
- **`skillmds`** — an MCP server so any MCP-capable agent (Claude Code, Claude Desktop, Cursor, …) can search, fetch, validate, and install `SKILL.md` skills with no copy-paste.
|
|
16
|
+
- **`skillmd`** — a CLI that lints and security-scans skills before installing or publishing them. *The registry that lints.*
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## CLI quick start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm i -g skillmds # installs the `skillmd` command (and `skillmds`)
|
|
24
|
+
|
|
25
|
+
skillmd lint ./my-skill # validate against the spec + quality score
|
|
26
|
+
skillmd lint . --format sarif # SARIF for GitHub Code Scanning
|
|
27
|
+
skillmd scan . --deny executes_scripts
|
|
28
|
+
skillmd search pdf --verified
|
|
29
|
+
skillmd add anthropic/pdf -a claude-code -g # lints before installing
|
|
30
|
+
skillmd init my-skill
|
|
31
|
+
skillmd login && skillmd publish ./my-skill # refuses to publish on lint errors
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Without a global install, run a one-off with `npx -p skillmds skillmd lint .`.
|
|
35
|
+
Commands: `lint`/`check`, `scan`, `rules`, `init`, `search`, `add`, `list`, `remove`, `update`, `publish`, `login`. All support `--json`.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## MCP server
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
**Claude Code** (one line):
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
claude mcp add skillmds -- npx -y skillmds
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Claude Desktop / Cursor / any MCP client** — add to your MCP config:
|
|
50
|
+
|
|
51
|
+
```jsonc
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"skillmds": {
|
|
55
|
+
"command": "npx",
|
|
56
|
+
"args": ["-y", "skillmds"]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
That's it. Restart your client and the SkillMD tools are available.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## What you can do
|
|
67
|
+
|
|
68
|
+
Once connected, just ask your agent in plain language:
|
|
69
|
+
|
|
70
|
+
- *"Find a skill for optimizing Dockerfiles."*
|
|
71
|
+
- *"Install the anthropic/pdf skill."*
|
|
72
|
+
- *"What are the top-rated data skills right now?"*
|
|
73
|
+
|
|
74
|
+
The agent picks the right tool, fetches the skill from SkillMD, and writes it into your skills directory.
|
|
75
|
+
|
|
76
|
+
## Tools
|
|
77
|
+
|
|
78
|
+
| Tool | Auth | What it does |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| `skillmd_search` | – | Search skills by name, description, or task (filter by category, type, rating, verified). |
|
|
81
|
+
| `skillmd_get` | – | Fetch one skill by `owner/name`, with its `SKILL.md`, provenance, license, and security flags. |
|
|
82
|
+
| `skillmd_install` | – | Write a skill's `SKILL.md` into your agent's skills dir. **Never executes scripts.** |
|
|
83
|
+
| `skillmd_trending` | – | Top skills on the leaderboard (`30d` or `all`, optional category). |
|
|
84
|
+
| `skillmd_recommend` | – | Skills similar to one you give, or trending if none. |
|
|
85
|
+
| `skillmd_list_saved` | token | Your saved skills (requires `SKILLMD_TOKEN`). |
|
|
86
|
+
| `skillmd_lint` | – | Validate a SKILL.md against the spec; returns diagnostics, security flags, and a quality score (0-100). Pass `content` or a `slug`. |
|
|
87
|
+
|
|
88
|
+
By default, `skillmd_install` writes to `~/.claude/skills/<name>/SKILL.md`. Pass a `dest` to target another directory.
|
|
89
|
+
|
|
90
|
+
## Configuration
|
|
91
|
+
|
|
92
|
+
Both are optional environment variables:
|
|
93
|
+
|
|
94
|
+
| Variable | Default | Purpose |
|
|
95
|
+
| --- | --- | --- |
|
|
96
|
+
| `SKILLMD_API` | `https://skillmd-api.vinoor.workers.dev` | Override the API base URL. |
|
|
97
|
+
| `SKILLMD_TOKEN` | – | SkillMD personal access token; enables `skillmd_list_saved` and personalized recommendations. |
|
|
98
|
+
|
|
99
|
+
Example with a token:
|
|
100
|
+
|
|
101
|
+
```jsonc
|
|
102
|
+
{
|
|
103
|
+
"mcpServers": {
|
|
104
|
+
"skillmds": {
|
|
105
|
+
"command": "npx",
|
|
106
|
+
"args": ["-y", "skillmds"],
|
|
107
|
+
"env": { "SKILLMD_TOKEN": "skillmd_pat_…" }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Safety
|
|
114
|
+
|
|
115
|
+
SkillMD shows security flags (executes scripts, network calls, reads secrets, or docs-only) parsed from every skill's files, and **this server never runs a skill's scripts** — `skillmd_install` only writes the `SKILL.md` to disk. Review a skill before relying on it, especially from unverified authors.
|
|
116
|
+
|
|
117
|
+
## Requirements
|
|
118
|
+
|
|
119
|
+
- Node.js **18+**
|
|
120
|
+
|
|
121
|
+
## Links
|
|
122
|
+
|
|
123
|
+
- 🌐 Registry: **[skillmd.com](https://skillmd.com)**
|
|
124
|
+
- 🧩 What is an Agent Skill? See the [FAQ](https://skillmd.com/#faq)
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
MIT
|
package/bin/skillmd-mcp.mjs
CHANGED
|
@@ -14,6 +14,14 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprot
|
|
|
14
14
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
import { join, resolve } from "node:path";
|
|
17
|
+
// Shared validation engine, bundled into ./vendor at publish time (npm run build).
|
|
18
|
+
// Falls back gracefully if the vendor build is absent (e.g. running from source).
|
|
19
|
+
let lint = null;
|
|
20
|
+
try {
|
|
21
|
+
({ lint } = await import("../vendor/index.js"));
|
|
22
|
+
} catch {
|
|
23
|
+
/* skillmd_lint will report that validation is unavailable */
|
|
24
|
+
}
|
|
17
25
|
|
|
18
26
|
const API = process.env.SKILLMD_API || "https://skillmd-api.vinoor.workers.dev";
|
|
19
27
|
const TOKEN = process.env.SKILLMD_TOKEN || "";
|
|
@@ -86,6 +94,18 @@ const TOOLS = [
|
|
|
86
94
|
description: "List the signed-in user's saved skills. Requires SKILLMD_TOKEN to be set.",
|
|
87
95
|
inputSchema: { type: "object", properties: {} },
|
|
88
96
|
},
|
|
97
|
+
{
|
|
98
|
+
name: "skillmd_lint",
|
|
99
|
+
description:
|
|
100
|
+
"Validate a SKILL.md against the SkillMD spec and return diagnostics, security flags, and a quality score (0-100). Pass raw SKILL.md content, or a registry slug (owner/name) to fetch and lint.",
|
|
101
|
+
inputSchema: {
|
|
102
|
+
type: "object",
|
|
103
|
+
properties: {
|
|
104
|
+
content: { type: "string", description: "Raw SKILL.md content to validate" },
|
|
105
|
+
slug: { type: "string", description: "Registry slug owner/name to fetch and validate" },
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
89
109
|
];
|
|
90
110
|
|
|
91
111
|
function reconstructSkillMd(skill) {
|
|
@@ -134,6 +154,20 @@ async function handleCall(name, args) {
|
|
|
134
154
|
const r = await api(`/api/favorites`);
|
|
135
155
|
return text(r.items ?? []);
|
|
136
156
|
}
|
|
157
|
+
case "skillmd_lint": {
|
|
158
|
+
if (!lint) return text("Validation engine unavailable — run `npm run build` in the skillmds package.");
|
|
159
|
+
let raw = args.content;
|
|
160
|
+
let slug;
|
|
161
|
+
if (!raw && args.slug) {
|
|
162
|
+
const [owner, slugName] = String(args.slug).split("/");
|
|
163
|
+
const skill = await api(`/api/skills/${owner}/${slugName}`);
|
|
164
|
+
raw = reconstructSkillMd(skill);
|
|
165
|
+
slug = slugName;
|
|
166
|
+
}
|
|
167
|
+
if (!raw) return text("Provide `content` (raw SKILL.md) or `slug` (owner/name).");
|
|
168
|
+
const result = lint(raw, slug ? { slug } : {});
|
|
169
|
+
return text({ ok: result.ok, score: result.score, diagnostics: result.diagnostics, security: result.security });
|
|
170
|
+
}
|
|
137
171
|
case "skillmd_install": {
|
|
138
172
|
const [owner, slugName] = String(args.slug).split("/");
|
|
139
173
|
const skill = await api(`/api/skills/${owner}/${slugName}`);
|
|
@@ -153,7 +187,7 @@ async function handleCall(name, args) {
|
|
|
153
187
|
}
|
|
154
188
|
}
|
|
155
189
|
|
|
156
|
-
const server = new Server({ name: "skillmd", version: "
|
|
190
|
+
const server = new Server({ name: "skillmd", version: "1.0.0" }, { capabilities: { tools: {} } });
|
|
157
191
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
158
192
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
159
193
|
try {
|
package/bin/skillmd.mjs
ADDED