progressive-skills-mcp 0.2.0__py3-none-any.whl
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.
- progressive_skills_mcp/__init__.py +29 -0
- progressive_skills_mcp/__main__.py +13 -0
- progressive_skills_mcp/_server.py +1238 -0
- progressive_skills_mcp/_version.py +5 -0
- progressive_skills_mcp/progressive_disclosure.py +164 -0
- progressive_skills_mcp/skills/context7-docs-lookup.zip +0 -0
- progressive_skills_mcp-0.2.0.dist-info/METADATA +228 -0
- progressive_skills_mcp-0.2.0.dist-info/RECORD +10 -0
- progressive_skills_mcp-0.2.0.dist-info/WHEEL +4 -0
- progressive_skills_mcp-0.2.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Progressive disclosure implementation for skillz.
|
|
2
|
+
|
|
3
|
+
Add this code to _server.py to enable progressive disclosure.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Optional, Any
|
|
7
|
+
from fastmcp import Context
|
|
8
|
+
from fastmcp.exceptions import ToolError
|
|
9
|
+
import base64
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MetadataGenerator:
|
|
13
|
+
"""Generate system prompt metadata for all skills."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, registry):
|
|
16
|
+
self.registry = registry
|
|
17
|
+
|
|
18
|
+
def generate_system_prompt_metadata(self) -> str:
|
|
19
|
+
"""Generate markdown-formatted skill metadata for system prompts."""
|
|
20
|
+
skills = sorted(self.registry.skills, key=lambda s: s.slug)
|
|
21
|
+
|
|
22
|
+
if not skills:
|
|
23
|
+
return "No skills available."
|
|
24
|
+
|
|
25
|
+
lines = [
|
|
26
|
+
"## Available Skills",
|
|
27
|
+
"",
|
|
28
|
+
"You have access to specialized skills. To use a skill, call the `load_skill` tool with the skill name.",
|
|
29
|
+
"",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
for skill in skills:
|
|
33
|
+
lines.append(f"- **{skill.slug}**: {skill.metadata.description}")
|
|
34
|
+
|
|
35
|
+
return "\n".join(lines)
|
|
36
|
+
|
|
37
|
+
def generate_json_metadata(self) -> str:
|
|
38
|
+
"""Generate JSON metadata for programmatic use."""
|
|
39
|
+
import json
|
|
40
|
+
metadata = [
|
|
41
|
+
{
|
|
42
|
+
"name": skill.slug,
|
|
43
|
+
"description": skill.metadata.description,
|
|
44
|
+
"allowed_tools": list(skill.metadata.allowed_tools),
|
|
45
|
+
}
|
|
46
|
+
for skill in self.registry.skills
|
|
47
|
+
]
|
|
48
|
+
return json.dumps(metadata, indent=2)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def register_progressive_disclosure_tools(mcp, registry) -> None:
|
|
52
|
+
"""Register 3 universal tools for progressive disclosure."""
|
|
53
|
+
|
|
54
|
+
@mcp.tool(
|
|
55
|
+
name="load_skill",
|
|
56
|
+
description=(
|
|
57
|
+
"Load the complete instructions for a skill. "
|
|
58
|
+
"Use this when you've decided a skill is relevant based on "
|
|
59
|
+
"the skill metadata in your system prompt. "
|
|
60
|
+
"Returns the full SKILL.md content without frontmatter."
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
async def load_skill_tool(
|
|
64
|
+
skill_name: str,
|
|
65
|
+
ctx: Optional[Context] = None,
|
|
66
|
+
) -> str:
|
|
67
|
+
"""Load full skill instructions (Level 2 progressive disclosure)."""
|
|
68
|
+
try:
|
|
69
|
+
skill = registry.get(skill_name)
|
|
70
|
+
LOGGER.info("Loaded skill: %s", skill_name)
|
|
71
|
+
return skill.read_body()
|
|
72
|
+
except Exception as exc:
|
|
73
|
+
raise ToolError(
|
|
74
|
+
f"Skill '{skill_name}' not found. "
|
|
75
|
+
f"Available skills can be seen in your system prompt."
|
|
76
|
+
) from exc
|
|
77
|
+
|
|
78
|
+
@mcp.tool(
|
|
79
|
+
name="read_skill_file",
|
|
80
|
+
description=(
|
|
81
|
+
"Read a specific file from a skill's directory. "
|
|
82
|
+
"Use this when skill instructions reference a file "
|
|
83
|
+
"(e.g., 'See references/api_reference.md'). "
|
|
84
|
+
"Provide the skill name and relative file path."
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
async def read_skill_file_tool(
|
|
88
|
+
skill_name: str,
|
|
89
|
+
file_path: str,
|
|
90
|
+
ctx: Optional[Context] = None,
|
|
91
|
+
) -> str:
|
|
92
|
+
"""Read a specific file from skill directory (Level 3 progressive disclosure)."""
|
|
93
|
+
try:
|
|
94
|
+
skill = registry.get(skill_name)
|
|
95
|
+
|
|
96
|
+
# Validate path doesn't traverse upward
|
|
97
|
+
if ".." in file_path or file_path.startswith("/"):
|
|
98
|
+
raise ToolError("Invalid path: path traversal not allowed")
|
|
99
|
+
|
|
100
|
+
if not skill.exists(file_path):
|
|
101
|
+
raise ToolError(
|
|
102
|
+
f"File '{file_path}' not found in skill '{skill_name}'"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Read content
|
|
106
|
+
data = skill.open_bytes(file_path)
|
|
107
|
+
|
|
108
|
+
# Try to decode as UTF-8, fallback to base64 for binary
|
|
109
|
+
try:
|
|
110
|
+
content = data.decode("utf-8")
|
|
111
|
+
except UnicodeDecodeError:
|
|
112
|
+
content = f"[Binary file - base64 encoded]\n{base64.b64encode(data).decode('ascii')}"
|
|
113
|
+
|
|
114
|
+
LOGGER.info("Read file: %s/%s", skill_name, file_path)
|
|
115
|
+
return content
|
|
116
|
+
|
|
117
|
+
except Exception as exc:
|
|
118
|
+
raise ToolError(str(exc)) from exc
|
|
119
|
+
|
|
120
|
+
@mcp.tool(
|
|
121
|
+
name="list_skill_files",
|
|
122
|
+
description=(
|
|
123
|
+
"List files available in a skill's directory. "
|
|
124
|
+
"Use this to discover what reference files, scripts, or resources "
|
|
125
|
+
"a skill provides. Optionally specify a subdirectory like "
|
|
126
|
+
"'references' or 'scripts'."
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
async def list_skill_files_tool(
|
|
130
|
+
skill_name: str,
|
|
131
|
+
subdirectory: Optional[str] = None,
|
|
132
|
+
ctx: Optional[Context] = None,
|
|
133
|
+
) -> str:
|
|
134
|
+
"""List available files in a skill directory."""
|
|
135
|
+
try:
|
|
136
|
+
skill = registry.get(skill_name)
|
|
137
|
+
|
|
138
|
+
# Get all resource paths
|
|
139
|
+
all_paths = list(skill.iter_resource_paths())
|
|
140
|
+
|
|
141
|
+
# Filter by subdirectory if specified
|
|
142
|
+
if subdirectory:
|
|
143
|
+
# Normalize subdirectory path
|
|
144
|
+
subdir_prefix = subdirectory.rstrip("/") + "/"
|
|
145
|
+
filtered_paths = [
|
|
146
|
+
path for path in all_paths
|
|
147
|
+
if path.startswith(subdir_prefix)
|
|
148
|
+
]
|
|
149
|
+
else:
|
|
150
|
+
filtered_paths = all_paths
|
|
151
|
+
|
|
152
|
+
if not filtered_paths:
|
|
153
|
+
subdir_msg = f" in subdirectory '{subdirectory}'" if subdirectory else ""
|
|
154
|
+
return f"No files found in skill '{skill_name}'{subdir_msg}"
|
|
155
|
+
|
|
156
|
+
# Format output
|
|
157
|
+
subdir_msg = f" in '{subdirectory}'" if subdirectory else ""
|
|
158
|
+
lines = [f"Files in skill '{skill_name}'{subdir_msg}:"]
|
|
159
|
+
lines.extend(f" - {path}" for path in sorted(filtered_paths))
|
|
160
|
+
|
|
161
|
+
return "\n".join(lines)
|
|
162
|
+
|
|
163
|
+
except Exception as exc:
|
|
164
|
+
raise ToolError(str(exc)) from exc
|
|
Binary file
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: progressive-skills-mcp
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: MCP server that exposes Claude-style skills to any MCP client.
|
|
5
|
+
Keywords: mcp,skills,fastmcp,claude
|
|
6
|
+
Author: Eleanor Berger
|
|
7
|
+
Author-email: Eleanor Berger <eleanor@intellectronica.net>
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2025 Eleanor Berger <eleanor@intellectronica.net>
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
Classifier: Development Status :: 3 - Alpha
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Programming Language :: Python
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
35
|
+
Requires-Dist: fastmcp>=2.2.5
|
|
36
|
+
Requires-Dist: pyyaml>=6.0
|
|
37
|
+
Requires-Python: >=3.12
|
|
38
|
+
Project-URL: Homepage, https://github.com/Flowtrica/skills-mcp
|
|
39
|
+
Project-URL: Issues, https://github.com/Flowtrica/skills-mcp/issues
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# Skills MCP
|
|
43
|
+
|
|
44
|
+
MCP server for SKILL.md files with **progressive disclosure** - achieving **13x token efficiency** over traditional approaches.
|
|
45
|
+
|
|
46
|
+
Based on [intellectronica/skillz](https://github.com/intellectronica/skillz) with progressive disclosure modifications inspired by Claude.ai's approach.
|
|
47
|
+
|
|
48
|
+
## What's Different?
|
|
49
|
+
|
|
50
|
+
**Original skillz:**
|
|
51
|
+
- Creates 1 tool per skill
|
|
52
|
+
- 20 skills = 20 tools × ~100 tokens = **2000 tokens/request**
|
|
53
|
+
|
|
54
|
+
**Skills MCP (this fork):**
|
|
55
|
+
- Creates 3 universal tools (`load_skill`, `read_skill_file`, `list_skill_files`)
|
|
56
|
+
- 20 skills = 3 tools × ~50 tokens = **150 tokens/request**
|
|
57
|
+
- **13x improvement!** 🎉
|
|
58
|
+
|
|
59
|
+
## Features
|
|
60
|
+
|
|
61
|
+
✅ Progressive disclosure (3-level token efficiency)
|
|
62
|
+
✅ Metadata generation for system prompts
|
|
63
|
+
✅ Compatible with all SKILL.md format files
|
|
64
|
+
✅ Supports .zip and .skill archives
|
|
65
|
+
✅ Docker image available
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
### Using Docker
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
docker run -i --rm \
|
|
73
|
+
-v /path/to/skills:/skills \
|
|
74
|
+
flowtrica/skills-mcp:latest \
|
|
75
|
+
/skills
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Using uvx
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
uvx skills-mcp@latest /path/to/skills
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### With MCPHub
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"skills": {
|
|
90
|
+
"command": "docker",
|
|
91
|
+
"args": [
|
|
92
|
+
"run", "-i", "--rm",
|
|
93
|
+
"--entrypoint", "sh",
|
|
94
|
+
"flowtrica/skills-mcp:latest",
|
|
95
|
+
"-c",
|
|
96
|
+
"git clone https://github.com/YOUR_USERNAME/your-skills.git /tmp/skills && skills-mcp /tmp/skills"
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Progressive Disclosure
|
|
104
|
+
|
|
105
|
+
### Level 1: System Prompt (Once per conversation)
|
|
106
|
+
```markdown
|
|
107
|
+
## Available Skills
|
|
108
|
+
- **weather**: Get weather forecasts
|
|
109
|
+
- **pptx**: Create presentations
|
|
110
|
+
```
|
|
111
|
+
**Cost:** ~200 tokens, sent ONCE
|
|
112
|
+
|
|
113
|
+
### Level 2: On-Demand Instructions
|
|
114
|
+
```python
|
|
115
|
+
load_skill("pptx") # Returns full SKILL.md
|
|
116
|
+
```
|
|
117
|
+
**Cost:** 0 tokens until loaded
|
|
118
|
+
|
|
119
|
+
### Level 3: Referenced Resources
|
|
120
|
+
```python
|
|
121
|
+
read_skill_file("pptx", "references/api.md")
|
|
122
|
+
```
|
|
123
|
+
**Cost:** 0 tokens until accessed
|
|
124
|
+
|
|
125
|
+
## Generate Metadata
|
|
126
|
+
|
|
127
|
+
For Onyx or other MCP clients that support system prompts:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
skills-mcp --generate-metadata /path/to/skills
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Output:
|
|
134
|
+
```markdown
|
|
135
|
+
## Available Skills
|
|
136
|
+
|
|
137
|
+
You have access to specialized skills...
|
|
138
|
+
|
|
139
|
+
- **test-skill**: A simple test skill
|
|
140
|
+
- **weather**: Get weather forecasts
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Installation
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pip install skills-mcp
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Or use with `uv`:
|
|
150
|
+
```bash
|
|
151
|
+
uv tool install skills-mcp
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Usage
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Run MCP server
|
|
158
|
+
skills-mcp /path/to/skills
|
|
159
|
+
|
|
160
|
+
# Generate metadata
|
|
161
|
+
skills-mcp --generate-metadata /path/to/skills
|
|
162
|
+
|
|
163
|
+
# Generate JSON metadata
|
|
164
|
+
skills-mcp --generate-metadata --format json /path/to/skills
|
|
165
|
+
|
|
166
|
+
# List discovered skills
|
|
167
|
+
skills-mcp --list-skills /path/to/skills
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Skill Format
|
|
171
|
+
|
|
172
|
+
Skills can be:
|
|
173
|
+
- **Directories** with SKILL.md file
|
|
174
|
+
- **Zip archives** containing SKILL.md
|
|
175
|
+
- **.skill archives**
|
|
176
|
+
|
|
177
|
+
Example structure:
|
|
178
|
+
```
|
|
179
|
+
skills/
|
|
180
|
+
├── weather/
|
|
181
|
+
│ ├── SKILL.md
|
|
182
|
+
│ └── references/
|
|
183
|
+
│ └── api.md
|
|
184
|
+
└── pptx.zip
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
SKILL.md format:
|
|
188
|
+
```markdown
|
|
189
|
+
---
|
|
190
|
+
name: skill-name
|
|
191
|
+
description: Brief description
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
# Full Instructions
|
|
195
|
+
|
|
196
|
+
Detailed skill instructions here...
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Building Docker Image
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
docker build -t flowtrica/skills-mcp:latest .
|
|
203
|
+
docker push flowtrica/skills-mcp:latest
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Token Efficiency Comparison
|
|
207
|
+
|
|
208
|
+
| Approach | Tools/Request | Tokens/Request | 20 Skills |
|
|
209
|
+
|----------|--------------|----------------|-----------|
|
|
210
|
+
| Original | 20 tools | ~100 each | 2000 tokens |
|
|
211
|
+
| **Skills MCP** | **3 tools** | **~50 each** | **150 tokens** |
|
|
212
|
+
| **Improvement** | | | **13x better!** 🎉 |
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT (same as original skillz)
|
|
217
|
+
|
|
218
|
+
## Credits
|
|
219
|
+
|
|
220
|
+
- Based on [skillz](https://github.com/intellectronica/skillz) by Eleanor Berger
|
|
221
|
+
- Progressive disclosure modifications by Flowtrica
|
|
222
|
+
- Inspired by Claude.ai's skills system
|
|
223
|
+
|
|
224
|
+
## Links
|
|
225
|
+
|
|
226
|
+
- Original skillz: https://github.com/intellectronica/skillz
|
|
227
|
+
- Skills repo: https://github.com/Flowtrica/agent-skills
|
|
228
|
+
- Docker Hub: https://hub.docker.com/r/flowtrica/skills-mcp
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
progressive_skills_mcp/__init__.py,sha256=WFbujAfiFsm3g567Ea91ZXjhLesI78EVhc3Ao3oy1PM,522
|
|
2
|
+
progressive_skills_mcp/__main__.py,sha256=AFR1CXSuPL4Td1RPNWZzuUXntdaHqgJOp9DL5iPk8QM,215
|
|
3
|
+
progressive_skills_mcp/_server.py,sha256=jWuqHTTad8ECpawX-qd0PdNCodb0t2hcOPJo5qUnxVI,41991
|
|
4
|
+
progressive_skills_mcp/_version.py,sha256=q4q6xy8hoU3hhiPLlZPK9YPK0gwpSwNYBznw8EVjY6k,106
|
|
5
|
+
progressive_skills_mcp/progressive_disclosure.py,sha256=rSOGm0XodEXMoNlRTnkyPeDFiY3yug1i_pv3aUvHqPE,5855
|
|
6
|
+
progressive_skills_mcp/skills/context7-docs-lookup.zip,sha256=9jvk8QROayFq249BxCUCi2dhvaUdH2eOdEZunHjNSkg,2430
|
|
7
|
+
progressive_skills_mcp-0.2.0.dist-info/WHEEL,sha256=5DEXXimM34_d4Gx1AuF9ysMr1_maoEtGKjaILM3s4w4,80
|
|
8
|
+
progressive_skills_mcp-0.2.0.dist-info/entry_points.txt,sha256=v3yDRF-b-QfYLa8bfmOvTr40hHKTy9F0166K-DfoyGo,80
|
|
9
|
+
progressive_skills_mcp-0.2.0.dist-info/METADATA,sha256=yirmfD0v-RsW7xn-bIWfFB4ABcZt94TMX88AxxT26es,5964
|
|
10
|
+
progressive_skills_mcp-0.2.0.dist-info/RECORD,,
|