Agent skill
mcp-builder
Guide for building Model Context Protocol (MCP) servers - tool definitions, resource handling, transport protocols, and testing. Auto-triggers when working with MCP.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/mcp-builder-bigdegenenergy-open-cloud-ops
SKILL.md
MCP Builder Skill
MCP Architecture
Core Concepts
| Concept | Description |
|---|---|
| Server | Exposes tools and resources to AI clients |
| Tool | A function the AI can call (with input schema) |
| Resource | Read-only data the AI can access (files, URLs) |
| Prompt | Reusable prompt templates |
| Transport | Communication layer (stdio or SSE) |
Transport Protocols
| Transport | Use Case | Pros | Cons |
|---|---|---|---|
| stdio | Local CLI tools, Claude Code | Simple, fast, secure | Local only |
| SSE | Remote/web servers | Network accessible | More complex setup |
Building a Python MCP Server
Project Setup
uv init my-mcp-server
cd my-mcp-server
uv add mcp
Minimal Server
# server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def search_docs(query: str, limit: int = 5) -> str:
"""Search documentation by keyword.
Args:
query: Search query string
limit: Maximum results to return
"""
results = do_search(query, limit)
return "\n".join(f"- {r.title}: {r.snippet}" for r in results)
@mcp.resource("docs://{topic}")
def get_doc(topic: str) -> str:
"""Get documentation for a specific topic."""
return load_doc(topic)
@mcp.prompt()
def summarize_prompt(content: str) -> str:
"""Create a summarization prompt."""
return f"Summarize the following content:\n\n{content}"
if __name__ == "__main__":
mcp.run()
Tool Design Best Practices
# GOOD: Clear name, typed params, docstring with Args
@mcp.tool()
def get_user_orders(
user_id: str,
status: str = "all",
limit: int = 10,
) -> str:
"""Fetch orders for a specific user.
Args:
user_id: The user's unique identifier
status: Filter by order status (all, pending, shipped, delivered)
limit: Maximum number of orders to return (1-100)
"""
...
# BAD: Vague name, no types, no docs
@mcp.tool()
def get_data(params):
...
Tool Patterns
| Pattern | When to Use |
|---|---|
| Single-purpose tools | Always preferred - one tool, one job |
| Typed parameters | Always - gives the AI clear input schema |
| Descriptive docstrings | Always - AI reads these to understand tool purpose |
| String return values | Default - return formatted text |
| Error messages in return | Prefer over raising exceptions |
Building a TypeScript MCP Server
Project Setup
npx @anthropic-ai/create-mcp-server my-server
cd my-server
npm install
Minimal Server
import { McpServer } from "@anthropic-ai/sdk/mcp";
const server = new McpServer({
name: "my-server",
version: "1.0.0",
});
server.tool(
"search_docs",
"Search documentation by keyword",
{
query: { type: "string", description: "Search query" },
limit: { type: "number", description: "Max results", default: 5 },
},
async ({ query, limit }) => {
const results = await doSearch(query, limit);
return {
content: [{ type: "text", text: formatResults(results) }],
};
},
);
server.resource("docs", "docs://{topic}", async (uri) => {
const topic = uri.pathname;
return {
contents: [{ uri: uri.href, text: await loadDoc(topic) }],
};
});
server.run();
Configuration
Claude Code Integration (.mcp.json)
{
"mcpServers": {
"my-server": {
"command": "uv",
"args": ["run", "--directory", "/path/to/server", "server.py"],
"env": {
"API_KEY": "..."
}
}
}
}
Claude Desktop Integration
{
"mcpServers": {
"my-server": {
"command": "npx",
"args": ["-y", "my-mcp-server"],
"env": {}
}
}
}
Testing MCP Servers
Manual Testing with MCP Inspector
# Install inspector
npx @anthropic-ai/mcp-inspector
# Connect to your server
npx @anthropic-ai/mcp-inspector uv run server.py
Unit Testing Tools
import pytest
from server import mcp
@pytest.mark.asyncio
async def test_search_docs():
result = await mcp.call_tool("search_docs", {
"query": "authentication",
"limit": 3,
})
assert len(result) > 0
assert "authentication" in result.lower()
@pytest.mark.asyncio
async def test_get_doc():
result = await mcp.read_resource("docs://getting-started")
assert "Getting Started" in result
Common MCP Server Patterns
Database Access
# IMPORTANT: Use a read-only database user/role for security.
# String-based SQL validation (e.g., startswith("SELECT")) is NOT
# sufficient — it can be bypassed with CTEs, stacked queries, etc.
from sqlalchemy import create_engine, text
# Connection uses a read-only database role
read_engine = create_engine(READ_ONLY_DATABASE_URL)
@mcp.tool()
def query_database(sql: str) -> str:
"""Run a read-only SQL query against the database.
Args:
sql: SQL SELECT query. Connection uses a read-only DB role.
"""
with read_engine.connect() as conn:
results = conn.execute(text(sql))
return format_as_table(results)
External API Wrapper
@mcp.tool()
def search_github_issues(
repo: str,
query: str,
state: str = "open",
) -> str:
"""Search GitHub issues in a repository.
Args:
repo: Repository in owner/name format
query: Search query for issue titles and bodies
state: Issue state filter (open, closed, all)
"""
issues = github_client.search_issues(repo, query, state)
return "\n".join(
f"#{i.number} [{i.state}] {i.title}" for i in issues
)
File System Access
@mcp.tool()
def read_project_file(path: str) -> str:
"""Read a file from the project directory.
Args:
path: Relative path from project root (no .. traversal allowed)
"""
safe_path = resolve_safe_path(PROJECT_ROOT, path)
return safe_path.read_text()
Security Considerations
- Validate all tool inputs (never trust AI-provided parameters)
- Use read-only database connections where possible
- Restrict file access to project directories (prevent path traversal)
- Never expose secrets in tool responses
- Rate limit expensive operations
- Log all tool invocations for audit
Activation Triggers
This skill auto-activates when prompts contain:
- "mcp", "model context protocol", "mcp server"
- "fastmcp", "mcp tool", "mcp resource"
- ".mcp.json", "mcp config", "mcp inspector"
Integration
- @ai-engineer agent: LLM application development
- api-design skill: Tool API design patterns
- security-review skill: Securing MCP servers
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?