# Mcp Creator

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-wyattowalsh-agents-mcp-creator`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [wyattowalsh](https://agentstack.voostack.com/s/wyattowalsh)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [wyattowalsh](https://github.com/wyattowalsh)
- **Source:** https://github.com/wyattowalsh/agents/tree/main/skills/mcp-creator
- **Website:** https://agents.w4w.dev

## Install

```sh
agentstack add skill-wyattowalsh-agents-mcp-creator
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# MCP Creator — FastMCP v3

Build production-ready MCP servers with FastMCP v3 (3.0.0rc2). This skill guides through research, scaffolding, implementation, testing, and deployment. All first-party output follows this repo's conventions: `mcp//` directory, `fastmcp.json` config, exact `uv` workspace member, imperative voice, kebab-case naming. Reserve `mcp/servers/` for machine-local third-party MCP installs; it is gitignored.

**Target:** FastMCP v3 rc2 — Provider/Transform architecture, 14 built-in middleware, OAuth 2.1, server composition, component versioning, structured output, background tasks, elicitation, sampling.

**Input:** `$ARGUMENTS` — the service, API, or capability to wrap as an MCP server.

---

## Dispatch

Route `$ARGUMENTS` to the appropriate mode:

| $ARGUMENTS pattern | Mode | Start at |
|---------------------|------|----------|
| Service/API name (e.g., "GitHub", "Stripe") | **New server** | Phase 1 |
| Path to existing first-party server (e.g., `mcp/myserver/`) | **Extend** | Phase 3 |
| OpenAPI spec URL or file path | **Convert OpenAPI** | Phase 2 (scaffold) then load `references/server-composition.md` §6 |
| FastAPI app to convert | **Convert FastAPI** | Phase 2 (scaffold) then load `references/server-composition.md` §7 |
| Error message or "debug" + description | **Debug** | Load `references/common-errors.md`, match symptom |
| "learn" or conceptual question | **Learn** | Load relevant reference file, explain |
| Empty | **Gallery / help overview** | Show available modes and example invocations |

---

## Consult Live Documentation

Before implementation, fetch current FastMCP v3 docs. Bundled references capture rc2 — live docs may be newer.

1. **Context7** — `resolve-library-id` for "fastmcp", then `query-docs` for the topic.
2. **WebFetch** — `https://gofastmcp.com/llms-full.txt` — comprehensive LLM-optimized docs.
3. **WebSearch fallback** — `site:gofastmcp.com ` for specific topics.

If live docs contradict bundled references, **live docs win**. Always fetch live docs first — API details shift between rc2 and stable.

---

## Phase 1: Research & Plan

**Goal:** Understand the target service and design the MCP server's tool/resource/prompt inventory.

**Load:** `references/tool-design.md` (naming, descriptions, parameter design, 8 tool patterns)

### 1.1 Understand the Target

- Read any documentation, SDK, or API reference for the target service.
- Identify the core operations users need (CRUD, search, status, config).
- Note authentication requirements (API keys, OAuth, tokens).
- Check for existing MCP servers for this service — avoid duplicating work.

### 1.2 Architecture Checklist

Answer before proceeding:

- [ ] Auth needed? (API key → env var, OAuth → HTTP transport, none → stdio)
- [ ] Transport? (stdio for local, Streamable HTTP for remote/multi-client)
- [ ] Background tasks? (long-running operations → `task=True`, requires `fastmcp[tasks]`)
- [ ] OpenAPI spec available? (→ `OpenAPIProvider` or `FastMCP.from_openapi()`)
- [ ] Multiple domains? (→ composed servers with `mount()` + namespaces)

### 1.3 Design Tool Inventory

Plan 5-15 tools per server. For each tool, define:

| Field | Requirement |
|-------|-------------|
| Name | `snake_case`, `verb_noun` format, max 64 chars |
| Description | 3-5 sentences: WHAT, WHEN to use, WHEN NOT, WHAT it returns |
| Parameters | Each with type, description, constraints via `Annotated[type, Field(...)]` |
| Annotations | `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint` |
| Error cases | What `ToolError` messages to raise for expected failures |

### 1.4 Design Resources and Prompts

- **Resources** for static/slow-changing data (config, schemas, status). URI-addressed.
- **Prompts** for reusable message templates that guide LLM behavior.
- See `references/fastmcp-v3-api.md` §6-7 for URI patterns and prompt design.

### 1.5 Plan Architecture

Decide on composition strategy:

- **Single server** — Most cases. One `FastMCP` instance with all tools.
- **Composed servers** — Large APIs. Domain servers mounted via `mount()` with namespaces.
- **Provider-based** — Dynamic tool registration. `FileSystemProvider` or custom `Provider`.
- **OpenAPI conversion** — Auto-generate tools from OpenAPI spec. `OpenAPIProvider` or `FastMCP.from_openapi()`.

See `references/server-composition.md` for patterns.

### 1.6 Deliverable

Produce a tool/resource/prompt inventory table before proceeding:

```markdown
| Component | Type | Name | Description (brief) |
|-----------|------|------|---------------------|
| Tool | tool | search_issues | Search GitHub issues by query |
| Resource | resource | config://settings | Current server configuration |
| Prompt | prompt | summarize_pr | Summarize a pull request for review |
```

---

## Phase 2: Scaffold

**Goal:** Create the project directory, tests, and configure dependencies.

### 2.1 Create Project Structure

Run `python scripts/scaffold_mcp.py ` to scaffold:

```
mcp//
├── server.py          # FastMCP entry point
├── pyproject.toml     # uv project config
├── fastmcp.json       # FastMCP CLI config
└── tests/
    ├── conftest.py    # Client fixture, mock Context
    └── test_server.py # Automated test suite
```

Customize the scaffold:
- Set server name in `server.py`: `mcp = FastMCP("name")`.
- Set package name in `pyproject.toml`: `name = "mcp-"`.
- Update description in `pyproject.toml`.
- Add service-specific dependencies to both `pyproject.toml` and `fastmcp.json`.

### 2.2 Add Test Configuration

Add to `pyproject.toml`:

```toml
[tool.pytest.ini_options]
asyncio_mode = "auto"

[dependency-groups]
dev = ["pytest>=8", "pytest-asyncio>=0.25"]
```

Create `tests/conftest.py` — see `references/testing.md` §4 for the complete template.

### 2.3 Configure and Verify

- Ensure root `pyproject.toml` has `[tool.uv.workspace] members = ["mcp/"]`.
- Run `cd mcp/ && uv sync` to install dependencies.
- Verify: `uv run python -c "from server import mcp; print(mcp.name)"`.

Note: `python scripts/check.py` validates this skill only, NOT MCP servers. Use the import check above for MCP server validation.

---

## Phase 3: Implement

**Goal:** Build all tools, resources, and prompts from the Phase 1 inventory.

**Load:** `references/fastmcp-v3-api.md` (full API surface), `references/tool-design.md` (patterns)

### 3.1 Server Setup

```python
from fastmcp import FastMCP, Context

mcp = FastMCP(
    "server-name",
    instructions="Description of what this server provides and when to use it.",
)
```

For shared resources (HTTP clients, DB connections), add a composable lifespan:

```python
from fastmcp.server.lifespan import lifespan

@lifespan
async def http_lifespan(server):
    import httpx
    async with httpx.AsyncClient() as client:
        yield {"http": client}

mcp = FastMCP("server-name", lifespan=http_lifespan)
# Access in tools: ctx.lifespan_context["http"]
```

Combine lifespans with `|`: `mcp = FastMCP("name", lifespan=db_lifespan | cache_lifespan)`

### 3.2 Implement Tools

For each tool in the inventory, follow this pattern:

```python
from typing import Annotated
from pydantic import Field
from fastmcp import Context
from fastmcp.exceptions import ToolError

@mcp.tool(
    annotations={
        "readOnlyHint": True,
        "openWorldHint": True,
    },
)
async def search_items(
    query: Annotated[str, Field(description="Search term to find items.", min_length=1)],
    limit: Annotated[int, Field(description="Max results to return.", ge=1, le=100)] = 10,
    ctx: Context | None = None,
) -> dict:
    """Search for items matching a query.

    Use this tool when you need to find items by keyword. Returns a list of
    matching items with their IDs and titles. Use the limit parameter to
    control result count. Does not search archived items.

    Returns a dictionary with 'items' list and 'total' count.
    """
    if ctx:
        await ctx.info(f"Searching for: {query}")
    try:
        results = await do_search(query, limit)
        return {"items": results, "total": len(results)}
    except ServiceError as e:
        raise ToolError(f"Search failed: {e}")
```

**Key rules for every tool:**
- `Annotated[type, Field(description=...)]` on EVERY parameter.
- Verbose docstring: WHAT, WHEN to use, WHEN NOT, WHAT it returns.
- `ToolError` for expected failures (always visible to client).
- `annotations` dict on every tool — at minimum `readOnlyHint`.
- `ctx: Context | None = None` for testability without MCP runtime.

See `references/tool-design.md` §9 for 8 complete tool patterns (sync, async+Context, stateful, external API, data processing, dependency-injected, sampling, elicitation).

### 3.3 Implement Resources

```python
import json

@mcp.resource("config://settings", mime_type="application/json")
async def get_settings() -> str:
    """Current server configuration."""
    return json.dumps(settings)

@mcp.resource("users://{user_id}/profile")
async def get_user_profile(user_id: str) -> str:
    """User profile by ID."""
    return json.dumps(await fetch_profile(user_id))
```

See `references/fastmcp-v3-api.md` §6 for URI templates, query params, wildcards, and class-based resources.

### 3.4 Implement Prompts

```python
from fastmcp.prompts import Message

@mcp.prompt
def summarize_pr(pr_number: int, detail_level: str = "brief") -> list[Message]:
    """Generate a prompt to summarize a pull request."""
    return [Message(
        role="user",
        content=f"Summarize PR #{pr_number} at {detail_level} detail level.",
    )]
```

### 3.5 Composition (if applicable)

For large servers, split into domain modules and compose. See `references/server-composition.md`.

```python
from fastmcp import FastMCP
from .issues import issues_server
from .repos import repos_server

mcp = FastMCP("github")
mcp.mount(issues_server, namespace="issues")
mcp.mount(repos_server, namespace="repos")
```

### 3.6 Auth (if applicable)

Load `references/auth-and-security.md` when implementing authentication.

- **stdio transport:** No MCP-level auth. Use env vars for backend API keys.
- **HTTP transport:** OAuth 2.1 via `JWTVerifier`, `GitHubProvider`, or `RemoteAuthProvider`.
- **Per-tool auth:** `@mcp.tool(auth=require_scopes("admin"))`.
- **Dual-mode pattern:** `common.py` with shared tools, separate auth/no-auth entry points.

---

## Phase 4: Test

**Goal:** Verify all components work correctly with deterministic tests.

**Load:** `references/testing.md` (patterns, 18-item checklist)

### 4.1 Write Tests

Use the in-memory `Client` — no network, no subprocess:

```python
import pytest
from fastmcp import Client
from server import mcp

@pytest.fixture
async def client():
    async with Client(mcp) as c:
        yield c

async def test_search_items(client):
    result = await client.call_tool("search_items", {"query": "test"})
    assert result.data is not None
    assert not result.is_error

async def test_list_tools(client):
    tools = await client.list_tools()
    names = [t.name for t in tools]
    assert "search_items" in names
```

### 4.2 Test Categories

Cover all 8 categories from `references/testing.md`:

1. **Discovery** — `list_tools()`, `list_resources()`, `list_prompts()` return expected names.
2. **Happy path** — Each tool with valid input returns expected output.
3. **Error handling** — Invalid input produces `ToolError`, not crashes.
4. **Edge cases** — Empty strings, boundary values, Unicode, large inputs.
5. **Resources** — `read_resource(uri)` returns correct content and MIME type.
6. **Prompts** — `get_prompt(name, args)` returns expected messages.
7. **Integration** — Tool chains, lifespan setup/teardown.
8. **Concurrent** — Multiple simultaneous calls don't interfere.

### 4.3 Interactive Testing

```bash
# MCP Inspector (browser-based)
fastmcp dev inspector mcp//server.py

# CLI testing
fastmcp list mcp//server.py
fastmcp call mcp//server.py search_items '{"query": "test"}'
```

### 4.4 Run Tests

```bash
cd mcp/ && uv run pytest -v
```

---

## Phase 5: Deploy & Configure

**Goal:** Make the server available to MCP clients.

**Load:** `references/deployment.md` (transports, client configs, Docker)

### 5.1 Select Transport

| Scenario | Transport | Command |
|----------|-----------|---------|
| Local / Claude Desktop | stdio | `fastmcp run server.py` |
| Remote / multi-client | Streamable HTTP | `fastmcp run server.py --transport http --port 8000` |
| Development | Inspector | `fastmcp dev inspector server.py` |

### 5.2 Generate Client Config

Add to client config (Claude Desktop, Claude Code, Cursor):

```json
{
  "mcpServers": {
    "server-name": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/mcp/", "fastmcp", "run", "server.py"]
    }
  }
}
```

See `references/deployment.md` §7 for complete configs per client.

### 5.3 Validate

MCP server validation (skill check.py does NOT check MCP servers):

```bash
# Import check
uv run python -c "from server import mcp; print(mcp.name)"

# List registered components
fastmcp list mcp//server.py

# Interactive inspection
fastmcp dev inspector mcp//server.py
```

### 5.4 Quality Checklist

Before declaring the server complete:

- [ ] Every tool has `Annotated` + `Field(description=...)` on all parameters
- [ ] Every tool has a verbose docstring (WHAT, WHEN, WHEN NOT, RETURNS)
- [ ] Every tool has `annotations` (at minimum `readOnlyHint`)
- [ ] Every tool uses `ToolError` for expected failures
- [ ] No `print()` or `stdout` writes in any tool
- [ ] Resources have correct URI schemes and MIME types
- [ ] Tests pass: `uv run pytest -v`
- [ ] MCP Inspector shows all components correctly
- [ ] `fastmcp.json` lists all required dependencies
- [ ] `pyproject.toml` has correct metadata and dependencies
- [ ] No deprecated constructor kwargs (removed in rc1)
- [ ] Custom routes have manual auth if sensitive
- [ ] `mask_error_details=True` set for production deployment

---

## Reference File Index

Load these files on demand during the relevant phase. Do NOT load all at once.

| File | Content | Load during |
|------|---------|-------------|
| `references/fastmcp-v3-api.md` | Complete v3 API surface: constructor, decorators, Context, return types, resources, prompts, providers, transforms, 14 middleware, background tasks, visibility, v2→v3 changes | Phase 3 |
| `references/tool-design.md` | LLM-optimized naming, descriptions, parameters, annotations, error handling, 8 tool patterns, structured output, response patterns, anti-patterns | Phase 1, 3 |
| `references/server-composition.md` | mount(), import_server(), proxy, FileSystemProvider, OpenAPI (OpenAPIProvider + from_openapi), FastAPI conversion, custom providers, transforms, gateway pattern, DRY registration | Phase 1, 3 |
| `references/testing.md` | In-memory Client, pytest setup, conftest.py template, 8 test categories, MCP Inspector, CLI testing, 18-item checklist | Phase 4 |
| `references/auth-and-security.md` | OAuth 2.1, JWTVerifier, per-component auth, custom auth checks, session-based visibility, custom route auth bypass, SSRF prevention, dual-mode pattern, 15 security rules | Phase 3 |
| `references/deployment.md` | Transports, FastMCP CLI, ASGI, custom routes, client configs, fastmcp.json schema, Docker, background task workers, production checklist | Phase 5 |
| `references/resources-and-prompts.md` | Resources (static, dynamic, binary), prompts (single/multi-message), resource vs tool guidance, testing patterns | Phase 3 |
| `references/common-errors.md` | 34 errors: symptom → cause → v3-updated fix, quick-fix lookup table | Debug mode |
| `references/quick-reference.md` | Minimal examples: server, tool, resource, prompt, lifespan, test, run | Quick start |

---

## Critical Rules

These are non-negotiable. Violating any of these produces broken MCP servers.

1. **No stdout.** Never use `print()` or write to stdout in tools/resources/prompts. Stdout is the MCP transport. Use `ctx.info()`, `ctx.warning()`, `ctx.error()` for logging.

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [wyattowalsh](https://github.com/wyattowalsh)
- **Source:** [wyattowalsh/agents](https://github.com/wyattowalsh/agents)
- **License:** MIT
- **Homepage:** https://agents.w4w.dev

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-wyattowalsh-agents-mcp-creator
- Seller: https://agentstack.voostack.com/s/wyattowalsh
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
