Initial commit
This commit is contained in:
13
skills/claude-code/mcp-server-creator/CHANGELOG.md
Normal file
13
skills/claude-code/mcp-server-creator/CHANGELOG.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 0.2.0
|
||||
|
||||
- Refactored to Anthropic progressive disclosure pattern
|
||||
- Updated description with "Use PROACTIVELY when..." format
|
||||
|
||||
## 0.1.0
|
||||
|
||||
- Initial skill release
|
||||
- TypeScript and Python SDK support
|
||||
- Claude Desktop integration
|
||||
- MCP Inspector testing workflow
|
||||
199
skills/claude-code/mcp-server-creator/README.md
Normal file
199
skills/claude-code/mcp-server-creator/README.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# MCP Server Creator Skill
|
||||
|
||||
Automated tool for creating production-ready Model Context Protocol (MCP) servers with TypeScript or Python SDKs.
|
||||
|
||||
## What This Skill Does
|
||||
|
||||
The MCP Server Creator skill streamlines the entire process of building MCP servers by:
|
||||
|
||||
1. **Gathering requirements** through interactive questions about your server's purpose
|
||||
2. **Selecting the right SDK** (TypeScript, Python, Java, Kotlin, or C#)
|
||||
3. **Generating project structure** with proper dependencies and build configuration
|
||||
4. **Creating server implementation** with tools, resources, and prompts
|
||||
5. **Configuring Claude Desktop** integration with proper paths and environment
|
||||
6. **Providing testing guidance** with MCP Inspector and validation steps
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when you want to:
|
||||
|
||||
- Connect Claude to your data sources (databases, APIs, files)
|
||||
- Expose custom tools for AI to call
|
||||
- Build workflow automation servers
|
||||
- Create enterprise integrations
|
||||
- Learn MCP development patterns
|
||||
|
||||
## Trigger Phrases
|
||||
|
||||
- "create an MCP server for [purpose]"
|
||||
- "build a Model Context Protocol server"
|
||||
- "set up MCP integration with [data source]"
|
||||
- "help me create a server for Claude Desktop"
|
||||
- "scaffold an MCP server"
|
||||
|
||||
## What Gets Generated
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
mcp-server-name/
|
||||
├── src/
|
||||
│ └── index.ts (or main.py)
|
||||
├── build/ (TypeScript only)
|
||||
├── package.json / pyproject.toml
|
||||
├── tsconfig.json (TypeScript only)
|
||||
├── .env.example
|
||||
├── .gitignore
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### Key Features
|
||||
|
||||
- ✅ Full TypeScript or Python server implementation
|
||||
- ✅ Proper SDK integration with error handling
|
||||
- ✅ Tool definitions with Zod schemas or type hints
|
||||
- ✅ Resource and prompt handlers (if needed)
|
||||
- ✅ Claude Desktop configuration
|
||||
- ✅ Environment variable management
|
||||
- ✅ Security best practices (.gitignore, input validation)
|
||||
- ✅ Comprehensive documentation
|
||||
- ✅ Testing instructions with MCP Inspector
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Simple Tool Server
|
||||
|
||||
**You:** "Create an MCP server that can search my local documents"
|
||||
|
||||
**Skill generates:**
|
||||
- File search tool with glob patterns
|
||||
- Content search tool using grep
|
||||
- Resource handlers for file contents
|
||||
- Claude Desktop configuration
|
||||
- Security validations (path traversal prevention)
|
||||
|
||||
### Database Integration
|
||||
|
||||
**You:** "Build an MCP server to query my PostgreSQL database"
|
||||
|
||||
**Skill generates:**
|
||||
- Database query tool with SQL validation
|
||||
- Schema inspection tools
|
||||
- Connection pooling setup
|
||||
- Environment variable configuration
|
||||
- Read-only query enforcement
|
||||
|
||||
### API Wrapper
|
||||
|
||||
**You:** "Create a server that wraps the GitHub API"
|
||||
|
||||
**Skill generates:**
|
||||
- GitHub API client setup
|
||||
- Tools for common operations (search, issues, PRs)
|
||||
- Authentication configuration
|
||||
- Rate limiting handling
|
||||
- Response formatting for AI consumption
|
||||
|
||||
## Supported Languages
|
||||
|
||||
| Language | SDK | Best For |
|
||||
|----------|-----|----------|
|
||||
| **TypeScript** | `@modelcontextprotocol/sdk` | Web APIs, JS ecosystem |
|
||||
| **Python** | `mcp[cli]` (FastMCP) | Data processing, ML |
|
||||
| **Java** | Spring AI MCP | Enterprise Java apps |
|
||||
| **Kotlin** | Kotlin SDK | Android/JVM apps |
|
||||
| **C#** | ModelContextProtocol NuGet | Windows/Azure apps |
|
||||
|
||||
## Common Patterns Included
|
||||
|
||||
The skill includes templates and guidance for:
|
||||
|
||||
- **Database Integration**: PostgreSQL, MySQL, MongoDB
|
||||
- **API Wrappers**: REST APIs, GraphQL
|
||||
- **File System Access**: Secure file operations
|
||||
- **Search Integration**: Elasticsearch, vector search
|
||||
- **Workflow Automation**: CI/CD, deployments
|
||||
- **Notification Systems**: Email, Slack, SMS
|
||||
- **Data Processing**: ETL, analytics pipelines
|
||||
- **Authentication**: Token validation, permissions
|
||||
|
||||
## Testing Your Server
|
||||
|
||||
The skill provides three testing approaches:
|
||||
|
||||
1. **MCP Inspector** (recommended first)
|
||||
```bash
|
||||
npx @modelcontextprotocol/inspector node build/index.js
|
||||
```
|
||||
- Browser-based testing interface
|
||||
- Validates schemas and responses
|
||||
- No Claude Desktop required
|
||||
|
||||
2. **Claude Desktop Integration**
|
||||
- Add to `claude_desktop_config.json`
|
||||
- Restart Claude Desktop
|
||||
- Test with natural language
|
||||
|
||||
3. **Custom Client**
|
||||
- Build your own MCP client
|
||||
- Use in other AI applications
|
||||
|
||||
## Files Included
|
||||
|
||||
### Templates
|
||||
- `typescript-server.ts.template` - Full TypeScript server template
|
||||
- `python-server.py.template` - Full Python server template
|
||||
- `package.json.template` - npm configuration
|
||||
- `tsconfig.json.template` - TypeScript configuration
|
||||
|
||||
### Data Files
|
||||
- `common-patterns.yaml` - 8 common server patterns with dependencies
|
||||
- `tool-examples.yaml` - Example tool definitions for common use cases
|
||||
|
||||
## Security Features
|
||||
|
||||
Every generated server includes:
|
||||
|
||||
- ✅ Environment variable management (never commit secrets)
|
||||
- ✅ Input validation with schemas
|
||||
- ✅ Proper error handling (don't leak internals)
|
||||
- ✅ .gitignore configuration
|
||||
- ✅ Logging best practices (stderr only for STDIO)
|
||||
- ✅ Path traversal prevention (file servers)
|
||||
- ✅ SQL injection prevention (database servers)
|
||||
|
||||
## Next Steps After Generation
|
||||
|
||||
1. Review generated code and customize tool implementations
|
||||
2. Add your API keys/credentials to `.env`
|
||||
3. Build the project (`npm run build` for TypeScript)
|
||||
4. Test with MCP Inspector
|
||||
5. Add to Claude Desktop configuration
|
||||
6. Test with natural language queries
|
||||
7. Iterate and enhance based on usage
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
The skill includes debugging guidance for:
|
||||
|
||||
- Server not detected in Claude Desktop
|
||||
- Tools not appearing
|
||||
- Connection timeouts
|
||||
- Build errors
|
||||
- STDIO logging issues
|
||||
- Configuration syntax errors
|
||||
|
||||
Check `~/Library/Logs/Claude/mcp*.log` for detailed error messages.
|
||||
|
||||
## Learn More
|
||||
|
||||
- [MCP Documentation](https://modelcontextprotocol.io)
|
||||
- [TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
|
||||
- [Python SDK](https://github.com/modelcontextprotocol/python-sdk)
|
||||
- [Example Servers](https://github.com/modelcontextprotocol/servers)
|
||||
|
||||
---
|
||||
|
||||
**Created by**: Connor
|
||||
**Version**: 0.1.0
|
||||
**License**: MIT
|
||||
121
skills/claude-code/mcp-server-creator/SKILL.md
Normal file
121
skills/claude-code/mcp-server-creator/SKILL.md
Normal file
@@ -0,0 +1,121 @@
|
||||
---
|
||||
name: mcp-server-creator
|
||||
version: 0.2.0
|
||||
description: Use PROACTIVELY when creating Model Context Protocol servers for connecting AI applications to external data sources, tools, and workflows. Generates production-ready MCP servers with TypeScript/Python SDKs, configuration templates, and Claude Desktop integration. Includes testing workflow with MCP Inspector. Not for modifying existing MCP servers or non-MCP integrations.
|
||||
author: Connor
|
||||
---
|
||||
|
||||
# MCP Server Creator
|
||||
|
||||
## Overview
|
||||
|
||||
This skill automates the creation of Model Context Protocol (MCP) servers—the standardized way to connect AI applications to external data sources, tools, and workflows.
|
||||
|
||||
**Key Capabilities**:
|
||||
- Interactive requirements gathering and language selection
|
||||
- Project scaffolding with SDK integration (TypeScript/Python)
|
||||
- Server implementation with tools, resources, and prompts
|
||||
- Claude Desktop configuration generation
|
||||
- Testing workflow with MCP Inspector
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
**Trigger Phrases**:
|
||||
- "create an MCP server for [purpose]"
|
||||
- "build a Model Context Protocol server"
|
||||
- "set up MCP integration with [data source]"
|
||||
- "generate MCP server to expose [tools/data]"
|
||||
|
||||
**Use Cases**:
|
||||
- Exposing custom data sources to AI applications
|
||||
- Creating tools for AI models to call
|
||||
- Building enterprise integrations for Claude
|
||||
|
||||
**NOT for**:
|
||||
- Consuming existing MCP servers (this creates new ones)
|
||||
- Non-AI integrations (use REST APIs instead)
|
||||
- Simple file operations (use built-in tools)
|
||||
|
||||
## Response Style
|
||||
|
||||
- **Interactive**: Ask clarifying questions about purpose and capabilities
|
||||
- **Educational**: Explain MCP concepts and best practices
|
||||
- **Language-aware**: Support TypeScript and Python SDKs
|
||||
- **Production-ready**: Generate complete, tested configurations
|
||||
|
||||
## Quick Decision Matrix
|
||||
|
||||
| User Request | Action | Reference |
|
||||
|--------------|--------|-----------|
|
||||
| "create MCP server" | Full workflow | Start at Phase 1 |
|
||||
| "TypeScript MCP setup" | Skip to Phase 2 | `workflow/phase-2-structure.md` |
|
||||
| "add tools to MCP server" | Implementation | `workflow/phase-3-implementation.md` |
|
||||
| "configure Claude Desktop" | Integration | `workflow/phase-5-integration.md` |
|
||||
| "test MCP server" | Validation | `workflow/phase-6-testing.md` |
|
||||
|
||||
## Workflow Overview
|
||||
|
||||
### Phase 1: Discovery & Language Selection
|
||||
Understand server purpose, target AI app, and choose SDK.
|
||||
→ **Details**: `workflow/phase-1-discovery.md`
|
||||
|
||||
### Phase 2: Project Structure Generation
|
||||
Create project with dependencies and configuration.
|
||||
→ **Details**: `workflow/phase-2-structure.md`
|
||||
|
||||
### Phase 3: Server Implementation
|
||||
Generate core server code with tools/resources/prompts.
|
||||
→ **Details**: `workflow/phase-3-implementation.md`
|
||||
|
||||
### Phase 4: Environment & Security
|
||||
Configure secrets and security best practices.
|
||||
→ **Details**: `workflow/phase-4-security.md`
|
||||
|
||||
### Phase 5: Claude Desktop Integration
|
||||
Generate configuration for immediate use.
|
||||
→ **Details**: `workflow/phase-5-integration.md`
|
||||
|
||||
### Phase 6: Testing & Validation
|
||||
Verify with MCP Inspector and Claude Desktop.
|
||||
→ **Details**: `workflow/phase-6-testing.md`
|
||||
|
||||
### Phase 7: Documentation & Handoff
|
||||
Provide README and next steps.
|
||||
→ **Details**: `workflow/phase-7-documentation.md`
|
||||
|
||||
## Important Reminders
|
||||
|
||||
1. **STDIO = No stdout logging** - Use console.error or stderr only
|
||||
2. **Build before test** - TypeScript requires `npm run build`
|
||||
3. **Absolute paths only** - Claude Desktop config needs full paths
|
||||
4. **Complete restart required** - Quit Claude Desktop entirely (Cmd+Q)
|
||||
5. **Schemas matter** - AI uses descriptions to decide when to call tools
|
||||
6. **Security first** - Never commit secrets, validate all inputs
|
||||
7. **Test incrementally** - MCP Inspector before Claude integration
|
||||
|
||||
## Limitations
|
||||
|
||||
- Only TypeScript and Python SDKs fully supported
|
||||
- HTTP transport requires additional security setup
|
||||
- Claude Desktop must be restarted for config changes
|
||||
- Cannot modify existing MCP servers (creates new ones only)
|
||||
|
||||
## Reference Materials
|
||||
|
||||
| Resource | Purpose |
|
||||
|----------|---------|
|
||||
| `workflow/*.md` | Detailed phase instructions |
|
||||
| `reference/capabilities.md` | Tools, resources, prompts deep-dive |
|
||||
| `reference/troubleshooting.md` | Common issues and debugging |
|
||||
| `reference/language-guides/*.md` | TypeScript and Python best practices |
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] Project structure created with dependencies
|
||||
- [ ] Server implements requested capabilities
|
||||
- [ ] All tools have proper schemas and descriptions
|
||||
- [ ] Logging configured correctly (no stdout for STDIO)
|
||||
- [ ] Environment variables configured securely
|
||||
- [ ] Claude Desktop config generated with absolute paths
|
||||
- [ ] MCP Inspector testing passes
|
||||
- [ ] Server appears in Claude Desktop after restart
|
||||
144
skills/claude-code/mcp-server-creator/data/common-patterns.yaml
Normal file
144
skills/claude-code/mcp-server-creator/data/common-patterns.yaml
Normal file
@@ -0,0 +1,144 @@
|
||||
# Common MCP Server Patterns
|
||||
|
||||
database_integration:
|
||||
name: "Database Integration"
|
||||
description: "Connect AI to databases (PostgreSQL, MySQL, MongoDB)"
|
||||
typical_tools:
|
||||
- query_database: "Execute SQL queries with safety checks"
|
||||
- get_schema: "Retrieve database schema information"
|
||||
- list_tables: "List all available tables"
|
||||
- describe_table: "Get detailed table structure"
|
||||
typical_resources:
|
||||
- "db://tables/{table}/schema"
|
||||
- "db://tables/{table}/sample-data"
|
||||
dependencies:
|
||||
typescript: ["pg", "mysql2", "mongodb"]
|
||||
python: ["psycopg2", "pymysql", "pymongo"]
|
||||
security_notes:
|
||||
- "Use read-only connections when possible"
|
||||
- "Implement query validation to prevent SQL injection"
|
||||
- "Never expose raw connection strings"
|
||||
|
||||
api_wrapper:
|
||||
name: "API Wrapper"
|
||||
description: "Wrap REST APIs for AI consumption"
|
||||
typical_tools:
|
||||
- search_api: "Search endpoint with filters"
|
||||
- get_resource: "Fetch specific resource by ID"
|
||||
- list_resources: "List resources with pagination"
|
||||
- create_resource: "Create new resource (with approval)"
|
||||
typical_resources:
|
||||
- "api://endpoints/{endpoint}"
|
||||
- "api://docs/{path}"
|
||||
dependencies:
|
||||
typescript: ["axios", "node-fetch"]
|
||||
python: ["httpx", "requests"]
|
||||
security_notes:
|
||||
- "Store API keys in environment variables"
|
||||
- "Implement rate limiting"
|
||||
- "Validate all responses"
|
||||
|
||||
filesystem_access:
|
||||
name: "File System Access"
|
||||
description: "Secure file operations with access controls"
|
||||
typical_tools:
|
||||
- search_files: "Search files by pattern or content"
|
||||
- read_file: "Read file contents (with permission check)"
|
||||
- list_directory: "List directory contents"
|
||||
- get_file_info: "Get file metadata"
|
||||
typical_resources:
|
||||
- "file:///{absolute_path}"
|
||||
- "file:///workspace/{relative_path}"
|
||||
dependencies:
|
||||
typescript: ["fs/promises", "glob", "ignore"]
|
||||
python: ["pathlib", "glob", "gitignore_parser"]
|
||||
security_notes:
|
||||
- "Implement strict path validation (prevent ../ attacks)"
|
||||
- "Use allowlist/denylist for directories"
|
||||
- "Never allow writes without explicit approval"
|
||||
|
||||
workflow_automation:
|
||||
name: "Workflow Automation"
|
||||
description: "Trigger and monitor automated workflows"
|
||||
typical_tools:
|
||||
- trigger_workflow: "Start a workflow with parameters"
|
||||
- get_workflow_status: "Check workflow execution status"
|
||||
- list_workflows: "List available workflows"
|
||||
- cancel_workflow: "Cancel running workflow"
|
||||
typical_prompts:
|
||||
- deployment_workflow: "Template for deployment approvals"
|
||||
- testing_workflow: "Template for test execution"
|
||||
dependencies:
|
||||
typescript: ["@actions/core", "@octokit/rest"]
|
||||
python: ["github", "gitlab"]
|
||||
security_notes:
|
||||
- "Require approval for destructive operations"
|
||||
- "Log all workflow executions"
|
||||
- "Implement timeout mechanisms"
|
||||
|
||||
search_integration:
|
||||
name: "Search Integration"
|
||||
description: "Connect to search engines and indexing systems"
|
||||
typical_tools:
|
||||
- search: "Full-text search with filters"
|
||||
- semantic_search: "Vector-based semantic search"
|
||||
- index_document: "Add document to search index"
|
||||
typical_resources:
|
||||
- "search://query/{query}"
|
||||
- "search://document/{doc_id}"
|
||||
dependencies:
|
||||
typescript: ["@elastic/elasticsearch", "typesense"]
|
||||
python: ["elasticsearch", "typesense"]
|
||||
security_notes:
|
||||
- "Sanitize search queries"
|
||||
- "Implement access control on results"
|
||||
- "Rate limit search requests"
|
||||
|
||||
notification_system:
|
||||
name: "Notification System"
|
||||
description: "Send notifications via email, Slack, SMS"
|
||||
typical_tools:
|
||||
- send_notification: "Send notification to channel"
|
||||
- get_notification_history: "Retrieve past notifications"
|
||||
- create_alert: "Set up automated alerts"
|
||||
dependencies:
|
||||
typescript: ["@slack/web-api", "nodemailer", "twilio"]
|
||||
python: ["slack_sdk", "sendgrid", "twilio"]
|
||||
security_notes:
|
||||
- "Validate recipient addresses"
|
||||
- "Prevent notification spam"
|
||||
- "Never expose credentials in logs"
|
||||
|
||||
data_processing:
|
||||
name: "Data Processing Pipeline"
|
||||
description: "Transform, analyze, and aggregate data"
|
||||
typical_tools:
|
||||
- transform_data: "Apply transformations to dataset"
|
||||
- aggregate_data: "Compute aggregations and statistics"
|
||||
- validate_data: "Validate data against schema"
|
||||
typical_resources:
|
||||
- "data://dataset/{name}"
|
||||
- "data://schema/{schema_id}"
|
||||
dependencies:
|
||||
typescript: ["papaparse", "lodash", "ajv"]
|
||||
python: ["pandas", "numpy", "jsonschema"]
|
||||
security_notes:
|
||||
- "Validate data schemas"
|
||||
- "Implement size limits"
|
||||
- "Sanitize outputs"
|
||||
|
||||
authentication_service:
|
||||
name: "Authentication Service"
|
||||
description: "User authentication and authorization checks"
|
||||
typical_tools:
|
||||
- verify_token: "Validate authentication token"
|
||||
- get_user_permissions: "Retrieve user permissions"
|
||||
- check_access: "Check if user has access to resource"
|
||||
dependencies:
|
||||
typescript: ["jsonwebtoken", "passport", "bcrypt"]
|
||||
python: ["pyjwt", "passlib", "python-jose"]
|
||||
security_notes:
|
||||
- "Never expose secrets or tokens"
|
||||
- "Use secure token storage"
|
||||
- "Implement token expiration"
|
||||
- "Log all authentication attempts"
|
||||
168
skills/claude-code/mcp-server-creator/data/tool-examples.yaml
Normal file
168
skills/claude-code/mcp-server-creator/data/tool-examples.yaml
Normal file
@@ -0,0 +1,168 @@
|
||||
# Example Tool Definitions for Common Use Cases
|
||||
|
||||
database_query:
|
||||
name: "query_database"
|
||||
description: "Execute a SQL query against the database (read-only)"
|
||||
params:
|
||||
- name: "query"
|
||||
type: "string"
|
||||
description: "SQL query to execute (SELECT only)"
|
||||
- name: "limit"
|
||||
type: "number"
|
||||
description: "Maximum number of rows to return (default: 100)"
|
||||
optional: true
|
||||
returns: "Array of result rows as JSON objects"
|
||||
implementation_notes:
|
||||
- "Validate query is SELECT only (no INSERT/UPDATE/DELETE)"
|
||||
- "Apply row limits to prevent large responses"
|
||||
- "Handle connection errors gracefully"
|
||||
- "Format results as JSON for easy AI parsing"
|
||||
|
||||
web_search:
|
||||
name: "search_web"
|
||||
description: "Search the web using a search engine API"
|
||||
params:
|
||||
- name: "query"
|
||||
type: "string"
|
||||
description: "Search query string"
|
||||
- name: "num_results"
|
||||
type: "number"
|
||||
description: "Number of results to return (default: 10)"
|
||||
optional: true
|
||||
returns: "Array of search results with title, URL, and snippet"
|
||||
implementation_notes:
|
||||
- "Use search API (Google Custom Search, Bing, etc.)"
|
||||
- "Cache results to avoid rate limits"
|
||||
- "Return structured data (title, url, description)"
|
||||
- "Handle API errors and quota limits"
|
||||
|
||||
file_search:
|
||||
name: "search_files"
|
||||
description: "Search for files matching a pattern or containing text"
|
||||
params:
|
||||
- name: "pattern"
|
||||
type: "string"
|
||||
description: "File pattern (glob) or search term"
|
||||
- name: "directory"
|
||||
type: "string"
|
||||
description: "Directory to search in (default: current)"
|
||||
optional: true
|
||||
- name: "search_content"
|
||||
type: "boolean"
|
||||
description: "Search file contents, not just names (default: false)"
|
||||
optional: true
|
||||
returns: "Array of file paths matching the pattern or containing the text"
|
||||
implementation_notes:
|
||||
- "Validate directory path (prevent path traversal)"
|
||||
- "Respect .gitignore patterns"
|
||||
- "Limit search depth and file count"
|
||||
- "Use efficient search algorithms (ripgrep, etc.)"
|
||||
|
||||
send_email:
|
||||
name: "send_email"
|
||||
description: "Send an email message"
|
||||
params:
|
||||
- name: "to"
|
||||
type: "string"
|
||||
description: "Recipient email address"
|
||||
- name: "subject"
|
||||
type: "string"
|
||||
description: "Email subject line"
|
||||
- name: "body"
|
||||
type: "string"
|
||||
description: "Email body (plain text or HTML)"
|
||||
- name: "html"
|
||||
type: "boolean"
|
||||
description: "Whether body is HTML (default: false)"
|
||||
optional: true
|
||||
returns: "Confirmation message with message ID"
|
||||
implementation_notes:
|
||||
- "Validate email addresses"
|
||||
- "Use transactional email service (SendGrid, SES, etc.)"
|
||||
- "Implement rate limiting"
|
||||
- "Log all sent emails"
|
||||
- "Require user approval for sensitive sends"
|
||||
|
||||
create_ticket:
|
||||
name: "create_ticket"
|
||||
description: "Create a new issue or ticket in project management system"
|
||||
params:
|
||||
- name: "title"
|
||||
type: "string"
|
||||
description: "Issue title"
|
||||
- name: "description"
|
||||
type: "string"
|
||||
description: "Detailed issue description"
|
||||
- name: "priority"
|
||||
type: "string"
|
||||
description: "Priority level (low, medium, high, critical)"
|
||||
optional: true
|
||||
- name: "assignee"
|
||||
type: "string"
|
||||
description: "Username to assign ticket to"
|
||||
optional: true
|
||||
returns: "Created ticket ID and URL"
|
||||
implementation_notes:
|
||||
- "Integrate with Jira, GitHub Issues, Linear, etc."
|
||||
- "Validate priority values"
|
||||
- "Apply default labels/tags"
|
||||
- "Return link to created ticket"
|
||||
|
||||
calculate_metrics:
|
||||
name: "calculate_metrics"
|
||||
description: "Calculate metrics from a dataset"
|
||||
params:
|
||||
- name: "dataset"
|
||||
type: "array"
|
||||
description: "Array of data points"
|
||||
- name: "metrics"
|
||||
type: "array"
|
||||
description: "List of metrics to calculate (mean, median, sum, etc.)"
|
||||
returns: "Object with calculated metric values"
|
||||
implementation_notes:
|
||||
- "Support common statistical operations"
|
||||
- "Handle missing or invalid data"
|
||||
- "Return results in structured format"
|
||||
- "Optimize for large datasets"
|
||||
|
||||
format_code:
|
||||
name: "format_code"
|
||||
description: "Format source code using language-specific formatter"
|
||||
params:
|
||||
- name: "code"
|
||||
type: "string"
|
||||
description: "Source code to format"
|
||||
- name: "language"
|
||||
type: "string"
|
||||
description: "Programming language (javascript, python, etc.)"
|
||||
- name: "style"
|
||||
type: "string"
|
||||
description: "Style guide (standard, prettier, black, etc.)"
|
||||
optional: true
|
||||
returns: "Formatted code string"
|
||||
implementation_notes:
|
||||
- "Use language-specific formatters (prettier, black, etc.)"
|
||||
- "Handle syntax errors gracefully"
|
||||
- "Support multiple style configurations"
|
||||
- "Preserve comments and structure"
|
||||
|
||||
translate_text:
|
||||
name: "translate_text"
|
||||
description: "Translate text between languages"
|
||||
params:
|
||||
- name: "text"
|
||||
type: "string"
|
||||
description: "Text to translate"
|
||||
- name: "source_lang"
|
||||
type: "string"
|
||||
description: "Source language code (auto-detect if omitted)"
|
||||
optional: true
|
||||
- name: "target_lang"
|
||||
type: "string"
|
||||
description: "Target language code"
|
||||
returns: "Translated text string"
|
||||
implementation_notes:
|
||||
- "Use translation API (Google Translate, DeepL, etc.)"
|
||||
- "Support language auto-detection"
|
||||
- "Handle API rate limits"
|
||||
- "Cache common translations"
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"weather": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/Users/username/projects/mcp-weather-server/build/index.js"
|
||||
]
|
||||
},
|
||||
"database": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/Users/username/projects/mcp-database-server/build/index.js"
|
||||
],
|
||||
"env": {
|
||||
"DATABASE_URL": "postgresql://user:pass@localhost:5432/mydb"
|
||||
}
|
||||
},
|
||||
"python-server": {
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"--directory",
|
||||
"/Users/username/projects/mcp-python-server",
|
||||
"run",
|
||||
"main.py"
|
||||
],
|
||||
"env": {
|
||||
"API_KEY": "your_api_key_here"
|
||||
}
|
||||
},
|
||||
"filesystem": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/Users/username/projects/mcp-filesystem-server/build/index.js"
|
||||
],
|
||||
"env": {
|
||||
"ALLOWED_DIRECTORIES": "/Users/username/Documents,/Users/username/Projects"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Simple Weather MCP Server Example
|
||||
*
|
||||
* Demonstrates basic MCP server structure with two tools:
|
||||
* - get_forecast: Get weather forecast for a location
|
||||
* - get_alerts: Get weather alerts for a US state
|
||||
*/
|
||||
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import {
|
||||
CallToolRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
|
||||
const NWS_API_BASE = "https://api.weather.gov";
|
||||
|
||||
// Initialize server
|
||||
const server = new Server(
|
||||
{
|
||||
name: "weather-server",
|
||||
version: "1.0.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// List available tools
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
||||
tools: [
|
||||
{
|
||||
name: "get_forecast",
|
||||
description: "Get weather forecast for a location (latitude, longitude)",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
latitude: {
|
||||
type: "number",
|
||||
description: "Latitude coordinate",
|
||||
},
|
||||
longitude: {
|
||||
type: "number",
|
||||
description: "Longitude coordinate",
|
||||
},
|
||||
},
|
||||
required: ["latitude", "longitude"],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get_alerts",
|
||||
description: "Get weather alerts for a US state",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
state: {
|
||||
type: "string",
|
||||
description: "Two-letter US state code (e.g., CA, NY)",
|
||||
},
|
||||
},
|
||||
required: ["state"],
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
// Handle tool calls
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
|
||||
if (name === "get_forecast") {
|
||||
const { latitude, longitude } = args as { latitude: number; longitude: number };
|
||||
|
||||
try {
|
||||
// Get grid point for location
|
||||
const pointResponse = await fetch(
|
||||
`${NWS_API_BASE}/points/${latitude},${longitude}`
|
||||
);
|
||||
const pointData = await pointResponse.json();
|
||||
|
||||
// Get forecast from grid point
|
||||
const forecastUrl = pointData.properties.forecast;
|
||||
const forecastResponse = await fetch(forecastUrl);
|
||||
const forecastData = await forecastResponse.json();
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(forecastData.properties.periods, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error fetching forecast: ${error instanceof Error ? error.message : String(error)}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (name === "get_alerts") {
|
||||
const { state } = args as { state: string };
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${NWS_API_BASE}/alerts/active?area=${state}`
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(data.features || [], null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error fetching alerts: ${error instanceof Error ? error.message : String(error)}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
});
|
||||
|
||||
// Start server
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
console.error("Weather MCP server running on stdio");
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,75 @@
|
||||
# MCP Capability Deep-Dives
|
||||
|
||||
## Tools: AI-Callable Functions
|
||||
|
||||
**When to use**: AI needs to perform actions or fetch computed data
|
||||
|
||||
### Structure
|
||||
- **Name**: Descriptive verb (e.g., "search_docs", "create_ticket")
|
||||
- **Description**: Clear explanation (AI uses this to decide when to call)
|
||||
- **Schema**: Input parameters with types and descriptions
|
||||
- **Handler**: Async function returning structured content
|
||||
|
||||
### Example Tool Types
|
||||
- Data fetching: "get_user_data", "search_products"
|
||||
- Computation: "calculate_metrics", "analyze_sentiment"
|
||||
- Actions: "send_email", "create_issue", "update_status"
|
||||
- External APIs: "search_web", "translate_text"
|
||||
|
||||
---
|
||||
|
||||
## Resources: Data Exposure
|
||||
|
||||
**When to use**: AI needs to read data without side effects
|
||||
|
||||
### Structure
|
||||
- **URI**: Pattern like "scheme://path/{param}"
|
||||
- **MIME type**: Helps AI understand content format
|
||||
- **Handler**: Returns content (text, JSON, binary)
|
||||
|
||||
### Example Resource Types
|
||||
- File contents: "file:///path/to/file.txt"
|
||||
- Database records: "db://users/{user_id}"
|
||||
- API responses: "api://endpoint/{id}"
|
||||
- Search results: "search://query/{term}"
|
||||
|
||||
---
|
||||
|
||||
## Prompts: Specialized Workflows
|
||||
|
||||
**When to use**: Provide templates for common tasks
|
||||
|
||||
### Structure
|
||||
- **Name**: Descriptive identifier
|
||||
- **Description**: When to use this prompt
|
||||
- **Arguments**: Parameters to customize
|
||||
- **Template**: Pre-filled prompt text
|
||||
|
||||
### Example Prompt Types
|
||||
- Code review: Pre-filled checklist
|
||||
- Bug triage: Structured investigation steps
|
||||
- Documentation: Template with sections
|
||||
|
||||
---
|
||||
|
||||
## Common Server Patterns
|
||||
|
||||
### Database Integration Server
|
||||
**Tools**: query_database, get_schema, list_tables
|
||||
**Resources**: db://tables/{table}/schema
|
||||
**Example**: PostgreSQL, MySQL, MongoDB access
|
||||
|
||||
### API Wrapper Server
|
||||
**Tools**: call_endpoint, search_api, get_resource
|
||||
**Resources**: api://endpoints/{endpoint}
|
||||
**Example**: Wrap REST APIs for AI consumption
|
||||
|
||||
### File System Server
|
||||
**Resources**: file:///{path}
|
||||
**Tools**: search_files, read_file, list_directory
|
||||
**Example**: Secure file access with permissions
|
||||
|
||||
### Workflow Automation Server
|
||||
**Tools**: trigger_workflow, check_status, get_results
|
||||
**Prompts**: workflow_templates
|
||||
**Example**: CI/CD, deployment, data pipelines
|
||||
@@ -0,0 +1,91 @@
|
||||
# Python MCP Server Best Practices (FastMCP)
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
uv init mcp-server-name
|
||||
uv add "mcp[cli]"
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
- ✓ Use type hints (FastMCP reads them!)
|
||||
- ✓ Write detailed docstrings (becomes tool descriptions)
|
||||
- ✓ Use async functions for I/O
|
||||
- ✓ Handle exceptions gracefully
|
||||
- ✓ Log to stderr only in STDIO mode
|
||||
|
||||
## Tool Definition
|
||||
|
||||
```python
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP("server-name")
|
||||
|
||||
@mcp.tool()
|
||||
async def search_database(query: str, limit: int = 10) -> str:
|
||||
"""
|
||||
Search the database for records matching the query.
|
||||
|
||||
Args:
|
||||
query: Search terms to match against records
|
||||
limit: Maximum number of results to return (default: 10)
|
||||
|
||||
Returns:
|
||||
JSON string of matching records
|
||||
"""
|
||||
results = await db.search(query, limit=limit)
|
||||
return json.dumps(results)
|
||||
```
|
||||
|
||||
## Resource Definition
|
||||
|
||||
```python
|
||||
@mcp.resource("db://tables/{table_name}/schema")
|
||||
async def get_table_schema(table_name: str) -> str:
|
||||
"""Get the schema for a database table."""
|
||||
schema = await db.get_schema(table_name)
|
||||
return json.dumps(schema)
|
||||
```
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### STDIO Transport
|
||||
|
||||
```python
|
||||
import sys
|
||||
|
||||
# WRONG - corrupts JSON-RPC
|
||||
print("Debug info")
|
||||
|
||||
# CORRECT - safe for STDIO
|
||||
print("Debug info", file=sys.stderr)
|
||||
|
||||
# Or use logging
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO, stream=sys.stderr)
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
async def risky_operation(param: str) -> str:
|
||||
"""Perform an operation that might fail."""
|
||||
try:
|
||||
result = await external_api.call(param)
|
||||
return str(result)
|
||||
except Exception as e:
|
||||
logging.error(f"Operation failed: {e}")
|
||||
raise ValueError(f"Operation failed: {e}")
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
# With uv
|
||||
uv run main.py
|
||||
|
||||
# Direct
|
||||
python main.py
|
||||
```
|
||||
@@ -0,0 +1,71 @@
|
||||
# TypeScript MCP Server Best Practices
|
||||
|
||||
## Configuration
|
||||
|
||||
- ✓ Use strict mode in tsconfig.json
|
||||
- ✓ Target ES2022 or later
|
||||
- ✓ Use Node16 module resolution
|
||||
|
||||
## Implementation
|
||||
|
||||
- ✓ Leverage Zod for runtime validation
|
||||
- ✓ Export types for reusability
|
||||
- ✓ Use async/await consistently
|
||||
- ✓ Handle errors with try/catch
|
||||
- ✓ Build before testing!
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### STDIO Transport
|
||||
```typescript
|
||||
// WRONG - corrupts JSON-RPC
|
||||
console.log("Debug info");
|
||||
|
||||
// CORRECT - safe for STDIO
|
||||
console.error("Debug info");
|
||||
```
|
||||
|
||||
### Tool Schemas
|
||||
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
|
||||
const ToolInputSchema = z.object({
|
||||
query: z.string().describe("Search query"),
|
||||
limit: z.number().optional().default(10).describe("Max results"),
|
||||
});
|
||||
|
||||
// Validate in handler
|
||||
const input = ToolInputSchema.parse(request.params.arguments);
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```typescript
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
try {
|
||||
const result = await performOperation(request.params);
|
||||
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
||||
} catch (error) {
|
||||
console.error("Tool error:", error);
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: `Error: ${error.message}`
|
||||
}],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Build & Run
|
||||
|
||||
```bash
|
||||
# Development
|
||||
npm run watch
|
||||
|
||||
# Production
|
||||
npm run build
|
||||
node build/index.js
|
||||
```
|
||||
@@ -0,0 +1,103 @@
|
||||
# MCP Server Troubleshooting
|
||||
|
||||
## Error Handling Patterns
|
||||
|
||||
### Validation Errors
|
||||
|
||||
```typescript
|
||||
if (!isValid(input)) {
|
||||
throw new Error("Invalid input: expected format X, got Y");
|
||||
}
|
||||
```
|
||||
|
||||
### API Errors
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const result = await externalAPI.call();
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error("API error:", error);
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: `Error: ${error.message}. Please try again.`
|
||||
}]
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Resource Not Found
|
||||
|
||||
```typescript
|
||||
if (!resource) {
|
||||
throw new Error(`Resource not found: ${uri}`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Issues
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| Server not detected | Invalid path | Use absolute path, verify file exists |
|
||||
| Tools don't appear | Build not run | Run `npm run build` |
|
||||
| "Server error" | stdout logging | Remove console.log, use console.error |
|
||||
| Connection timeout | Server crash | Check mcp-server-NAME.log for errors |
|
||||
| Invalid config | JSON syntax | Validate JSON, check quotes/commas |
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Commands
|
||||
|
||||
### Check Claude Desktop Logs
|
||||
|
||||
```bash
|
||||
tail -f ~/Library/Logs/Claude/mcp.log
|
||||
tail -f ~/Library/Logs/Claude/mcp-server-[name].log
|
||||
```
|
||||
|
||||
### Validate Config JSON
|
||||
|
||||
```bash
|
||||
python -m json.tool ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
||||
```
|
||||
|
||||
### Test with MCP Inspector
|
||||
|
||||
```bash
|
||||
npx @modelcontextprotocol/inspector [command] [args]
|
||||
```
|
||||
|
||||
### Restart Claude Desktop
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
osascript -e 'quit app "Claude"'
|
||||
open -a Claude
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Transport-Specific Issues
|
||||
|
||||
### STDIO Transport
|
||||
|
||||
**Problem**: Server crashes with no error
|
||||
**Cause**: Using console.log() which corrupts JSON-RPC
|
||||
**Solution**: Use console.error() only
|
||||
|
||||
**Problem**: Server not responding
|
||||
**Cause**: Blocking synchronous operation
|
||||
**Solution**: Use async/await for all I/O
|
||||
|
||||
### HTTP Transport
|
||||
|
||||
**Problem**: Connection refused
|
||||
**Cause**: Wrong port or server not running
|
||||
**Solution**: Check PORT env var, verify server started
|
||||
|
||||
**Problem**: Authentication errors
|
||||
**Cause**: Missing or invalid credentials
|
||||
**Solution**: Configure auth headers/tokens
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "{{SERVER_NAME}}",
|
||||
"version": "1.0.0",
|
||||
"description": "{{SERVER_DESCRIPTION}}",
|
||||
"type": "module",
|
||||
"main": "build/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
|
||||
"watch": "tsc --watch",
|
||||
"start": "node build/index.js",
|
||||
"inspect": "npx @modelcontextprotocol/inspector node build/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.0",
|
||||
"zod": "^3.23.0"{{#EXTRA_DEPS}},
|
||||
{{EXTRA_DEPS}}{{/EXTRA_DEPS}}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.0.0",
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
"keywords": ["mcp", "model-context-protocol", "{{SERVER_NAME}}"],
|
||||
"author": "{{AUTHOR}}",
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
{{SERVER_NAME}} MCP Server
|
||||
|
||||
{{SERVER_DESCRIPTION}}
|
||||
"""
|
||||
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
import os
|
||||
from typing import Optional
|
||||
import logging
|
||||
|
||||
# Configure logging to stderr (CRITICAL: never log to stdout in STDIO mode)
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
handlers=[logging.StreamHandler()] # Writes to stderr by default
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Initialize MCP server
|
||||
mcp = FastMCP("{{SERVER_NAME}}")
|
||||
|
||||
{{#TOOLS}}
|
||||
@mcp.tool()
|
||||
async def {{TOOL_FUNCTION}}({{TOOL_PARAMS_TYPED}}) -> {{TOOL_RETURN_TYPE}}:
|
||||
"""
|
||||
{{TOOL_DESCRIPTION}}
|
||||
|
||||
Args:
|
||||
{{#TOOL_PARAMS}}
|
||||
{{PARAM_NAME}}: {{PARAM_DESCRIPTION}}
|
||||
{{/TOOL_PARAMS}}
|
||||
|
||||
Returns:
|
||||
{{TOOL_RETURN_DESCRIPTION}}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"{{TOOL_FUNCTION}} called with: {{TOOL_PARAMS_LOG}}")
|
||||
|
||||
# TODO: Implement your tool logic here
|
||||
result = None # Replace with actual implementation
|
||||
|
||||
return str(result)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in {{TOOL_FUNCTION}}: {str(e)}")
|
||||
raise
|
||||
|
||||
{{/TOOLS}}
|
||||
|
||||
{{#HAS_RESOURCES}}
|
||||
@mcp.resource("{{RESOURCE_URI_PATTERN}}")
|
||||
async def get_resource({{RESOURCE_PARAMS}}) -> str:
|
||||
"""
|
||||
{{RESOURCE_DESCRIPTION}}
|
||||
|
||||
Args:
|
||||
{{#RESOURCE_PARAMS_LIST}}
|
||||
{{PARAM_NAME}}: {{PARAM_DESCRIPTION}}
|
||||
{{/RESOURCE_PARAMS_LIST}}
|
||||
|
||||
Returns:
|
||||
Resource content as string
|
||||
"""
|
||||
try:
|
||||
logger.info(f"Resource requested: {{RESOURCE_PARAMS_LOG}}")
|
||||
|
||||
# TODO: Implement resource fetching logic
|
||||
content = "" # Replace with actual implementation
|
||||
|
||||
return content
|
||||
except Exception as e:
|
||||
logger.error(f"Error fetching resource: {str(e)}")
|
||||
raise
|
||||
{{/HAS_RESOURCES}}
|
||||
|
||||
{{#HAS_PROMPTS}}
|
||||
@mcp.prompt()
|
||||
async def {{PROMPT_NAME}}({{PROMPT_PARAMS}}) -> str:
|
||||
"""
|
||||
{{PROMPT_DESCRIPTION}}
|
||||
|
||||
Args:
|
||||
{{#PROMPT_PARAMS_LIST}}
|
||||
{{PARAM_NAME}}: {{PARAM_DESCRIPTION}}
|
||||
{{/PROMPT_PARAMS_LIST}}
|
||||
|
||||
Returns:
|
||||
Formatted prompt template
|
||||
"""
|
||||
return f"""
|
||||
{{PROMPT_TEMPLATE}}
|
||||
"""
|
||||
{{/HAS_PROMPTS}}
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info("Starting {{SERVER_NAME}} MCP server...")
|
||||
mcp.run()
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"outDir": "./build",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "build"]
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import {
|
||||
CallToolRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
import { z } from "zod";
|
||||
|
||||
// Server metadata
|
||||
const SERVER_NAME = "{{SERVER_NAME}}";
|
||||
const SERVER_VERSION = "1.0.0";
|
||||
|
||||
// Initialize MCP server
|
||||
const server = new Server(
|
||||
{
|
||||
name: SERVER_NAME,
|
||||
version: SERVER_VERSION,
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
{{#HAS_RESOURCES}}resources: {},{{/HAS_RESOURCES}}
|
||||
{{#HAS_PROMPTS}}prompts: {},{{/HAS_PROMPTS}}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// List available tools
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
||||
tools: [
|
||||
{{#TOOLS}}
|
||||
{
|
||||
name: "{{TOOL_NAME}}",
|
||||
description: "{{TOOL_DESCRIPTION}}",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
{{#TOOL_PARAMS}}
|
||||
{{PARAM_NAME}}: {
|
||||
type: "{{PARAM_TYPE}}",
|
||||
description: "{{PARAM_DESCRIPTION}}",
|
||||
},
|
||||
{{/TOOL_PARAMS}}
|
||||
},
|
||||
required: [{{REQUIRED_PARAMS}}],
|
||||
},
|
||||
},
|
||||
{{/TOOLS}}
|
||||
],
|
||||
}));
|
||||
|
||||
// Handle tool calls
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
|
||||
{{#TOOLS}}
|
||||
if (name === "{{TOOL_NAME}}") {
|
||||
try {
|
||||
// TODO: Implement {{TOOL_NAME}} logic
|
||||
{{#TOOL_PARAMS}}
|
||||
const {{PARAM_NAME}} = args.{{PARAM_NAME}} as {{PARAM_TS_TYPE}};
|
||||
{{/TOOL_PARAMS}}
|
||||
|
||||
// Your implementation here
|
||||
const result = await {{TOOL_FUNCTION}}({{PARAM_NAMES}});
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Error in {{TOOL_NAME}}:`, error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
{{/TOOLS}}
|
||||
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
});
|
||||
|
||||
{{#HAS_RESOURCES}}
|
||||
// TODO: Implement resource handlers
|
||||
// Example:
|
||||
// server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
||||
// resources: [
|
||||
// {
|
||||
// uri: "resource://template/{id}",
|
||||
// name: "Resource Name",
|
||||
// description: "Resource description",
|
||||
// },
|
||||
// ],
|
||||
// }));
|
||||
{{/HAS_RESOURCES}}
|
||||
|
||||
{{#HAS_PROMPTS}}
|
||||
// TODO: Implement prompt handlers
|
||||
// Example:
|
||||
// server.setRequestHandler(ListPromptsRequestSchema, async () => ({
|
||||
// prompts: [
|
||||
// {
|
||||
// name: "prompt_name",
|
||||
// description: "Prompt description",
|
||||
// arguments: [
|
||||
// {
|
||||
// name: "arg_name",
|
||||
// description: "Argument description",
|
||||
// required: true,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// }));
|
||||
{{/HAS_PROMPTS}}
|
||||
|
||||
// Start server
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
|
||||
// CRITICAL: Never use console.log() in STDIO mode - it corrupts the JSON-RPC stream!
|
||||
console.error(`${SERVER_NAME} MCP server running on stdio`);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error("Fatal error:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
# Phase 1: Discovery & Language Selection
|
||||
|
||||
**Purpose**: Understand what the user wants to build and choose the right SDK
|
||||
|
||||
## Questions to Ask
|
||||
|
||||
### 1. Server Purpose
|
||||
- "What data source, tools, or workflows do you want to expose to AI?"
|
||||
- Examples: "Access PostgreSQL database", "Search Jira tickets", "Format code"
|
||||
|
||||
### 2. Target AI Application
|
||||
- Claude Desktop (most common)
|
||||
- Custom AI application
|
||||
- Multiple clients
|
||||
|
||||
### 3. Programming Language Preference
|
||||
- **TypeScript/Node.js** (recommended for web APIs, JavaScript ecosystem)
|
||||
- **Python** (recommended for data processing, ML workflows)
|
||||
- **Java/Spring AI** (enterprise Java applications)
|
||||
- **Kotlin** (Android/JVM applications)
|
||||
- **C#/.NET** (Windows/Azure applications)
|
||||
|
||||
### 4. Capability Types Needed
|
||||
- **Tools**: Functions AI can call (e.g., "get_weather", "search_database")
|
||||
- **Resources**: Data AI can read (e.g., file contents, API responses)
|
||||
- **Prompts**: Specialized templates for common tasks
|
||||
|
||||
## Output
|
||||
|
||||
Clear understanding of:
|
||||
- Server purpose
|
||||
- Language choice
|
||||
- Capabilities needed (tools/resources/prompts)
|
||||
|
||||
## Transition
|
||||
|
||||
Proceed to Phase 2 (Project Structure Generation)
|
||||
@@ -0,0 +1,88 @@
|
||||
# Phase 2: Project Structure Generation
|
||||
|
||||
**Purpose**: Create proper project structure with SDK integration
|
||||
|
||||
## TypeScript Project Setup
|
||||
|
||||
```bash
|
||||
# Create project directory
|
||||
mkdir mcp-[server-name]
|
||||
cd mcp-[server-name]
|
||||
|
||||
# Initialize npm project
|
||||
npm init -y
|
||||
|
||||
# Install dependencies
|
||||
npm install @modelcontextprotocol/sdk zod
|
||||
npm install -D @types/node typescript
|
||||
```
|
||||
|
||||
### TypeScript Configuration (tsconfig.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"outDir": "./build",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
```
|
||||
|
||||
### Package.json Scripts
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
|
||||
"watch": "tsc --watch",
|
||||
"start": "node build/index.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Python Project Setup
|
||||
|
||||
```bash
|
||||
# Create project with uv
|
||||
uv init mcp-[server-name]
|
||||
cd mcp-[server-name]
|
||||
|
||||
# Set up virtual environment
|
||||
uv venv
|
||||
source .venv/bin/activate
|
||||
|
||||
# Install MCP SDK
|
||||
uv add "mcp[cli]"
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
mcp-server-name/
|
||||
├── src/
|
||||
│ └── index.ts (or main.py)
|
||||
├── build/ (TypeScript only)
|
||||
├── .env.example
|
||||
├── .gitignore
|
||||
├── package.json / pyproject.toml
|
||||
├── tsconfig.json (TypeScript only)
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Complete project structure with dependencies installed
|
||||
|
||||
## Transition
|
||||
|
||||
Proceed to Phase 3 (Server Implementation)
|
||||
@@ -0,0 +1,134 @@
|
||||
# Phase 3: Server Implementation
|
||||
|
||||
**Purpose**: Generate core server code with requested capabilities
|
||||
|
||||
## TypeScript Server Template
|
||||
|
||||
```typescript
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import { z } from "zod";
|
||||
|
||||
// Initialize server
|
||||
const server = new Server(
|
||||
{
|
||||
name: "server-name",
|
||||
version: "1.0.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
resources: {},
|
||||
prompts: {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Example Tool
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
||||
tools: [
|
||||
{
|
||||
name: "tool_name",
|
||||
description: "What this tool does",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
param: { type: "string", description: "Parameter description" }
|
||||
},
|
||||
required: ["param"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
if (request.params.name === "tool_name") {
|
||||
const { param } = request.params.arguments;
|
||||
const result = await performOperation(param);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2)
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error(`Unknown tool: ${request.params.name}`);
|
||||
});
|
||||
|
||||
// Start server with STDIO transport
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
|
||||
// CRITICAL: Never console.log() in STDIO mode!
|
||||
console.error("Server running on stdio");
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
```
|
||||
|
||||
## Python Server Template (FastMCP)
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
import os
|
||||
|
||||
# Initialize server
|
||||
mcp = FastMCP("server-name")
|
||||
|
||||
@mcp.tool()
|
||||
async def tool_name(param: str) -> str:
|
||||
"""
|
||||
Description of what this tool does.
|
||||
|
||||
Args:
|
||||
param: Parameter description
|
||||
|
||||
Returns:
|
||||
Result description
|
||||
"""
|
||||
result = await perform_operation(param)
|
||||
return str(result)
|
||||
|
||||
@mcp.resource("resource://template/{id}")
|
||||
async def get_resource(id: str) -> str:
|
||||
"""Get resource by ID."""
|
||||
return f"Resource content for {id}"
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run()
|
||||
```
|
||||
|
||||
## Key Implementation Patterns
|
||||
|
||||
### 1. Tool Definition
|
||||
- Clear, descriptive names
|
||||
- Comprehensive descriptions (AI uses this!)
|
||||
- Strong typing with Zod/type hints
|
||||
- Proper error handling
|
||||
|
||||
### 2. Resource Patterns
|
||||
- URI templates for dynamic resources
|
||||
- Efficient data fetching (avoid heavy computation)
|
||||
- Proper MIME types
|
||||
|
||||
### 3. Logging Rules
|
||||
- **STDIO servers**: NEVER use console.log/print (corrupts JSON-RPC)
|
||||
- Use console.error / logging.error (stderr is safe)
|
||||
- **HTTP servers**: stdout is safe
|
||||
|
||||
## Output
|
||||
|
||||
Fully implemented server with requested capabilities
|
||||
|
||||
## Transition
|
||||
|
||||
Proceed to Phase 4 (Environment & Security)
|
||||
@@ -0,0 +1,61 @@
|
||||
# Phase 4: Environment & Security
|
||||
|
||||
**Purpose**: Secure secrets and configure environment
|
||||
|
||||
## Generate .env.example
|
||||
|
||||
```bash
|
||||
# API Keys and Secrets
|
||||
API_KEY=your_api_key_here
|
||||
DATABASE_URL=postgresql://user:pass@localhost:5432/db
|
||||
|
||||
# Server Configuration
|
||||
PORT=3000
|
||||
LOG_LEVEL=info
|
||||
```
|
||||
|
||||
## Generate .gitignore
|
||||
|
||||
```
|
||||
# Dependencies
|
||||
node_modules/
|
||||
.venv/
|
||||
__pycache__/
|
||||
|
||||
# Build outputs
|
||||
build/
|
||||
dist/
|
||||
*.pyc
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
- ✓ Never commit .env files
|
||||
- ✓ Use environment variables for all secrets
|
||||
- ✓ Validate all inputs with schemas
|
||||
- ✓ Implement proper error handling (don't leak internals)
|
||||
- ✓ Use HTTPS for HTTP transport servers
|
||||
|
||||
## Output
|
||||
|
||||
Secure configuration with secrets management
|
||||
|
||||
## Transition
|
||||
|
||||
Proceed to Phase 5 (Claude Desktop Integration)
|
||||
@@ -0,0 +1,60 @@
|
||||
# Phase 5: Claude Desktop Integration
|
||||
|
||||
**Purpose**: Configure server in Claude Desktop for immediate use
|
||||
|
||||
## Configuration Location
|
||||
|
||||
- **macOS/Linux**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
||||
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
||||
|
||||
## TypeScript Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"server-name": {
|
||||
"command": "node",
|
||||
"args": ["/absolute/path/to/mcp-server-name/build/index.js"],
|
||||
"env": {
|
||||
"API_KEY": "your_api_key_here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Python Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"server-name": {
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"--directory",
|
||||
"/absolute/path/to/mcp-server-name",
|
||||
"run",
|
||||
"main.py"
|
||||
],
|
||||
"env": {
|
||||
"API_KEY": "your_api_key_here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Critical Requirements
|
||||
|
||||
- ✅ **Use ABSOLUTE paths** (not relative like `./` or `~/`)
|
||||
- ✅ Run `npm run build` before testing (TypeScript)
|
||||
- ✅ Completely restart Claude Desktop (Cmd+Q on macOS)
|
||||
- ✅ Valid JSON syntax (check with `python -m json.tool`)
|
||||
|
||||
## Output
|
||||
|
||||
Complete Claude Desktop configuration with restart instructions
|
||||
|
||||
## Transition
|
||||
|
||||
Proceed to Phase 6 (Testing & Validation)
|
||||
@@ -0,0 +1,60 @@
|
||||
# Phase 6: Testing & Validation
|
||||
|
||||
**Purpose**: Verify server works correctly before deployment
|
||||
|
||||
## Testing Workflow
|
||||
|
||||
### 1. Build Check (TypeScript)
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
# Should complete without errors
|
||||
# Verify build/index.js exists
|
||||
```
|
||||
|
||||
### 2. MCP Inspector Testing
|
||||
|
||||
```bash
|
||||
# Install MCP Inspector
|
||||
npx @modelcontextprotocol/inspector node build/index.js
|
||||
|
||||
# Or for Python
|
||||
npx @modelcontextprotocol/inspector uv run main.py
|
||||
```
|
||||
|
||||
- Opens browser interface to test tools/resources
|
||||
- Validates schemas and responses
|
||||
- Great for debugging before Claude integration
|
||||
|
||||
### 3. Claude Desktop Integration Test
|
||||
|
||||
- Add to claude_desktop_config.json
|
||||
- Completely restart Claude Desktop
|
||||
- Check logs: `~/Library/Logs/Claude/mcp*.log`
|
||||
- Look for server in "🔌" (attachments) menu
|
||||
|
||||
### 4. Functional Testing in Claude
|
||||
|
||||
Test with natural language queries:
|
||||
- "Use [server-name] to [perform action]"
|
||||
- "Can you [tool description]?"
|
||||
- Verify tool appears in suggestions
|
||||
- Check response accuracy
|
||||
|
||||
## Debugging Common Issues
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| Server not detected | Invalid path | Use absolute path, verify file exists |
|
||||
| Tools don't appear | Build not run | Run `npm run build` |
|
||||
| "Server error" | stdout logging | Remove console.log, use console.error |
|
||||
| Connection timeout | Server crash | Check mcp-server-NAME.log for errors |
|
||||
| Invalid config | JSON syntax | Validate JSON, check quotes/commas |
|
||||
|
||||
## Output
|
||||
|
||||
Validated, working MCP server with test results
|
||||
|
||||
## Transition
|
||||
|
||||
Proceed to Phase 7 (Documentation & Handoff)
|
||||
@@ -0,0 +1,97 @@
|
||||
# Phase 7: Documentation & Handoff
|
||||
|
||||
**Purpose**: Provide user with complete documentation and next steps
|
||||
|
||||
## Generate README.md
|
||||
|
||||
```markdown
|
||||
# MCP Server: [Name]
|
||||
|
||||
## Description
|
||||
[What this server does and why it's useful]
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Tools
|
||||
- **tool_name**: Description of what it does
|
||||
- Parameters: param1 (type) - description
|
||||
- Returns: description
|
||||
|
||||
### Resources
|
||||
- **resource://pattern/{id}**: Description
|
||||
|
||||
### Prompts
|
||||
- **prompt_name**: Description
|
||||
|
||||
## Setup
|
||||
|
||||
### Prerequisites
|
||||
- Node.js 18+ / Python 3.10+
|
||||
- Claude Desktop or MCP-compatible client
|
||||
|
||||
### Installation
|
||||
|
||||
1. Clone/download this server
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
npm install && npm run build
|
||||
# OR
|
||||
uv sync
|
||||
```
|
||||
|
||||
3. Configure environment:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env with your credentials
|
||||
```
|
||||
|
||||
4. Add to Claude Desktop config (see Phase 5)
|
||||
|
||||
5. Restart Claude Desktop completely
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Example 1: [Use Case]
|
||||
Query: "[Natural language query]"
|
||||
Expected: [What happens]
|
||||
|
||||
## Development
|
||||
|
||||
### Running Locally
|
||||
```bash
|
||||
npm run watch # Auto-rebuild on changes
|
||||
```
|
||||
|
||||
### Testing with MCP Inspector
|
||||
```bash
|
||||
npx @modelcontextprotocol/inspector node build/index.js
|
||||
```
|
||||
|
||||
### Debugging
|
||||
Logs location: `~/Library/Logs/Claude/mcp-server-[name].log`
|
||||
|
||||
## Security Notes
|
||||
- Never commit .env file
|
||||
- Rotate API keys regularly
|
||||
- Validate all inputs
|
||||
```
|
||||
|
||||
## Provide Next Steps
|
||||
|
||||
```markdown
|
||||
## Next Steps
|
||||
|
||||
1. ✅ Server code generated at: [path]
|
||||
2. ⬜ Review and customize tool implementations
|
||||
3. ⬜ Add your API keys to .env
|
||||
4. ⬜ Run build: `npm run build` or test with `uv run`
|
||||
5. ⬜ Test with MCP Inspector
|
||||
6. ⬜ Add to Claude Desktop config
|
||||
7. ⬜ Restart Claude Desktop
|
||||
8. ⬜ Test with natural language queries
|
||||
9. ⬜ Iterate and enhance based on usage
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Complete documentation and clear path to production use
|
||||
Reference in New Issue
Block a user