Back to skills
SKILL.md
055 Architecture B5fa8504
ASecurityThis document describes the architecture and design decisions behind the skills-lister MCP server.
- 9 stars
- 0 votes
- 0 copies
- 0 views
- Added October 11, 2026
Works with
Security analysis
92/100- Installs packages at runtime which could introduce malicious dependencies
npx -y skills add tools-only/X-Skills --skill 055-architecture_b5fa8504 --agent claude-codeAre you the author of 055 Architecture B5fa8504?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tools-only-055-architecture-b5fa8504)# Skills Lister MCP Server - Architecture
## Overview
This document describes the architecture and design decisions behind the skills-lister MCP server.
## Problem Statement
The original `/skills` slash command in Claude Code had performance issues:
1. **High token usage**: 5,000-10,000 tokens per invocation
2. **Slow execution**: 3-5 seconds to read and parse multiple SKILL.md files
3. **Expensive**: Each call cost ~$0.015 in API usage
4. **Redundant processing**: LLM parsed YAML frontmatter unnecessarily
## Solution Architecture
### High-Level Design
```
┌─────────────────┐
│ User Request │
│ "List skills" │
└────────┬────────┘
│
▼
┌─────────────────────────┐
│ Claude Code/AI │
│ Recognizes intent, │
│ calls MCP tool │
└────────┬────────────────┘
│
▼
┌─────────────────────────┐
│ MCP Protocol Layer │
│ JSON-RPC over stdio │
└────────┬────────────────┘
│
▼
┌─────────────────────────┐
│ skills-lister Server │
│ (Python 3.10+) │
└────────┬────────────────┘
│
▼
┌─────────────────────────┐
│ subprocess.run() │
│ Execute shell script │
└────────┬────────────────┘
│
▼
┌─────────────────────────┐
│ ~/bin/list-skills.sh │
│ Reads SKILL.md files │
│ Formats output │
└────────┬────────────────┘
│
▼
┌─────────────────────────┐
│ Return to Claude │
│ 0 tokens used │
└─────────────────────────┘
```
### Component Breakdown
#### 1. MCP Server (server.py)
**Language**: Python 3.10+
**Dependencies**:
- `mcp` - Official MCP SDK
- `subprocess` - Execute shell commands
- `json` - Parse/format JSON data
- `asyncio` - Async/await support
**Key Functions**:
```python
@app.list_tools()
async def list_tools() -> list[Tool]:
"""Declares available tools to Claude"""
# Returns metadata about list_skills tool
```
```python
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
"""Executes tool calls from Claude"""
# Runs ~/bin/list-skills.sh
# Returns formatted output
```
**Communication**:
- **Input**: stdin (JSON-RPC messages from Claude)
- **Output**: stdout (JSON-RPC responses to Claude)
- **Protocol**: MCP (Model Context Protocol)
#### 2. Shell Script (~/bin/list-skills.sh)
**Language**: Bash
**Responsibilities**:
1. Scan `~/.claude/skills/` and `.claude/skills/`
2. Read YAML frontmatter from SKILL.md files
3. Extract `name:` and `description:` fields
4. Format output based on flags:
- `--names-only`: Just skill names
- `--json`: Structured JSON with metadata
- (no flag): Human-readable with descriptions
**Why reuse existing script?**
- Already tested and working
- No code duplication
- Easy to maintain
- Can be used independently
#### 3. MCP Protocol Layer
**Standard**: Model Context Protocol by Anthropic
**Transport**: stdio (stdin/stdout)
**Message Format**: JSON-RPC 2.0
**Tool Declaration**:
```json
{
"name": "list_skills",
"description": "List all available Claude skills...",
"inputSchema": {
"type": "object",
"properties": {
"format": {
"type": "string",
"enum": ["names-only", "json", "full"]
}
}
}
}
```
**Tool Call**:
```json
{
"method": "tools/call",
"params": {
"name": "list_skills",
"arguments": {
"format": "names-only"
}
}
}
```
**Response**:
```json
{
"content": [
{
"type": "text",
"text": "skill1\nskill2\nskill3..."
}
]
}
```
## Design Decisions
### 1. Why Python?
**Pros**:
- MCP SDK officially supports Python
- Easy subprocess management
- Simple async/await syntax
- Cross-platform compatibility
**Alternatives considered**:
- TypeScript: Requires Node.js runtime
- Go: Requires compilation step
- Rust: Steep learning curve
**Decision**: Python offers best balance of simplicity and MCP support.
### 2. Why Shell Script Execution?
**Pros**:
- Reuse existing, tested code
- No reimplementation needed
- Script can be used standalone
- Easy to debug and modify
**Alternatives considered**:
- Parse SKILL.md in Python: Code duplication
- Read JSON cache: Requires cache management
- Database: Overkill for simple listing
**Decision**: Shell script is simplest and most maintainable.
### 3. Why Three Output Formats?
**names-only** (267 chars):
- Minimal token usage
- Fast response
- Best for simple listing
**json** (5,117 chars):
- Machine-readable
- Includes metadata
- Good for programmatic use
**full** (5,063 chars):
- Human-readable
- Includes descriptions
- Best for browsing
**Decision**: Multiple formats provide flexibility without adding complexity.
### 4. Why Async/Await?
MCP protocol is asynchronous by design:
- Non-blocking I/O
- Handle multiple concurrent requests
- Standard for modern Python servers
**Decision**: Follow MCP SDK patterns for consistency.
## Data Flow
### Request Flow
1. **User types**: "List all skills"
2. **Claude identifies intent**: Needs skill listing
3. **Claude calls**: `list_skills` tool via MCP
4. **MCP server receives**: JSON-RPC call on stdin
5. **Server executes**: `~/bin/list-skills.sh --names-only`
6. **Script runs**: Reads SKILL.md files, extracts names
7. **Script outputs**: Newline-separated skill names
8. **Server captures**: stdout from subprocess
9. **Server responds**: JSON-RPC response on stdout
10. **Claude receives**: Text content with skill names
11. **Claude presents**: Formatted list to user
**Total time**: <1 second
**Tokens used**: 0
### Error Flow
1. **Error occurs**: Script not found, permission denied, etc.
2. **Server catches**: Exception in subprocess.run()
3. **Server responds**: Error message via MCP
4. **Claude receives**: Error text
5. **Claude presents**: User-friendly error message
**Examples**:
- "Script not found at ~/bin/list-skills.sh"
- "Script execution timed out after 10 seconds"
- "Error executing script: [stderr output]"
## Performance Characteristics
### Latency
| Component | Time | Notes |
|-----------|------|-------|
| MCP protocol overhead | ~50ms | JSON-RPC parsing |
| Python startup | ~100ms | Import modules |
| Shell script execution | ~500ms | Read files, parse YAML |
| **Total** | **~650ms** | **Sub-second response** |
### Token Usage
| Method | Tokens | Cost per call |
|--------|--------|---------------|
| Direct file reading | 5,000-10,000 | ~$0.015 |
| **MCP server** | **0** | **$0** |
### Scalability
- **File I/O bound**: Performance scales with number of skills
- **Current**: 16 skills, ~500ms
- **Projected**: 100 skills, ~2-3 seconds
- **Optimization**: Could add caching if needed
## Security Considerations
### Input Validation
```python
# Validate format parameter
output_format = arguments.get("format", "names-only")
# Only allow enum values from schema
```
### Command Injection
```python
# Safe: No user input in command
cmd = [script_path, "--names-only"]
# NOT using shell=True
subprocess.run(cmd, shell=False)
```
### Path Traversal
```python
# Fixed path, no user input
script_path = os.path.expanduser("~/bin/list-skills.sh")
# Validated before execution
if not os.path.exists(script_path):
return error
```
### Timeout Protection
```python
# 10-second timeout prevents hanging
result = subprocess.run(cmd, timeout=10)
```
## Testing Strategy
### Unit Tests (Future)
```python
def test_list_skills_names_only():
result = call_tool("list_skills", {"format": "names-only"})
assert isinstance(result, list)
assert all(isinstance(line, str) for line in result)
def test_list_skills_json():
result = call_tool("list_skills", {"format": "json"})
data = json.loads(result[0].text)
assert "total" in data
assert "skills" in data
```
### Integration Tests
```bash
# Test shell script directly
./scripts/list-skills.sh --names-only
# Test MCP server
echo '{"method":"tools/list"}' | python3 server.py
```
### Manual Testing
1. Configure in Claude Desktop
2. Ask: "List all skills"
3. Verify: Instant response with skill names
4. Check: Logs show MCP tool call
## Deployment
### Installation Methods
1. **Direct execution**: `python3 server.py`
2. **pip install**: `pip install -e .` (editable mode)
3. **Symlink**: Link to system Python packages
### Configuration
**Location**: Claude config file (JSON)
**Required**:
- `command`: Python interpreter path
- `args`: Absolute path to server.py
**Optional**:
- `env`: Environment variables
- `cwd`: Working directory
### Monitoring
**Logs**:
- Claude Desktop: `~/Library/Logs/Claude/` (macOS)
- Stderr: Captured by Claude, shown in logs
**Debugging**:
```python
import sys
print(f"Debug: {message}", file=sys.stderr)
```
## Future Enhancements
### Potential Features
1. **Caching**
- Cache SKILL.md parsing results
- Invalidate on file modification
- 10-100x speedup for repeated calls
2. **Search/Filter**
- Search skill descriptions
- Filter by category/tags
- Regular expression support
3. **Skill Details**
- Get full SKILL.md content
- Show dependencies
- Display examples
4. **Validation**
- Check SKILL.md syntax
- Verify YAML frontmatter
- Report issues
5. **Installation**
- Install skill from URL
- Update existing skills
- Manage dependencies
### Additional MCP Servers
Pattern can be extended to:
- Code search across repositories
- Git operations (status, diff, log)
- File system operations
- Database queries
- API integrations
## Lessons Learned
### What Worked Well
1. **Reusing existing script**: No reimplementation needed
2. **Simple design**: Easy to understand and maintain
3. **MCP protocol**: Clean separation of concerns
4. **Zero tokens**: Significant cost savings
### What Could Be Better
1. **Error messages**: Could be more user-friendly
2. **Configuration**: Could auto-detect script location
3. **Documentation**: Could include video tutorials
4. **Testing**: Needs automated test suite
### Key Takeaways
1. **MCP is powerful**: Enables zero-token operations
2. **Simple is better**: Don't over-engineer
3. **Reuse works**: Leverage existing tools
4. **Documentation matters**: Good docs = easy adoption
## References
- [MCP Specification](https://spec.modelcontextprotocol.io/)
- [MCP Python SDK](https://github.com/anthropics/mcp-python-sdk)
- [Claude Code Docs](https://docs.claude.com/claude-code)
- [JSON-RPC 2.0](https://www.jsonrpc.org/specification)
## Conclusion
The skills-lister MCP server demonstrates how MCP can eliminate token usage for data retrieval operations. By delegating file system operations to a dedicated server, we achieve:
- **100% token reduction**
- **5x faster response**
- **Zero cost per call**
- **Better user experience**
This architecture can serve as a template for other MCP servers, enabling efficient zero-token operations for a wide range of tasks.
Attribution
Comments
Loading comments…