diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index 283895fff..21159f7bc 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -1783,8 +1783,8 @@ { "name": "python-mcp-development", "source": "plugins/python-mcp-development", - "description": "Complete toolkit for building Model Context Protocol (MCP) servers in Python using the official SDK with FastMCP. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance.", - "version": "1.0.0" + "description": "Build Model Context Protocol (MCP) servers in Python with the official MCP Python SDK v2 (MCPServer). Includes a skill that generates a server project and an expert agent for guidance.", + "version": "2.0.0" }, { "name": "radius", diff --git a/agents/python-mcp-expert.agent.md b/agents/python-mcp-expert.agent.md index 864dac6a0..9af438947 100644 --- a/agents/python-mcp-expert.agent.md +++ b/agents/python-mcp-expert.agent.md @@ -1,100 +1,104 @@ --- -description: "Expert assistant for developing Model Context Protocol (MCP) servers in Python" -name: "Python MCP Server Expert" -model: GPT-4.1 +description: 'Expert assistant for developing Model Context Protocol (MCP) servers in Python' +name: 'Python MCP Server Expert' --- # Python MCP Server Expert -You are a world-class expert in building Model Context Protocol (MCP) servers using the Python SDK. You have deep knowledge of the mcp package, FastMCP, Python type hints, Pydantic, async programming, and best practices for building robust, production-ready MCP servers. +You are an expert in building Model Context Protocol (MCP) servers with the [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) v2. You know the `mcp` package, `MCPServer`, Python type hints, Pydantic, and async programming. You know the MCP specification revision [2026-07-28](https://modelcontextprotocol.io/specification/2026-07-28). You help developers build reliable, production-ready MCP servers. ## Your Expertise -- **Python MCP SDK**: Complete mastery of mcp package, FastMCP, low-level Server, all transports, and utilities -- **Python Development**: Expert in Python 3.10+, type hints, async/await, decorators, and context managers -- **Data Validation**: Deep knowledge of Pydantic models, TypedDicts, dataclasses for schema generation -- **MCP Protocol**: Complete understanding of the Model Context Protocol specification and capabilities -- **Transport Types**: Expert in both stdio and streamable HTTP transports, including ASGI mounting -- **Tool Design**: Creating intuitive, type-safe tools with proper schemas and structured output +- **Python MCP SDK**: The `mcp` package v2, `MCPServer`, the low-level `Server`, all transports, and the utilities +- **Python Development**: Python 3.10+, type hints, async/await, decorators, and context managers +- **Data Validation**: Pydantic models, TypedDicts, and dataclasses for schema generation +- **MCP Protocol**: The 2026-07-28 specification: stateless requests, `server/discover`, multi round-trip requests, and deprecated features +- **Transport Types**: stdio and Streamable HTTP transports, and ASGI mounting +- **Tool Design**: Type-safe tools with correct schemas and structured output - **Best Practices**: Testing, error handling, logging, resource management, and security -- **Debugging**: Troubleshooting type hint issues, schema problems, and transport errors +- **Debugging**: Type hint problems, schema problems, and transport errors ## Your Approach -- **Type Safety First**: Always use comprehensive type hints - they drive schema generation -- **Understand Use Case**: Clarify whether the server is for local (stdio) or remote (HTTP) use -- **FastMCP by Default**: Use FastMCP for most cases, only drop to low-level Server when needed -- **Decorator Pattern**: Leverage `@mcp.tool()`, `@mcp.resource()`, `@mcp.prompt()` decorators -- **Structured Output**: Return Pydantic models or TypedDicts for machine-readable data -- **Context When Needed**: Use Context parameter for logging, progress, sampling, or elicitation -- **Error Handling**: Implement comprehensive try-except with clear error messages -- **Test Early**: Encourage testing with `uv run mcp dev` before integration +- **Type Safety First**: Always use full type hints. The SDK makes the schemas from them. +- **Understand Use Case**: Find out if the server is for local (stdio) or remote (HTTP) use. +- **MCPServer by Default**: Use `MCPServer` from `mcp.server` for most cases. Use the low-level `Server` only when necessary. +- **No FastMCP**: SDK v2 removed `FastMCP` and `mcp.server.fastmcp`. Do not use them. +- **Decorator Pattern**: Use the `@mcp.tool()`, `@mcp.resource()`, and `@mcp.prompt()` decorators. +- **Structured Output**: Return Pydantic models or TypedDicts for machine-readable data. +- **Context When Needed**: Use the `Context` parameter (from `mcp.server.mcpserver`) for progress reports and lifespan resources. +- **Error Handling**: Raise `ToolError` (from `mcp.server.mcpserver.exceptions`) with a clear message for errors that the model must read. Do not raise `MCPError` for a tool failure. The client gets a protocol error, not a tool result with `is_error`. +- **Test Early**: Test with the MCP Inspector (`uv run mcp dev server.py`) and the in-memory client (`async with Client(mcp) as client:`) before integration. ## Guidelines -- Always use complete type hints for parameters and return values -- Write clear docstrings - they become tool descriptions in the protocol -- Use Pydantic models, TypedDicts, or dataclasses for structured outputs -- Return structured data when tools need machine-readable results -- Use `Context` parameter when tools need logging, progress, or LLM interaction -- Log with `await ctx.debug()`, `await ctx.info()`, `await ctx.warning()`, `await ctx.error()` -- Report progress with `await ctx.report_progress(progress, total, message)` -- Use sampling for LLM-powered tools: `await ctx.session.create_message()` -- Request user input with `await ctx.elicit(message, schema)` -- Define dynamic resources with URI templates: `@mcp.resource("resource://{param}")` -- Use lifespan context managers for startup/shutdown resources -- Access lifespan context via `ctx.request_context.lifespan_context` -- For HTTP servers, use `mcp.run(transport="streamable-http")` -- Enable stateless mode for scalability: `stateless_http=True` -- Mount to Starlette/FastAPI with `mcp.streamable_http_app()` -- Configure CORS and expose `Mcp-Session-Id` for browser clients -- Test with MCP Inspector: `uv run mcp dev server.py` -- Install to Claude Desktop: `uv run mcp install server.py` -- Use async functions for I/O-bound operations -- Clean up resources in finally blocks or context managers -- Validate inputs using Pydantic Field with descriptions -- Provide meaningful parameter names and descriptions +- Create the project with `uv init --app --no-package` and install the SDK with `uv add "mcp[cli]>=2,<3"`. +- Write clear docstrings and parameter names. The docstrings become the tool descriptions in the protocol. +- Set `version` on `MCPServer`. If you do not set it, the server reports an empty version. +- The SDK v2 types use snake_case fields, for example `read_only_hint`, `structured_content`, and `is_error`. +- Report progress with `await ctx.report_progress(progress, total, message)`. +- Get user input with a `Resolve(fn)` parameter that returns `Elicit(message, Model)`. This works with clients of all protocol revisions. +- Do not use `ctx.elicit()`. It fails on a 2026-07-28 connection. +- Log with the standard `logging` module to stderr. Protocol logging (`ctx.info()` and similar methods) is deprecated. +- In a stdio server, do not call `print()`. Stdout is the protocol channel. +- Do not use sampling (`ctx.session.create_message()`). It is deprecated. Call the LLM provider API directly. +- Do not use roots. They are deprecated. Get paths from tool parameters or the server configuration. +- Define dynamic resources with URI templates: `@mcp.resource("resource://{param}")`. +- Send list change notifications with `await ctx.notify_tools_changed()`. A 2026-07-28 connection drops `ctx.session.send_tool_list_changed()`. +- Use lifespan context managers for startup and shutdown resources. For stdio and HTTP, the lifespan runs one time for the server. Each in-memory `Client(mcp)` runs it again. +- Get the lifespan object from `ctx.request_context.lifespan_context`. +- For HTTP servers, use `mcp.run(transport="streamable-http")`. +- Give transport options (`host`, `port`, `json_response`, `stateless_http`, `transport_security`) to `run()`, not to `MCPServer(...)`. +- Give the server name as the first `MCPServer` argument. Give all other constructor arguments as keyword arguments. +- On the 2026-07-28 revision, Streamable HTTP requests have no session. `stateless_http=True` changes only how the server serves clients of earlier revisions. +- Mount to Starlette or FastAPI with `mcp.streamable_http_app()`. Give the transport options to this method. It has no `port` option. +- The lifespan of the host app must enter `mcp.session_manager.run()`. +- If you do not set `transport_security`, the SDK checks the `Host` and `Origin` headers only when the host is `127.0.0.1`, `localhost`, or `::1`. For all other hosts, set `transport_security=TransportSecuritySettings(allowed_hosts=[...], allowed_origins=[...])`. +- For browser clients, configure CORS. Allow the `Mcp-*` request headers. Expose the `Mcp-Session-Id` response header. +- For more than one worker, set `request_state_security=RequestStateSecurity(keys=[...])`. +- Install to Claude Desktop: `uv run mcp install server.py`. +- Use async functions for I/O-bound operations. +- Release resources in `finally` blocks or context managers. +- Validate inputs with Pydantic `Field` descriptions. ## Common Scenarios You Excel At -- **Creating New Servers**: Generating complete project structures with uv and proper setup -- **Tool Development**: Implementing typed tools for data processing, APIs, files, or databases -- **Resource Implementation**: Creating static or dynamic resources with URI templates -- **Prompt Development**: Building reusable prompts with proper message structures -- **Transport Setup**: Configuring stdio for local use or HTTP for remote access -- **Debugging**: Diagnosing type hint issues, schema validation errors, and transport problems -- **Optimization**: Improving performance, adding structured output, managing resources -- **Migration**: Helping upgrade from older MCP patterns to current best practices -- **Integration**: Connecting servers with databases, APIs, or other services -- **Testing**: Writing tests and providing testing strategies with mcp dev +- **Creating New Servers**: Generate complete project structures with uv +- **Tool Development**: Write typed tools for data processing, APIs, files, or databases +- **Resource Implementation**: Create static or dynamic resources with URI templates +- **Prompt Development**: Write reusable prompts with correct message structures +- **Transport Setup**: Configure stdio for local use or HTTP for remote access +- **Debugging**: Find type hint problems, schema validation errors, and transport problems +- **Optimization**: Improve performance, add structured output, and manage resources +- **Migration**: Upgrade servers from SDK v1 (`FastMCP`) to SDK v2 (`MCPServer`) +- **Integration**: Connect servers to databases, APIs, or other services +- **Testing**: Write tests with the in-memory `Client` and `mcp dev` ## Response Style -- Provide complete, working code that can be copied and run immediately -- Include all necessary imports at the top -- Add inline comments for important or non-obvious code -- Show complete file structure when creating new projects -- Explain the "why" behind design decisions -- Highlight potential issues or edge cases -- Suggest improvements or alternative approaches when relevant -- Include uv commands for setup and testing -- Format code with proper Python conventions -- Provide environment variable examples when needed +- Give complete, working code that the user can copy and run immediately. +- Put all necessary imports at the top. +- Add inline comments for important or unclear code. +- Show the complete file structure for new projects. +- Explain the reason for design decisions. +- Show possible problems and edge cases. +- Suggest improvements or alternative approaches when they are relevant. +- Include uv commands for setup and testing. +- Format code with the correct Python conventions. +- Give environment variable examples when necessary. ## Advanced Capabilities You Know -- **Lifespan Management**: Using context managers for startup/shutdown with shared resources -- **Structured Output**: Understanding automatic conversion of Pydantic models to schemas -- **Context Access**: Full use of Context for logging, progress, sampling, and elicitation +- **Multi Round-Trip Requests**: `Resolve` and `Elicit` for user input, and `InputRequiredResult` for manual control - **Dynamic Resources**: URI templates with parameter extraction -- **Completion Support**: Implementing argument completion for better UX -- **Image Handling**: Using Image class for automatic image processing -- **Icon Configuration**: Adding icons to server, tools, resources, and prompts -- **ASGI Mounting**: Integrating with Starlette/FastAPI for complex deployments -- **Session Management**: Understanding stateful vs stateless HTTP modes -- **Authentication**: Implementing OAuth with TokenVerifier -- **Pagination**: Handling large datasets with cursor-based pagination (low-level) -- **Low-Level API**: Using Server class directly for maximum control -- **Multi-Server**: Mounting multiple FastMCP servers in single ASGI app +- **Completion Support**: Argument completion with `@mcp.completion()` +- **Image Handling**: The `Image` and `Audio` classes for media results +- **Icon Configuration**: Icons for the server, tools, resources, and prompts +- **ASGI Mounting**: Integration with Starlette or FastAPI for complex deployments +- **Protocol Revisions**: One server serves 2026-07-28 clients and clients of earlier revisions +- **Authentication**: OAuth with `TokenVerifier` +- **Pagination**: Cursor-based pagination for large datasets (low-level) +- **Low-Level API**: The `Server` class for maximum control +- **Multi-Server**: More than one `MCPServer` in one ASGI app -You help developers build high-quality Python MCP servers that are type-safe, robust, well-documented, and easy for LLMs to use effectively. +You help developers build Python MCP servers that are type-safe, reliable, well documented, and easy for LLMs to use. diff --git a/docs/README.instructions.md b/docs/README.instructions.md index 0ac3727e0..e3bf08fc8 100644 --- a/docs/README.instructions.md +++ b/docs/README.instructions.md @@ -174,7 +174,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-instructions) for guidelines on | [PowerShell Cmdlet Development Guidelines](../instructions/powershell.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpowershell.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpowershell.instructions.md) | PowerShell cmdlet and scripting best practices based on Microsoft guidelines | | [PowerShell Pester v6 Testing Guidelines](../instructions/powershell-pester-6.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpowershell-pester-6.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpowershell-pester-6.instructions.md) | PowerShell Pester testing best practices based on Pester v6 conventions | | [Project Context](../instructions/moodle.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fmoodle.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fmoodle.instructions.md) | Instructions for GitHub Copilot to generate code in a Moodle project context. | -| [Python MCP Server Development](../instructions/python-mcp-server.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpython-mcp-server.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpython-mcp-server.instructions.md) | Instructions for building Model Context Protocol (MCP) servers using the Python SDK | +| [Python MCP Server Development](../instructions/python-mcp-server.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpython-mcp-server.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fpython-mcp-server.instructions.md) | Instructions for building Model Context Protocol (MCP) servers using the Python SDK v2 | | [QA Engineering Best Practices](../instructions/qa-engineering-best-practices.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fqa-engineering-best-practices.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fqa-engineering-best-practices.instructions.md) | Comprehensive QA engineering best practices covering test strategy, test pyramid, naming conventions, assertion patterns, bug reporting, and automation guidelines for modern software projects. | | [Quarkus](../instructions/quarkus.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fquarkus.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fquarkus.instructions.md) | Quarkus development standards and instructions | | [Quarkus MCP Server](../instructions/quarkus-mcp-server-sse.instructions.md)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fquarkus-mcp-server-sse.instructions.md)
[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fquarkus-mcp-server-sse.instructions.md) | Quarkus and MCP Server with HTTP SSE transport development standards and instructions | diff --git a/docs/README.plugins.md b/docs/README.plugins.md index fa32abc5d..9991fb3cb 100644 --- a/docs/README.plugins.md +++ b/docs/README.plugins.md @@ -99,7 +99,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-plugins) for guidelines on how t | [pr-artifact-explorer](../plugins/pr-artifact-explorer/README.md) | Navigate pull requests and securely explore GitHub Actions artifacts, including test results, static sites, terminal recordings, and source files. | 1 items | actions-artifacts, artifact-browser, canvas, copilot-extension, github-actions, pull-requests, test-results | | [project-documenter](../plugins/project-documenter/README.md) | Generate professional project documentation with draw.io architecture diagrams and Word (.docx) output with embedded images. Automatically discovers any project's technology stack and produces Markdown, diagrams, PNG exports, and a formatted Word document. | 3 items | documentation, architecture-diagrams, drawio, word-document, docx, png-images, c4-model, project-summary, auto-discovery | | [project-planning](../plugins/project-planning/README.md) | Tools and guidance for software project planning, feature breakdown, epic management, implementation planning, and task organization for development teams. | 15 items | planning, project-management, epic, feature, implementation, task, architecture, technical-spike | -| [python-mcp-development](../plugins/python-mcp-development/README.md) | Complete toolkit for building Model Context Protocol (MCP) servers in Python using the official SDK with FastMCP. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance. | 2 items | python, mcp, model-context-protocol, fastmcp, server-development | +| [python-mcp-development](../plugins/python-mcp-development/README.md) | Build Model Context Protocol (MCP) servers in Python with the official MCP Python SDK v2 (MCPServer). Includes a skill that generates a server project and an expert agent for guidance. | 2 items | python, mcp, model-context-protocol, mcp-python-sdk, server-development | | [react18-upgrade](../plugins/react18-upgrade/README.md) | Enterprise React 18 migration toolkit with specialized agents and skills for upgrading React 16/17 class-component codebases to React 18.3.1. Includes auditor, dependency surgeon, class component migration specialist, automatic batching fixer, and test guardian. | 13 items | react18, react, migration, upgrade, class-components, lifecycle, batching | | [react19-upgrade](../plugins/react19-upgrade/README.md) | Enterprise React 19 migration toolkit with specialized agents and skills for upgrading React 18 codebases to React 19. Includes auditor, dependency surgeon, source code migrator, and test guardian. Handles removal of deprecated APIs including ReactDOM.render, forwardRef, defaultProps, legacy context, string refs, and more. | 8 items | react19, react, migration, upgrade, hooks, modern-react | | [release-notes-showcase](../plugins/release-notes-showcase/README.md) | Compose and refine launch-ready release notes with contributor callouts and export-friendly output. | 1 items | changelog, contributor-callouts, email-export, launch-summary, product-updates, release-notes | diff --git a/docs/README.skills.md b/docs/README.skills.md index 18f811107..2e3530a45 100644 --- a/docs/README.skills.md +++ b/docs/README.skills.md @@ -340,7 +340,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to | [publish-to-pages](../skills/publish-to-pages/SKILL.md)
`gh skills install github/awesome-copilot publish-to-pages` | Publish presentations and web content to GitHub Pages. Converts PPTX, PDF, HTML, or Google Slides to a live GitHub Pages URL. Handles repo creation, file conversion, Pages enablement, and returns the live URL. Use when the user wants to publish, deploy, or share a presentation or HTML file via GitHub Pages. | `scripts/convert-pdf.py`
`scripts/convert-pptx.py`
`scripts/publish.sh` | | [pytest-coverage](../skills/pytest-coverage/SKILL.md)
`gh skills install github/awesome-copilot pytest-coverage` | Run pytest tests with coverage, discover lines missing coverage, and increase coverage to 100%. | None | | [python-azure-iot-edge-modules](../skills/python-azure-iot-edge-modules/SKILL.md)
`gh skills install github/awesome-copilot python-azure-iot-edge-modules` | Build and operate Python Azure IoT Edge modules with robust messaging, deployment manifests, observability, and production readiness checks. | `references/python-edge-module-template.md`
`references/python-official-best-practices.md` | -| [python-mcp-server-generator](../skills/python-mcp-server-generator/SKILL.md)
`gh skills install github/awesome-copilot python-mcp-server-generator` | Generate a complete MCP server project in Python with tools, resources, and proper configuration | None | +| [python-mcp-server-generator](../skills/python-mcp-server-generator/SKILL.md)
`gh skills install github/awesome-copilot python-mcp-server-generator` | Use this skill when the user wants to create a new Model Context Protocol (MCP) server in Python. Also use it to expose Python functions, an API, or a database to AI clients as MCP tools. The skill makes a uv project with the MCP Python SDK v2 (MCPServer), typed tools, in-memory tests, and client configuration. Do not use it for an MCP client or for a server in another language. | `references/streamable-http.md` | | [python-pypi-package-builder](../skills/python-pypi-package-builder/SKILL.md)
`gh skills install github/awesome-copilot python-pypi-package-builder` | End-to-end skill for building, testing, linting, versioning, and publishing a production-grade Python library to PyPI. Covers all four build backends (setuptools+setuptools_scm, hatchling, flit, poetry), PEP 440 versioning, semantic versioning, dynamic git-tag versioning, OOP/SOLID design, type hints (PEP 484/526/544/561), Trusted Publishing (OIDC), and the full PyPA packaging flow. Use for: creating Python packages, pip-installable SDKs, CLI tools, framework plugins, pyproject.toml setup, py.typed, setuptools_scm, semver, mypy, pre-commit, GitHub Actions CI/CD, or PyPI publishing. | `references/architecture-patterns.md`
`references/ci-publishing.md`
`references/community-docs.md`
`references/library-patterns.md`
`references/pyproject-toml.md`
`references/release-governance.md`
`references/testing-quality.md`
`references/tooling-ruff.md`
`references/versioning-strategy.md`
`scripts/scaffold.py` | | [qdrant-clients-sdk](../skills/qdrant-clients-sdk/SKILL.md)
`gh skills install github/awesome-copilot qdrant-clients-sdk` | Qdrant provides client SDKs for various programming languages, allowing easy integration with Qdrant deployments. | None | | [qdrant-deployment-options](../skills/qdrant-deployment-options/SKILL.md)
`gh skills install github/awesome-copilot qdrant-deployment-options` | Guides Qdrant deployment selection. Use when someone asks 'how to deploy Qdrant', 'Docker vs Cloud', 'local mode', 'embedded Qdrant', 'Qdrant EDGE', 'which deployment option', 'self-hosted vs cloud', or 'need lowest latency deployment'. Also use when choosing between deployment types for a new project. | None | diff --git a/instructions/python-mcp-server.instructions.md b/instructions/python-mcp-server.instructions.md index ade085922..d97270559 100644 --- a/instructions/python-mcp-server.instructions.md +++ b/instructions/python-mcp-server.instructions.md @@ -1,63 +1,74 @@ --- -description: 'Instructions for building Model Context Protocol (MCP) servers using the Python SDK' +description: 'Instructions for building Model Context Protocol (MCP) servers using the Python SDK v2' applyTo: '**/*.py, **/pyproject.toml, **/requirements.txt' --- # Python MCP Server Development +These instructions apply to the [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) v2 and the MCP specification revision [2026-07-28](https://modelcontextprotocol.io/specification/2026-07-28). + ## Instructions -- Use **uv** for project management: `uv init mcp-server-demo` and `uv add "mcp[cli]"` -- Import FastMCP from `mcp.server.fastmcp`: `from mcp.server.fastmcp import FastMCP` -- Use `@mcp.tool()`, `@mcp.resource()`, and `@mcp.prompt()` decorators for registration -- Type hints are mandatory - they're used for schema generation and validation -- Use Pydantic models, TypedDicts, or dataclasses for structured output -- Tools automatically return structured output when return types are compatible -- For stdio transport, use `mcp.run()` or `mcp.run(transport="stdio")` -- For HTTP servers, use `mcp.run(transport="streamable-http")` or mount to Starlette/FastAPI -- Use `Context` parameter in tools/resources to access MCP capabilities: `ctx: Context` -- Send logs with `await ctx.debug()`, `await ctx.info()`, `await ctx.warning()`, `await ctx.error()` -- Report progress with `await ctx.report_progress(progress, total, message)` -- Request user input with `await ctx.elicit(message, schema)` -- Use LLM sampling with `await ctx.session.create_message(messages, max_tokens)` -- Configure icons with `Icon(src="path", mimeType="image/png")` for server, tools, resources, prompts -- Use `Image` class for automatic image handling: `return Image(data=bytes, format="png")` -- Define resource templates with URI patterns: `@mcp.resource("greeting://{name}")` -- Implement completion support by accepting partial values and returning suggestions -- Use lifespan context managers for startup/shutdown with shared resources -- Access lifespan context in tools via `ctx.request_context.lifespan_context` -- For stateless HTTP servers, set `stateless_http=True` in FastMCP initialization -- Enable JSON responses for modern clients: `json_response=True` -- Test servers with: `uv run mcp dev server.py` (Inspector) or `uv run mcp install server.py` (Claude Desktop) -- Mount multiple servers in Starlette with different paths: `Mount("/path", mcp.streamable_http_app())` -- Configure CORS for browser clients: expose `Mcp-Session-Id` header -- Use low-level Server class for maximum control when FastMCP isn't sufficient +- Use **uv** for project management: `uv init --app --no-package mcp-server-demo` and `uv add "mcp[cli]>=2,<3"`. +- Import the server class from `mcp.server`: `from mcp.server import MCPServer`. +- Do not use `FastMCP` or `mcp.server.fastmcp`. SDK v2 removed this import path. +- Import `Context`, `Image`, `Audio`, `Resolve`, `Elicit`, and the prompt message classes from `mcp.server.mcpserver`. +- Use the `@mcp.tool()`, `@mcp.resource()`, and `@mcp.prompt()` decorators for registration. +- Add type hints to all parameters. The SDK makes the schemas from the type hints and validates the arguments. +- Use Pydantic models, TypedDicts, or dataclasses for structured output. +- A tool returns structured output when its return type is compatible. +- For stdio transport, use `mcp.run()` or `mcp.run(transport="stdio")`. +- For HTTP servers, use `mcp.run(transport="streamable-http")`, or mount `mcp.streamable_http_app()` in Starlette or FastAPI. +- Give transport options (`host`, `port`, `json_response`, `stateless_http`, `transport_security`) to `run()`, not to `MCPServer(...)`. +- When you mount the server, give the same options to `streamable_http_app()`. This method has no `port` option. +- Give the server name as the first `MCPServer` argument. Give all other constructor arguments as keyword arguments. +- Set `version` on `MCPServer`. If you do not set it, the server reports an empty version. +- The SDK v2 types use snake_case fields, for example `read_only_hint`, `structured_content`, and `is_error`. +- Add a `ctx: Context` parameter to a tool, resource, or prompt to get the request context. +- Report progress with `await ctx.report_progress(progress, total, message)`. +- Get user input with a `Resolve(fn)` parameter. Return `Elicit(message, Model)` from `fn`. This works with clients of all protocol revisions. +- Do not use `ctx.elicit()`. It fails on a 2026-07-28 connection. +- Log with the standard `logging` module. Protocol logging (`ctx.info()` and similar methods) is deprecated. +- Do not use sampling (`ctx.session.create_message()`). It is deprecated. Call the LLM provider API directly. +- Do not use roots (`ctx.session.list_roots()`). It is deprecated. Get paths from tool parameters or the server configuration. +- Configure icons with `Icon(src="https://...", mime_type="image/png")` from `mcp.types`. Server, tools, resources, and prompts accept `icons=[...]`. +- Use the `Image` class to return images: `return Image(data=png_bytes, format="png")` or `return Image(path=file_path)`. +- Define resource templates with RFC 6570 URI templates: `@mcp.resource("greeting://{name}")`. +- Add completion support with the `@mcp.completion()` decorator. +- Use a lifespan context manager for startup and shutdown of shared resources. For stdio and HTTP, the lifespan runs one time for the server. Each in-memory `Client(mcp)` runs it again. +- Get the lifespan object in tools from `ctx.request_context.lifespan_context`. Use `Context[AppContext]` for a typed result. +- Raise `ToolError` (from `mcp.server.mcpserver.exceptions`) for an error that the model must read. +- Do not raise `MCPError` for a tool failure. The client gets a protocol error, not a tool result with `is_error`. Many hosts do not show this error to the model. +- Send list change notifications with `await ctx.notify_tools_changed()`. Do not use `ctx.session.send_tool_list_changed()`. A 2026-07-28 connection drops it. +- On the 2026-07-28 revision, Streamable HTTP requests have no session. `stateless_http=True` changes only how the server serves clients of earlier revisions. +- `json_response=True` sends one JSON body for each request. In this mode, the server cannot send progress notifications during the request. +- Test servers with `uv run mcp dev server.py` (MCP Inspector) or `uv run mcp install server.py` (Claude Desktop). +- Write tests with the in-memory client: `async with Client(mcp) as client:` (`from mcp import Client`). +- Mount more than one server in Starlette with different paths: `Mount("/path", app=mcp.streamable_http_app())`. The lifespan of the host app must enter `mcp.session_manager.run()` for each server. +- For browser clients, configure CORS. Allow the `Mcp-*` request headers. Expose the `Mcp-Session-Id` response header. +- If you do not set `transport_security`, the SDK checks the `Host` and `Origin` headers only when the host is `127.0.0.1`, `localhost`, or `::1`. For all other hosts, set `transport_security=TransportSecuritySettings(allowed_hosts=[...], allowed_origins=[...])` (from `mcp.server.transport_security`). +- For more than one worker, set `request_state_security=RequestStateSecurity(keys=[...])` on `MCPServer`. +- Use the low-level `Server` class (from `mcp.server`) only when `MCPServer` does not give sufficient control. ## Best Practices -- Always use type hints - they drive schema generation and validation -- Return Pydantic models or TypedDicts for structured tool outputs -- Keep tool functions focused on single responsibilities -- Provide clear docstrings - they become tool descriptions -- Use descriptive parameter names with type hints -- Validate inputs using Pydantic Field descriptions -- Implement proper error handling with try-except blocks -- Use async functions for I/O-bound operations -- Clean up resources in lifespan context managers -- Log to stderr to avoid interfering with stdio transport (when using stdio) -- Use environment variables for configuration -- Test tools independently before LLM integration -- Consider security when exposing file system or network access -- Use structured output for machine-readable data -- Provide both content and structured data for backward compatibility +- Give each tool function one responsibility. +- Write clear docstrings. They become the tool descriptions. +- Use descriptive parameter names with type hints. +- Validate inputs with Pydantic `Field` descriptions. +- Use async functions for I/O-bound operations. The SDK runs sync functions on a worker thread. +- Log to stderr. Do not use `print()` in a stdio server, because stdout is the protocol channel. +- Use environment variables for configuration. +- Be careful when a tool gives access to the file system or the network. ## Common Patterns ### Basic Server Setup (stdio) -```python -from mcp.server.fastmcp import FastMCP -mcp = FastMCP("My Server") +```python +from mcp.server import MCPServer + +mcp = MCPServer("My Server", version="0.1.0") @mcp.tool() def calculate(a: int, b: int, op: str) -> int: @@ -71,10 +82,11 @@ if __name__ == "__main__": ``` ### HTTP Server -```python -from mcp.server.fastmcp import FastMCP -mcp = FastMCP("My HTTP Server") +```python +from mcp.server import MCPServer + +mcp = MCPServer("My HTTP Server", version="0.1.0") @mcp.tool() def hello(name: str = "World") -> str: @@ -82,10 +94,11 @@ def hello(name: str = "World") -> str: return f"Hello, {name}!" if __name__ == "__main__": - mcp.run(transport="streamable-http") + mcp.run(transport="streamable-http", host="127.0.0.1", port=8000) ``` ### Tool with Structured Output + ```python from pydantic import BaseModel, Field @@ -105,6 +118,7 @@ def get_weather(city: str) -> WeatherData: ``` ### Dynamic Resource + ```python @mcp.resource("users://{user_id}") def get_user(user_id: str) -> str: @@ -113,92 +127,121 @@ def get_user(user_id: str) -> str: ``` ### Tool with Context + ```python -from mcp.server.fastmcp import Context -from mcp.server.session import ServerSession +import logging + +from mcp.server.mcpserver import Context + +logger = logging.getLogger(__name__) @mcp.tool() -async def process_data( - data: str, - ctx: Context[ServerSession, None] -) -> str: - """Process data with logging""" - await ctx.info(f"Processing: {data}") +async def process_data(data: str, ctx: Context) -> str: + """Process data with progress reports""" + logger.info("Processing: %s", data) await ctx.report_progress(0.5, 1.0, "Halfway done") return f"Processed: {data}" ``` -### Tool with Sampling +### Tool with User Input + ```python -from mcp.server.fastmcp import Context -from mcp.server.session import ServerSession -from mcp.types import SamplingMessage, TextContent +from typing import Annotated + +from pydantic import BaseModel + +from mcp.server.mcpserver import AcceptedElicitation, Elicit, ElicitationResult, Resolve + +class Quantity(BaseModel): + copies: int + +async def ask_quantity() -> Elicit[Quantity]: + """Ask the user how many copies to reserve.""" + return Elicit("How many copies?", Quantity) @mcp.tool() -async def summarize( - text: str, - ctx: Context[ServerSession, None] +async def reserve( + title: str, + quantity: Annotated[ElicitationResult[Quantity], Resolve(ask_quantity)], ) -> str: - """Summarize text using LLM""" - result = await ctx.session.create_message( - messages=[SamplingMessage( - role="user", - content=TextContent(type="text", text=f"Summarize: {text}") - )], - max_tokens=100 - ) - return result.content.text if result.content.type == "text" else "" + """Reserve copies of a book""" + if isinstance(quantity, AcceptedElicitation): + return f"Reserved {quantity.data.copies} of {title!r}." + return "Nothing reserved." ``` ### Lifespan Management + ```python +from collections.abc import AsyncIterator from contextlib import asynccontextmanager from dataclasses import dataclass -from mcp.server.fastmcp import FastMCP, Context + +from mcp.server import MCPServer +from mcp.server.mcpserver import Context @dataclass class AppContext: - db: Database + db: Database # Your database client @asynccontextmanager -async def app_lifespan(server: FastMCP): +async def app_lifespan(server: MCPServer) -> AsyncIterator[AppContext]: db = await Database.connect() try: yield AppContext(db=db) finally: await db.disconnect() -mcp = FastMCP("My App", lifespan=app_lifespan) +mcp = MCPServer("My App", version="0.1.0", lifespan=app_lifespan) @mcp.tool() -def query(sql: str, ctx: Context) -> str: +def query(sql: str, ctx: Context[AppContext]) -> str: """Query database""" db = ctx.request_context.lifespan_context.db return db.execute(sql) ``` ### Prompt with Messages + ```python -from mcp.server.fastmcp.prompts import base +from mcp.server.mcpserver import AssistantMessage, Message, UserMessage @mcp.prompt(title="Code Review") -def review_code(code: str) -> list[base.Message]: +def review_code(code: str) -> list[Message]: """Create code review prompt""" return [ - base.UserMessage("Review this code:"), - base.UserMessage(code), - base.AssistantMessage("I'll review the code for you.") + UserMessage("Review this code:"), + UserMessage(code), + AssistantMessage("I'll review the code for you.") ] ``` ### Error Handling + ```python +from mcp.server.mcpserver.exceptions import ToolError + @mcp.tool() async def risky_operation(input: str) -> str: """Operation that might fail""" - try: - result = await perform_operation(input) - return f"Success: {result}" - except Exception as e: - return f"Error: {str(e)}" + if not input: + raise ToolError("Input must not be empty.") + result = await perform_operation(input) # Your operation + return f"Success: {result}" +``` + +### In-Memory Test + +```python +import pytest + +from mcp import Client + +from server import mcp # The HTTP Server example + +@pytest.mark.anyio +async def test_hello(): + async with Client(mcp) as client: + result = await client.call_tool("hello", {"name": "MCP"}) + assert result.structured_content == {"result": "Hello, MCP!"} ``` diff --git a/plugins/python-mcp-development/README.md b/plugins/python-mcp-development/README.md index 7d9e70f63..64f4c79f1 100644 --- a/plugins/python-mcp-development/README.md +++ b/plugins/python-mcp-development/README.md @@ -1,6 +1,6 @@ # Python MCP Server Development Plugin -Complete toolkit for building Model Context Protocol (MCP) servers in Python using the official SDK with FastMCP. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance. +Build Model Context Protocol (MCP) servers in Python with the official MCP Python SDK v2 (MCPServer). Includes a skill that generates a server project and an expert agent for guidance. ## Installation @@ -15,7 +15,7 @@ copilot plugin install python-mcp-development@awesome-copilot | Command | Description | |---------|-------------| -| `/python-mcp-development:python-mcp-server-generator` | Generate a complete MCP server project in Python with tools, resources, and proper configuration | +| `/python-mcp-development:python-mcp-server-generator` | Generate a Python MCP server project with the MCP Python SDK v2 (MCPServer), typed tools, in-memory tests, and client configuration | ### Agents diff --git a/plugins/python-mcp-development/plugin.json b/plugins/python-mcp-development/plugin.json index a8b9a9d2c..b7e5254be 100644 --- a/plugins/python-mcp-development/plugin.json +++ b/plugins/python-mcp-development/plugin.json @@ -1,8 +1,8 @@ { "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "python-mcp-development", - "description": "Complete toolkit for building Model Context Protocol (MCP) servers in Python using the official SDK with FastMCP. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance.", - "version": "1.0.0", + "description": "Build Model Context Protocol (MCP) servers in Python with the official MCP Python SDK v2 (MCPServer). Includes a skill that generates a server project and an expert agent for guidance.", + "version": "2.0.0", "author": { "name": "Awesome Copilot Community" }, @@ -12,7 +12,7 @@ "python", "mcp", "model-context-protocol", - "fastmcp", + "mcp-python-sdk", "server-development" ], "extensions": { diff --git a/skills/python-mcp-server-generator/SKILL.md b/skills/python-mcp-server-generator/SKILL.md index 9e77e716d..2af910728 100644 --- a/skills/python-mcp-server-generator/SKILL.md +++ b/skills/python-mcp-server-generator/SKILL.md @@ -1,105 +1,151 @@ --- name: python-mcp-server-generator -description: 'Generate a complete MCP server project in Python with tools, resources, and proper configuration' +description: 'Use this skill when the user wants to create a new Model Context Protocol (MCP) server in Python. Also use it to expose Python functions, an API, or a database to AI clients as MCP tools. The skill makes a uv project with the MCP Python SDK v2 (MCPServer), typed tools, in-memory tests, and client configuration. Do not use it for an MCP client or for a server in another language.' +compatibility: 'Requires uv, Python 3.10 or later, and network access to install packages. The MCP Inspector also requires Node.js.' --- -# Generate Python MCP Server +# Python MCP Server Generator -Create a complete Model Context Protocol (MCP) server in Python with the following specifications: +Create a Model Context Protocol (MCP) server in Python with the official [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) v2. SDK v2 supports the MCP specification revision [2026-07-28](https://modelcontextprotocol.io/specification/2026-07-28). The same server also serves clients that use earlier revisions. -## Requirements +## Workflow -1. **Project Structure**: Create a new Python project with proper structure using uv -2. **Dependencies**: Include mcp[cli] package with uv -3. **Transport Type**: Choose between stdio (for local) or streamable-http (for remote) -4. **Tools**: Create at least one useful tool with proper type hints -5. **Error Handling**: Include comprehensive error handling and validation +Copy this checklist and track your progress: -## Implementation Details +- [ ] Step 1: Create the project. +- [ ] Step 2: Write the server. +- [ ] Step 3: Write the tests. +- [ ] Step 4: Run the tests until they pass. +- [ ] Step 5: Configure the client. -### Project Setup -- Initialize with `uv init project-name` -- Add MCP SDK: `uv add "mcp[cli]"` -- Create main server file (e.g., `server.py`) -- Add `.gitignore` for Python projects -- Configure for direct execution with `if __name__ == "__main__"` +### Step 1: Create the project -### Server Configuration -- Use `FastMCP` class from `mcp.server.fastmcp` -- Set server name and optional instructions -- Choose transport: stdio (default) or streamable-http -- For HTTP: optionally configure host, port, and stateless mode +Run these commands: -### Tool Implementation -- Use `@mcp.tool()` decorator on functions -- Always include type hints - they generate schemas automatically -- Write clear docstrings - they become tool descriptions -- Use Pydantic models or TypedDicts for structured outputs -- Support async operations for I/O-bound tasks -- Include proper error handling +```bash +uv init --app --no-package project-name +cd project-name +uv add "mcp[cli]>=2,<3" +uv add --dev pytest +``` -### Resource/Prompt Setup (Optional) -- Add resources with `@mcp.resource()` decorator -- Use URI templates for dynamic resources: `"resource://{param}"` -- Add prompts with `@mcp.prompt()` decorator -- Return strings or Message lists from prompts +Then delete `main.py`. The server goes in `server.py`. -### Code Quality -- Use type hints for all function parameters and returns -- Write docstrings for tools, resources, and prompts -- Follow PEP 8 style guidelines -- Use async/await for asynchronous operations -- Implement context managers for resource cleanup -- Add inline comments for complex logic +- Without `--no-package`, uv makes a `src/` package layout, and the tests cannot import `server.py`. +- `uv init` makes the `.gitignore` file. Do not write a different one. -## Example Tool Types to Consider -- Data processing and transformation -- File system operations (read, analyze, search) -- External API integrations -- Database queries -- Text analysis or generation (with sampling) -- System information retrieval -- Math or scientific calculations +### Step 2: Write the server -## Configuration Options -- **For stdio Servers**: - - Simple direct execution - - Test with `uv run mcp dev server.py` - - Install to Claude: `uv run mcp install server.py` - -- **For HTTP Servers**: - - Port configuration via environment variables - - Stateless mode for scalability: `stateless_http=True` - - JSON response mode: `json_response=True` - - CORS configuration for browser clients - - Mounting to existing ASGI servers (Starlette/FastAPI) +Start from this template: -## Testing Guidance -- Explain how to run the server: - - stdio: `python server.py` or `uv run server.py` - - HTTP: `python server.py` then connect to `http://localhost:PORT/mcp` -- Test with MCP Inspector: `uv run mcp dev server.py` -- Install to Claude Desktop: `uv run mcp install server.py` -- Include example tool invocations -- Add troubleshooting tips +```python +from mcp.server import MCPServer +from mcp.server.mcpserver.exceptions import ToolError -## Additional Features to Consider -- Context usage for logging, progress, and notifications -- LLM sampling for AI-powered tools -- User input elicitation for interactive workflows -- Lifespan management for shared resources (databases, connections) -- Structured output with Pydantic models -- Icons for UI display -- Image handling with Image class -- Completion support for better UX +mcp = MCPServer("Demo", version="0.1.0") -## Best Practices -- Use type hints everywhere - they're not optional -- Return structured data when possible -- Log to stderr (or use Context logging) to avoid stdout pollution -- Clean up resources properly -- Validate inputs early -- Provide clear error messages -- Test tools independently before LLM integration -Generate a complete, production-ready MCP server with type safety, proper error handling, and comprehensive documentation. +@mcp.tool() +def divide(a: float, b: float) -> float: + """Divide a by b.""" + if b == 0: + raise ToolError("b must not be zero.") + return a / b + + +if __name__ == "__main__": + mcp.run() # stdio is the default transport +``` + +Then change the template for the request of the user: + +1. Replace `divide` with the tools that the user needs. +2. Give each tool full type hints and a docstring. The SDK makes the input schema from the type hints. The docstring becomes the tool description. +3. Return a Pydantic model or a `TypedDict` when the client needs machine-readable data. The SDK makes the output schema from the return type. +4. Use `async def` for I/O. The SDK runs a sync tool on a worker thread. +5. Mark a read-only tool with `@mcp.tool(annotations=ToolAnnotations(read_only_hint=True))` (from `mcp.types`). Use `destructive_hint=True` for a destructive tool. +6. Add resources (`@mcp.resource("users://{user_id}")`) and prompts (`@mcp.prompt()`) only when the user asks for them. + +Use stdio by default. Read [references/streamable-http.md](references/streamable-http.md) only when the user asks for a remote server or an HTTP server. + +### Step 3: Write the tests + +Put `test_server.py` next to `server.py`. Write a test for each tool and for each `ToolError`: + +```python +import pytest + +from mcp import Client + +from server import mcp + + +@pytest.mark.anyio +async def test_divide(): + async with Client(mcp) as client: + result = await client.call_tool("divide", {"a": 6, "b": 3}) + assert result.structured_content == {"result": 2.0} + + +@pytest.mark.anyio +async def test_divide_by_zero(): + async with Client(mcp) as client: + result = await client.call_tool("divide", {"a": 1, "b": 0}) + assert result.is_error + assert "must not be zero" in result.content[0].text +``` + +- The in-memory `Client` needs no subprocess and no port. It connects with the 2026-07-28 revision. +- The `mcp` package installs `anyio`, which supplies the `anyio` marker. Do not add `pytest-asyncio`. + +### Step 4: Run the tests until they pass + +1. Run `uv run pytest`. +2. If a test fails, read the error. Fix the server or the test. +3. Run `uv run pytest` again. +4. Continue only when all tests pass. + +### Step 5: Configure the client + +For VS Code, write `.vscode/mcp.json`: + +```json +{ + "servers": { + "demo": { + "type": "stdio", + "command": "uv", + "args": ["--directory", "/absolute/path/to/project", "run", "server.py"] + } + } +} +``` + +For Claude Desktop, run `uv run mcp install server.py`. + +Tell the user these commands: + +- `uv run server.py` starts the stdio server. The server waits for a host on stdin and prints nothing. +- `uv run mcp dev server.py` opens the MCP Inspector. The Inspector needs Node.js. + +## Gotchas + +SDK v2 and the 2026-07-28 revision changed many SDK v1 patterns. Do not copy SDK v1 examples. + +- SDK v2 removed `FastMCP` and `mcp.server.fastmcp`. Import the server class with `from mcp.server import MCPServer`. +- Import `Context`, `Image`, `Audio`, `Resolve`, `Elicit`, `ElicitationResult`, `AcceptedElicitation`, `Message`, `UserMessage`, and `AssistantMessage` from `mcp.server.mcpserver`. +- Give the server name as the first `MCPServer` argument. Give all other constructor arguments as keyword arguments. Their positional order changed in SDK v2. +- Set `version`. If you do not set it, the server reports an empty version. +- Give the transport options (`transport`, `host`, `port`, `json_response`, `stateless_http`, `transport_security`) to `run()`, not to `MCPServer(...)`. +- The SDK v2 types use snake_case fields, for example `read_only_hint`, `structured_content`, and `is_error`. +- Raise `ToolError` for an error that the model must read. For other exceptions, the model gets only a generic error message. +- Do not raise `MCPError` for a tool failure. The client gets a protocol error, not a tool result with `is_error`. Many hosts do not show this error to the model. +- In a stdio server, stdout is the protocol channel. Do not call `print()`. Log to stderr with the `logging` module. +- Do not use `ctx.elicit()`. It fails on a 2026-07-28 connection. For user input during a tool call, annotate a parameter with `Resolve(fn)`. Return `Elicit(message, Model)` from `fn`. +- Send list change notifications with `await ctx.notify_tools_changed()`. A 2026-07-28 connection drops `ctx.session.send_tool_list_changed()`. +- For stdio and HTTP, the lifespan runs one time, when the server starts. Each in-memory `Client(mcp)` in a test runs the lifespan again. Read its object with `ctx.request_context.lifespan_context`. +- The 2026-07-28 revision deprecates these features ([SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)). Do not add them to a new server: + - **Sampling** (`ctx.session.create_message()`): Call the LLM provider API directly. + - **Protocol logging** (`ctx.log()`, `ctx.info()`, and similar methods): Use the standard `logging` module. + - **Roots** (`ctx.session.list_roots()`): Get paths from tool parameters, resource URIs, or the server configuration. +- The 2026-07-28 revision has no SSE transport. Use Streamable HTTP. diff --git a/skills/python-mcp-server-generator/references/streamable-http.md b/skills/python-mcp-server-generator/references/streamable-http.md new file mode 100644 index 000000000..addee7240 --- /dev/null +++ b/skills/python-mcp-server-generator/references/streamable-http.md @@ -0,0 +1,46 @@ +# Streamable HTTP Servers + +Use this transport only for a remote server. A local server uses stdio. + +## Run the server + +Replace `mcp.run()` in `server.py`: + +```python +import os + +if __name__ == "__main__": + mcp.run( + transport="streamable-http", + host=os.environ.get("HOST", "127.0.0.1"), + port=int(os.environ.get("PORT", "8000")), + ) +``` + +Clients connect to `http://HOST:PORT/mcp`. For VS Code, write `.vscode/mcp.json`: + +```json +{ + "servers": { + "demo": { + "type": "http", + "url": "http://localhost:8000/mcp" + } + } +} +``` + +## Mount the server in an ASGI app + +1. Use `mcp.streamable_http_app()` to mount the server in a Starlette or FastAPI app. +2. Give the transport options to `streamable_http_app()`. This method has no `port` option. +3. Make the lifespan of the host app enter `mcp.session_manager.run()`. + +## Gotchas + +- Requests on the 2026-07-28 revision have no session. Any replica can answer a request. +- `stateless_http=True` changes only how the server serves clients of earlier revisions. +- `json_response=True` sends one JSON body for each request. In this mode, the server cannot send progress notifications during the request. +- If you do not set `transport_security`, the SDK checks the `Host` and `Origin` headers only when the host is `127.0.0.1`, `localhost`, or `::1`. For all other hosts, for example `0.0.0.0` or a public host name, the server does no check. For these hosts, give `transport_security=TransportSecuritySettings(allowed_hosts=[...], allowed_origins=[...])` (from `mcp.server.transport_security`) to `run()` or `streamable_http_app()`. +- For browser clients, add CORS to the host app. Allow the `Mcp-*` request headers. Expose the `Mcp-Session-Id` response header. +- For more than one worker, set `request_state_security=RequestStateSecurity(keys=[...])` (from `mcp.server.mcpserver`) on `MCPServer`. Use the same keys and the same server name on all workers.