Skip to content
Back to skills

055 Architecture B5fa8504

ASecurity

This 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
ai-agentstypescriptpythonrustgoshellbashnodeexpresstestingdebugging

Works with

  • claude code
  • claude desktop
  • api
  • mcp

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 055-architecture_b5fa8504 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 055 Architecture B5fa8504?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 055 Architecture B5fa8504
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-055-architecture-b5fa8504/badge)](https://www.skillsdirectory.com/skills/tools-only-055-architecture-b5fa8504)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# 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

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…