mcp-builder
暂无简介
- License 许可
- MIT
- 最近更新
- 2026-11-12
- Stars
- ★ 2
- Forks
- 0
03 SKILL.md 正文
MCP Builder Skill — Goliath Fleet Standard
FastMCP 3.2.4 | Starlette 1.0 | Sandra's Fleet | 2026-05-04
INSTALLATION (Claude Desktop skills):
Copy this file to: C:\Users<user>\AppData\Roaming\Claude\skills\mcp-builder\SKILL.md
OR place at: D:\Dev\repos\mcp-central-docs\skills\mcp-builder\SKILL.md
and symlink / reference from Claude Desktop skills config.
This skill auto-loads when Claude detects MCP server build/scaffold/port tasks.
TRIGGER CONDITIONS
Load this skill when the task involves any of:
- "create/scaffold/build a new MCP server"
- "add a tool/endpoint to [repo]-mcp"
- "what port should I use"
- "start.ps1 for new server"
- "FastMCP" appearing in a coding task
- "write a SKILL.md" or "create a skill"
- Dockerfile for a Python MCP container
FLEET IDENTITY
- GitHub: sandraschi
- Repos root:
D:\Dev\repos\ - Fleet info depot (aka "mcd"):
D:\Dev\repos\mcp-central-docs\ - Port registry:
D:\Dev\repos\mcp-central-docs\operations\WEBAPP_PORTS.md - Fleet index:
D:\Dev\repos\mcp-central-docs\projects\FLEET_INDEX.md - Standards:
D:\Dev\repos\mcp-central-docs\standards\
Before creating any new MCP server: read WEBAPP_PORTS.md to find the next free port pair. Never guess. Never use 3000/5000/5173/8000/8080.
FASTMCP 3.2.4 — CANONICAL PATTERNS
SOTA as of 2026-07-17
fastmcp>=3.4.4,<4
Key 3.2 additions over 3.1:
GenerativeUIprovider,prefab-ui>=0.18.0@mcp.tool(app=True)returnsPrefabAppdirectly (not wrapped inToolResult)mcp.http_app(path="/")replacesmcp.sse_app()for ASGI mountingfastmcp dev appsbrowser preview- Security fixes: SSRF/path traversal (GHSA-vv7q-7jx5-f767), PyJWT CVE-2026-32597
Key 3.1 additions (still current):
- CodeMode (BM25 tool discovery) —
@mcp.tool()withdescription=auto-indexes @mcp.prompt()for prompt templates@mcp.resource()for resource endpointsctx.sample()for agentic sampling (SEP-1577)- Prefab UI DSL (Python → React)
SearchToolsstandalone transform- Lazy imports
Minimal server template
"""[repo-name] MCP Server — [one line description]."""
from fastmcp import FastMCP, Context
from starlette.applications import Starlette
from starlette.routing import Mount
import uvicorn
mcp = FastMCP("[ServerName]", version="0.1.0")
@mcp.tool()
async def my_tool(param: str, ctx: Context) -> dict:
"""Tool description — appears in CodeMode BM25 index."""
return {"result": param}
# Mount MCP under /mcp on the Starlette app (Starlette 1.0 pattern)
app = Starlette(routes=[Mount("/mcp", mcp.http_app(path="/"))])
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=BACKEND_PORT)
NEVER do this (anti-patterns)
# WRONG — FastMCP 3.1 API, broken in 3.2
StreamingResponse(mcp.sse_app())
# WRONG — FastAPI/Pydantic (fleet standard is Starlette + plain dicts)
from fastapi import FastAPI
from pydantic import BaseModel
# WRONG — old decorator-call pattern (works but verbose)
mcp.tool()(my_function)
# WRONG — task=True on tool decorators (invalid, causes startup error)
@mcp.tool(task=True)
Prefab UI (3.2)
from fastmcp.contrib.prefab import PrefabApp, DataTable, Dashboard, Metric
@mcp.tool(app=True)
async def my_dashboard() -> PrefabApp:
return Dashboard(title="Status", metrics=[
Metric(label="Uptime", value="99.9%"),
])
STARLETTE STANDARD (mandatory for new webapps)
All new MCP server webapps use Starlette 1.0 + plain dicts. No FastAPI. No Pydantic models.
from starlette.applications import Starlette
from starlette.routing import Route, Mount
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.staticfiles import StaticFiles
async def health(request: Request) -> JSONResponse:
return JSONResponse({"status": "healthy", "version": "0.1.0"})
async def api_status(request: Request) -> JSONResponse:
data = await request.json()
return JSONResponse({"ok": True, "received": data})
app = Starlette(routes=[
Route("/health", health),
Route("/api/status", api_status, methods=["POST"]),
Mount("/mcp", mcp.http_app(path="/")),
Mount("/", StaticFiles(directory="dist", html=True), name="static"),
])
PORT ALLOCATION
Mandatory: check D:\Dev\repos\mcp-central-docs\operations\WEBAPP_PORTS.md for next free pair.
Rules:
- Range: 10700–11000 only
- Frontend and backend ports MUST be adjacent (e.g., 10956/10957)
- Even-numbered preferred for backends
- After allocating: update WEBAPP_PORTS.md AND FLEET_INDEX.md
Current high-water mark (2026-05-04): 10963 (deepfang Grafana) Next available pair: 10964/10965 — verify against registry before using.
START.PS1 — NAKED-PC INSTALL STANDARD
Every new MCP server MUST have a start.ps1 that works on a fresh Windows clone.
<#
.SYNOPSIS
Start [repo-name] MCP server — naked-PC compliant.
Requires: uv, Node.js LTS, just (auto-installed via winget if missing)
#>
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
function Require-Command {
param([string]$cmd, [string]$wingetId = "")
if (-not (Get-Command $cmd -ErrorAction SilentlyContinue)) {
if ($wingetId) {
Write-Host "Installing $cmd via winget..."
winget install --id $wingetId -e --accept-source-agreements --accept-package-agreements
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH","Machine") + ";" +
[System.Environment]::GetEnvironmentVariable("PATH","User")
} else {
Write-Error "$cmd not found and no winget ID provided. Install manually."
exit 1
}
}
}
Require-Command "uv" "astral-sh.uv"
Require-Command "node" "OpenJS.NodeJS.LTS"
Require-Command "just" "Casey.Just"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Set-Location $ScriptDir
# Kill zombie processes on our ports
$BackendPort = 10964 # REPLACE with actual port
$FrontendPort = 10965 # REPLACE with actual port
@($BackendPort, $FrontendPort) | ForEach-Object {
$conn = Get-NetTCPConnection -LocalPort $_ -ErrorAction SilentlyContinue
if ($conn) { Stop-Process -Id $conn.OwningProcess -Force -ErrorAction SilentlyContinue }
}
# Install Python deps
& "C:\Users\<user>\.local\bin\uv.exe" sync
# Build frontend if dist missing
if (-not (Test-Path "webapp\dist\index.html")) {
Write-Host "Building frontend..."
Push-Location webapp
npm ci
npm run build
Pop-Location
}
# Start backend
Start-Process -NoNewWindow "C:\Users\<user>\.local\bin\uv.exe" -ArgumentList "run", "python", "-m", "src.server"
# Wait for backend readiness
$timeout = 30
$elapsed = 0
while ($elapsed -lt $timeout) {
try {
$resp = Invoke-WebRequest "http://localhost:$BackendPort/health" -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
if ($resp.StatusCode -eq 200) { break }
} catch {}
Start-Sleep 1
$elapsed++
}
Write-Host "Backend ready at http://localhost:$BackendPort"
Start-Process "http://localhost:$FrontendPort"
Also provide start.bat:
@echo off
cd /d "%~dp0"
powershell -ExecutionPolicy Bypass -File "%~dp0start.ps1"
UV + PYTHON — FULL PATHS
In subprocess/PowerShell context, uv is NOT on PATH. Always use full path:
C:\Users\<user>\.local\bin\uv.exe
Python:
C:\Users\<user>\AppData\Local\Programs\Python\Python313\python.exe
pyproject.toml minimum:
[project]
name = "repo-name-mcp"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"fastmcp>=3.4.4,<4",
"starlette>=1.0.0",
"uvicorn[standard]>=0.30.0",
"httpx>=0.27.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
DOCKER / CONTAINERS
When writing Dockerfiles for MCP containers:
FROM python:3.12-slim
WORKDIR /app
RUN pip install --no-cache-dir fastmcp>=3.4.4,<4 starlette>=1.0.0 uvicorn[standard]>=0.30.0
# Non-root user (security standard — uid 65530+, one per container)
RUN adduser --disabled-password --gecos "" --uid 65530 mcp
USER mcp
EXPOSE 10964
CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "10964"]
Non-root UIDs in use (deepfang):
- 65533 sanitizer
- 65532 worker Next available: 65531, 65530, etc.
TOOL DESIGN PATTERNS
Portmanteau (preferred for dense tool sets)
Single tool with op parameter instead of explosion of separate tools:
@mcp.tool()
async def my_ops(op: str, path: str = "", content: str = "") -> dict:
"""
Unified file operations.
op: read | write | list | delete
"""
if op == "read": ...
elif op == "write": ...
raise ValueError(f"Unknown op: {op}")
Agentic workflow (SEP-1577)
@mcp.tool()
async def my_agentic_workflow(goal: str, ctx: Context) -> str:
"""Multi-step workflow via FastMCP 3.2 sampling."""
result = await ctx.sample(
messages=goal,
system_prompt="You are a [domain] specialist...",
temperature=0.2,
max_tokens=1024,
)
return result.text
Safe-fail defaults
All tools that call external services must fail safely:
try:
resp = await client.get(url, timeout=10.0)
except Exception as e:
return {"success": False, "error": str(e)}
CLAUDE DESKTOP MCP CONFIG
Path: C:\Users\<user>\AppData\Roaming\Claude\claude_desktop_config.json
New stdio server entry:
"repo-name-mcp": {
"command": "C:\\Users\\sandr\\.local\\bin\\uv.exe",
"args": ["run", "--directory", "D:\\Dev\\repos\\repo-name-mcp", "python", "-m", "src.server"],
"env": {
"SOME_VAR": "value"
}
}
New HTTP/SSE server entry (for FastMCP 3.2 http_app):
"repo-name-mcp": {
"type": "sse",
"url": "http://localhost:10964/mcp/sse"
}
MCP logs: C:\Users\<user>\AppData\Local\Claude\Logs\mcp-server-{name}.log (pre-2026-08-21: AppData\Roaming\Claude\logs)
GIT OPERATIONS IN POWERSHELL
git -C <path> via splatting fails. Always use:
Push-Location "D:\Dev\repos\repo-name"
& "C:\Program Files\Git\cmd\git.exe" add .
& "C:\Program Files\Git\cmd\git.exe" commit -m "message"
Pop-Location
Never use && in PowerShell — use semicolons or separate statements.
FLEET INDEX + PORT REGISTRY UPDATES
After creating any new server, update both:
D:\Dev\repos\mcp-central-docs\projects\FLEET_INDEX.md— add row to tableD:\Dev\repos\mcp-central-docs\operations\WEBAPP_PORTS.md— add port rows
Fleet index row format:
| [repo-name](file:///D:/Dev/repos/repo-name) | MCP Server | Active | **Description (v0.1.0)** — FastMCP 3.2.4; N tools; brief feature list. Backend **XXXXX**, frontend **XXXXX**. |
MCPB PACKAGING
Fleet uses source-code-only packaging via Anthropic mcpb CLI:
mcpb validate # validate manifest
mcpb pack # create package
# Never use: mcpb init, mcpb publish
No bundled deps in packages. pyproject.toml is the dependency manifest.
ADVANCED MEMORY NOTES
After significant work on any MCP server, write a note:
memops:adn_notes(operation="write",
title="repo-name-YYYY-MM-DD-session",
folder="projects",
tags=["repo-name", "fastmcp", "mcp", "status", "priority"],
content="..."
)
Tag ALL notes: [project-name, technology, status, priority]
COMMON MISTAKES TO AVOID
| Mistake | Correct |
|---|---|
mcp.sse_app() |
mcp.http_app(path="/") |
@mcp.tool(task=True) |
@mcp.tool() |
from fastapi import FastAPI |
from starlette.applications import Starlette |
where uv in subprocess |
C:\Users\<user>\.local\bin\uv.exe |
git -C path splatting |
Push-Location path; git ... |
&& in PowerShell |
; or separate statements |
| Guessing port numbers | Read WEBAPP_PORTS.md first |
mkdir in PowerShell |
New-Item -ItemType Directory |
Mixing \ and / in Windows paths |
Always \ for Windows paths |
| Not adding to FLEET_INDEX | Always update after creating server |
04 同仓库更多 Skills
Docs Research
Use MCP Central Docs server to search, ask, and retrieve documentation (FastMCP, standards, packaging).
wrappee-drift
Read-only, single-repo audit of a repo's tool coverage against the software it wraps (its current real API/docs, not training-data memory) and against comparable/competing wrappers. Trigger when the user says "wrappee drift" followed by a repo name, "capability audit" followed by a repo name, or asks whether a repo is missing features the wrapped software or a competitor now has. Always scoped to one named repo per invocation -- never trigger this fleet-wide or unprompted; that is explicitly against the SOP. Do NOT trigger for internal fleet-standard compliance (that is drift-scan) or strategic worth/archive decisions (that is quality-check) -- this is specifically about the gap between the repo's tool list and the wrapped software's/competitors' actual current capabilities.
modules
暂无简介
mcp-standards
Use when developing MCP servers to access comprehensive standards for scaffolding, packaging, sampling, documentation, testing, error handling, monitoring, and CI/CD workflows.
webapp-cua-test
Run the pre-Tauri CUA click-through test (real browser, dev stack, OCR "Connected" wait, sidebar nav walk) for a fleet MCP server repo under D:\Dev\repos. Trigger when the user says "cua webapp test" or "webapp clickthrough" followed by a repo name, asks for an e2e click-through of a webapp, or asks whether a webapp boots and connects in a real browser. Not for the installed NSIS app (that is the nsis-build skill / cua-nsis-test) and not for DOM assertions (Playwright), and not for hunting fake data or dead buttons (fakefind).
ship
Final release gate for a fleet MCP server repo under D:\Dev\repos -- run all quality gates, build the release artifact, verify it, commit, push, and cut a GitHub release. Trigger this whenever the user says "ship it", "ship" followed by a repo name, "release" followed by a repo name, or asks to finalize and publish work that's already been done in a repo. This is the terminal step after assfix/nsis-build, not a substitute for them -- if the repo hasn't been assessed recently, say so before shipping rather than shipping blind.