findskills-mcp 0.1.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 +88 -0
- package/api.js +36 -0
- package/bin.js +3 -0
- package/package.json +34 -0
- package/server.js +82 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# findskills-mcp
|
|
2
|
+
|
|
3
|
+
MCP Server for [FindSkills](https://findskills.org) — search and discover 15,000+ AI Agent Skills via the [Model Context Protocol](https://modelcontextprotocol.io).
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Claude Desktop
|
|
8
|
+
|
|
9
|
+
Add to `claude_desktop_config.json`:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"mcpServers": {
|
|
14
|
+
"findskills": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": ["-y", "findskills-mcp"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Claude Code
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
claude mcp add findskills -- npx -y findskills-mcp
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Other MCP Clients
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx findskills-mcp
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The server communicates over stdio using the MCP protocol.
|
|
35
|
+
|
|
36
|
+
## Tools
|
|
37
|
+
|
|
38
|
+
| Tool | Description |
|
|
39
|
+
|------|-------------|
|
|
40
|
+
| `search_skills` | Search by keyword, ranked by relevance |
|
|
41
|
+
| `list_skills` | Browse/filter by category, source, safety, quality |
|
|
42
|
+
| `get_skill` | Full details for a specific skill |
|
|
43
|
+
| `get_stats` | Dataset overview (total count, distributions) |
|
|
44
|
+
| `list_tags` | All tags with usage counts |
|
|
45
|
+
|
|
46
|
+
### search_skills
|
|
47
|
+
|
|
48
|
+
| Parameter | Type | Required | Description |
|
|
49
|
+
|-----------|------|----------|-------------|
|
|
50
|
+
| `query` | string | yes | Search keyword |
|
|
51
|
+
| `limit` | number | no | Max results (default 20, max 100) |
|
|
52
|
+
|
|
53
|
+
### list_skills
|
|
54
|
+
|
|
55
|
+
| Parameter | Type | Required | Description |
|
|
56
|
+
|-----------|------|----------|-------------|
|
|
57
|
+
| `category` | enum | no | One of: search, coding, data, communication, media, automation, security, ai-ml, devops, finance, productivity, integration, other |
|
|
58
|
+
| `source` | enum | no | clawhub, github, manual |
|
|
59
|
+
| `auth_type` | enum | no | none, api_key, oauth2, bearer |
|
|
60
|
+
| `sort` | enum | no | updated, added, stars, quality, safety, name |
|
|
61
|
+
| `min_quality` | number | no | Minimum quality score (0-100) |
|
|
62
|
+
| `min_safety` | number | no | Minimum safety score (0-100) |
|
|
63
|
+
| `limit` | number | no | Results per page (default 20) |
|
|
64
|
+
| `offset` | number | no | Pagination offset |
|
|
65
|
+
|
|
66
|
+
### get_skill
|
|
67
|
+
|
|
68
|
+
| Parameter | Type | Required | Description |
|
|
69
|
+
|-----------|------|----------|-------------|
|
|
70
|
+
| `id` | string | yes | Skill ID |
|
|
71
|
+
|
|
72
|
+
### get_stats
|
|
73
|
+
|
|
74
|
+
No parameters.
|
|
75
|
+
|
|
76
|
+
### list_tags
|
|
77
|
+
|
|
78
|
+
| Parameter | Type | Required | Description |
|
|
79
|
+
|-----------|------|----------|-------------|
|
|
80
|
+
| `limit` | number | no | Max tags (default 50) |
|
|
81
|
+
|
|
82
|
+
## Requirements
|
|
83
|
+
|
|
84
|
+
- Node.js >= 20.0.0
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
package/api.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const BASE = 'https://findskills.org/api/v1';
|
|
2
|
+
|
|
3
|
+
async function request(path) {
|
|
4
|
+
const res = await fetch(`${BASE}${path}`, { redirect: 'follow' });
|
|
5
|
+
if (!res.ok) throw new Error(`FindSkills API error: ${res.status} ${res.statusText}`);
|
|
6
|
+
return res.json();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function searchSkills(query, limit = 20) {
|
|
10
|
+
return request(`/search?q=${encodeURIComponent(query)}&limit=${limit}`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function listSkills({ category, source, auth_type, sort, min_quality, min_safety, limit = 20, offset = 0 } = {}) {
|
|
14
|
+
const params = new URLSearchParams();
|
|
15
|
+
params.set('limit', String(limit));
|
|
16
|
+
params.set('offset', String(offset));
|
|
17
|
+
if (category) params.set('category', category);
|
|
18
|
+
if (source) params.set('source', source);
|
|
19
|
+
if (auth_type) params.set('auth_type', auth_type);
|
|
20
|
+
if (sort) params.set('sort', sort);
|
|
21
|
+
if (min_quality != null) params.set('min_quality', String(min_quality));
|
|
22
|
+
if (min_safety != null) params.set('min_safety', String(min_safety));
|
|
23
|
+
return request(`/skills?${params}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function getSkill(id) {
|
|
27
|
+
return request(`/skills/${encodeURIComponent(id)}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function getStats() {
|
|
31
|
+
return request('/stats');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function listTags(limit = 50) {
|
|
35
|
+
return request(`/tags?limit=${limit}`);
|
|
36
|
+
}
|
package/bin.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "findskills-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP Server for FindSkills — search and discover 15,000+ AI Agent Skills",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"findskills-mcp": "bin.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin.js",
|
|
11
|
+
"server.js",
|
|
12
|
+
"api.js"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20.0.0"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"ai",
|
|
20
|
+
"agent",
|
|
21
|
+
"skills",
|
|
22
|
+
"findskills",
|
|
23
|
+
"model-context-protocol"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/shintemy/findskills.git"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.27.0",
|
|
32
|
+
"zod": "^3.24.0"
|
|
33
|
+
}
|
|
34
|
+
}
|
package/server.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { searchSkills, listSkills, getSkill, getStats, listTags } from './api.js';
|
|
5
|
+
|
|
6
|
+
function text(content) {
|
|
7
|
+
return { content: [{ type: 'text', text: typeof content === 'string' ? content : JSON.stringify(content, null, 2) }] };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function createServer() {
|
|
11
|
+
const server = new McpServer({ name: 'findskills', version: '0.1.0' });
|
|
12
|
+
|
|
13
|
+
server.registerTool('search_skills', {
|
|
14
|
+
title: 'Search Skills',
|
|
15
|
+
description: 'Search FindSkills directory by keyword. Returns skills ranked by relevance.',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
query: z.string().describe('Search keyword (e.g. "web scraping", "slack", "database")'),
|
|
18
|
+
limit: z.number().int().min(1).max(100).default(20).describe('Max results (default 20)'),
|
|
19
|
+
},
|
|
20
|
+
}, async ({ query, limit }) => {
|
|
21
|
+
const data = await searchSkills(query, limit);
|
|
22
|
+
return text(data);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
server.registerTool('list_skills', {
|
|
26
|
+
title: 'List Skills',
|
|
27
|
+
description: 'Browse and filter skills by category, source, safety tier, and more. Supports pagination.',
|
|
28
|
+
inputSchema: {
|
|
29
|
+
category: z.enum(['search', 'coding', 'data', 'communication', 'media', 'automation', 'security', 'ai-ml', 'devops', 'finance', 'productivity', 'integration', 'other']).optional().describe('Filter by category'),
|
|
30
|
+
source: z.enum(['clawhub', 'github', 'manual']).optional().describe('Filter by data source'),
|
|
31
|
+
auth_type: z.enum(['none', 'api_key', 'oauth2', 'bearer']).optional().describe('Filter by auth requirement'),
|
|
32
|
+
sort: z.enum(['updated', 'added', 'stars', 'quality', 'safety', 'name']).default('updated').describe('Sort order'),
|
|
33
|
+
min_quality: z.number().int().min(0).max(100).optional().describe('Minimum quality score (0-100)'),
|
|
34
|
+
min_safety: z.number().int().min(0).max(100).optional().describe('Minimum safety score (0-100)'),
|
|
35
|
+
limit: z.number().int().min(1).max(100).default(20).describe('Results per page'),
|
|
36
|
+
offset: z.number().int().min(0).default(0).describe('Pagination offset'),
|
|
37
|
+
},
|
|
38
|
+
}, async (params) => {
|
|
39
|
+
const data = await listSkills(params);
|
|
40
|
+
return text(data);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
server.registerTool('get_skill', {
|
|
44
|
+
title: 'Get Skill Details',
|
|
45
|
+
description: 'Get full details for a specific skill including auth requirements, safety signals, and quality signals.',
|
|
46
|
+
inputSchema: {
|
|
47
|
+
id: z.string().describe('Skill ID (e.g. "clawhub-web-search")'),
|
|
48
|
+
},
|
|
49
|
+
}, async ({ id }) => {
|
|
50
|
+
const data = await getSkill(id);
|
|
51
|
+
return text(data);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
server.registerTool('get_stats', {
|
|
55
|
+
title: 'Get Dataset Stats',
|
|
56
|
+
description: 'Get FindSkills dataset overview: total skill count, category/source/auth breakdowns, quality and safety distributions. Call this first to understand the dataset.',
|
|
57
|
+
inputSchema: {},
|
|
58
|
+
}, async () => {
|
|
59
|
+
const data = await getStats();
|
|
60
|
+
return text(data);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
server.registerTool('list_tags', {
|
|
64
|
+
title: 'List Tags',
|
|
65
|
+
description: 'List all skill tags with usage counts, sorted by popularity.',
|
|
66
|
+
inputSchema: {
|
|
67
|
+
limit: z.number().int().min(1).max(500).default(50).describe('Max tags to return'),
|
|
68
|
+
},
|
|
69
|
+
}, async ({ limit }) => {
|
|
70
|
+
const data = await listTags(limit);
|
|
71
|
+
return text(data);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return server;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export async function startServer() {
|
|
78
|
+
const server = createServer();
|
|
79
|
+
const transport = new StdioServerTransport();
|
|
80
|
+
await server.connect(transport);
|
|
81
|
+
console.error('FindSkills MCP Server running on stdio');
|
|
82
|
+
}
|