[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-php-mcp--server":3,"tool-php-mcp--server":64},[4,17,27,35,43,56],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":16},3808,"stable-diffusion-webui","AUTOMATIC1111\u002Fstable-diffusion-webui","stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面，旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点，将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。\n\n无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师，还是想要深入探索模型潜力的开发者与研究人员，都能从中获益。其核心亮点在于极高的功能丰富度：不仅支持文生图、图生图、局部重绘（Inpainting）和外绘（Outpainting）等基础模式，还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外，它内置了 GFPGAN 和 CodeFormer 等人脸修复工具，支持多种神经网络放大算法，并允许用户通过插件系统无限扩展能力。即使是显存有限的设备，stable-diffusion-webui 也提供了相应的优化选项，让高质量的 AI 艺术创作变得触手可及。",162132,3,"2026-04-05T11:01:52",[13,14,15],"开发框架","图像","Agent","ready",{"id":18,"name":19,"github_repo":20,"description_zh":21,"stars":22,"difficulty_score":23,"last_commit_at":24,"category_tags":25,"status":16},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",138956,2,"2026-04-05T11:33:21",[13,15,26],"语言模型",{"id":28,"name":29,"github_repo":30,"description_zh":31,"stars":32,"difficulty_score":23,"last_commit_at":33,"category_tags":34,"status":16},2271,"ComfyUI","Comfy-Org\u002FComfyUI","ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎，专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式，采用直观的节点式流程图界面，让用户通过连接不同的功能模块即可构建个性化的生成管线。\n\n这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景，也能自由组合模型、调整参数并实时预览效果，轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性，不仅支持 Windows、macOS 和 Linux 全平台，还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构，并率先支持 SDXL、Flux、SD3 等前沿模型。\n\n无论是希望深入探索算法潜力的研究人员和开发者，还是追求极致创作自由度的设计师与资深 AI 绘画爱好者，ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能，使其成为当前最灵活、生态最丰富的开源扩散模型工具之一，帮助用户将创意高效转化为现实。",107662,"2026-04-03T11:11:01",[13,14,15],{"id":36,"name":37,"github_repo":38,"description_zh":39,"stars":40,"difficulty_score":23,"last_commit_at":41,"category_tags":42,"status":16},3704,"NextChat","ChatGPTNextWeb\u002FNextChat","NextChat 是一款轻量且极速的 AI 助手，旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性，以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发，NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。\n\n这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言，它也提供了便捷的自托管方案，支持一键部署到 Vercel 或 Zeabur 等平台。\n\nNextChat 的核心亮点在于其广泛的模型兼容性，原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型，让用户在一个界面即可自由切换不同 AI 能力。此外，它还率先支持 MCP（Model Context Protocol）协议，增强了上下文处理能力。针对企业用户，NextChat 提供专业版解决方案，具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能，满足公司对数据隐私和个性化管理的高标准要求。",87618,"2026-04-05T07:20:52",[13,26],{"id":44,"name":45,"github_repo":46,"description_zh":47,"stars":48,"difficulty_score":23,"last_commit_at":49,"category_tags":50,"status":16},2268,"ML-For-Beginners","microsoft\u002FML-For-Beginners","ML-For-Beginners 是由微软推出的一套系统化机器学习入门课程，旨在帮助零基础用户轻松掌握经典机器学习知识。这套课程将学习路径规划为 12 周，包含 26 节精炼课程和 52 道配套测验，内容涵盖从基础概念到实际应用的完整流程，有效解决了初学者面对庞大知识体系时无从下手、缺乏结构化指导的痛点。\n\n无论是希望转型的开发者、需要补充算法背景的研究人员，还是对人工智能充满好奇的普通爱好者，都能从中受益。课程不仅提供了清晰的理论讲解，还强调动手实践，让用户在循序渐进中建立扎实的技能基础。其独特的亮点在于强大的多语言支持，通过自动化机制提供了包括简体中文在内的 50 多种语言版本，极大地降低了全球不同背景用户的学习门槛。此外，项目采用开源协作模式，社区活跃且内容持续更新，确保学习者能获取前沿且准确的技术资讯。如果你正寻找一条清晰、友好且专业的机器学习入门之路，ML-For-Beginners 将是理想的起点。",84991,"2026-04-05T10:45:23",[14,51,52,53,15,54,26,13,55],"数据工具","视频","插件","其他","音频",{"id":57,"name":58,"github_repo":59,"description_zh":60,"stars":61,"difficulty_score":10,"last_commit_at":62,"category_tags":63,"status":16},3128,"ragflow","infiniflow\u002Fragflow","RAGFlow 是一款领先的开源检索增强生成（RAG）引擎，旨在为大语言模型构建更精准、可靠的上下文层。它巧妙地将前沿的 RAG 技术与智能体（Agent）能力相结合，不仅支持从各类文档中高效提取知识，还能让模型基于这些知识进行逻辑推理和任务执行。\n\n在大模型应用中，幻觉问题和知识滞后是常见痛点。RAGFlow 通过深度解析复杂文档结构（如表格、图表及混合排版），显著提升了信息检索的准确度，从而有效减少模型“胡编乱造”的现象，确保回答既有据可依又具备时效性。其内置的智能体机制更进一步，使系统不仅能回答问题，还能自主规划步骤解决复杂问题。\n\n这款工具特别适合开发者、企业技术团队以及 AI 研究人员使用。无论是希望快速搭建私有知识库问答系统，还是致力于探索大模型在垂直领域落地的创新者，都能从中受益。RAGFlow 提供了可视化的工作流编排界面和灵活的 API 接口，既降低了非算法背景用户的上手门槛，也满足了专业开发者对系统深度定制的需求。作为基于 Apache 2.0 协议开源的项目，它正成为连接通用大模型与行业专有知识之间的重要桥梁。",77062,"2026-04-04T04:44:48",[15,14,13,26,54],{"id":65,"github_repo":66,"name":67,"description_en":68,"description_zh":69,"ai_summary_zh":70,"readme_en":71,"readme_zh":72,"quickstart_zh":73,"use_case_zh":74,"hero_image_url":75,"owner_login":76,"owner_name":77,"owner_avatar_url":78,"owner_bio":79,"owner_company":80,"owner_location":80,"owner_email":80,"owner_twitter":80,"owner_website":80,"owner_url":81,"languages":82,"stars":87,"forks":88,"last_commit_at":89,"license":90,"difficulty_score":23,"env_os":91,"env_gpu":92,"env_ram":93,"env_deps":94,"category_tags":103,"github_topics":80,"view_count":23,"oss_zip_url":80,"oss_zip_packed_at":80,"status":16,"created_at":104,"updated_at":105,"faqs":106,"releases":135},2043,"php-mcp\u002Fserver","server","Core PHP implementation for the Model Context Protocol (MCP) server","server 是一个专为 PHP 开发者打造的开源工具包，用于快速构建符合模型上下文协议（MCP）标准的服务端应用。它的核心作用是让现有的 PHP 后端功能能够被主流 AI 助手（如 Claude、Cursor、ChatGPT 等）直接识别和调用，从而打破传统后端与人工智能之间的交互壁垒。\n\n通过 server，开发者无需编写繁琐的适配代码，只需在 PHP 方法上添加简单的属性标记（如 `#[McpTool]`），即可将业务逻辑自动暴露为 AI 可理解的“工具”、“资源”或“提示词”。这不仅解决了 AI 难以直接操作私有后端数据的痛点，还实现了从代码定义到 AI 交互的零配置对接。\n\n该工具特别适合熟悉 PHP 生态的后端工程师使用，尤其是那些希望将现有系统智能化，或正在探索 AI Agent 落地场景的开发团队。其技术亮点在于充分利用了 PHP 8.1+ 的现代特性，支持基于属性的自动化注册、智能 JSON 模式生成以及多种通信传输方式（包括标准的输入输出流、HTTP SSE 及可恢复的流式 HTTP）。此外，它还内置了事件驱动架构以支持高并发处理，并提供完善的会话管理与依赖注入支持","server 是一个专为 PHP 开发者打造的开源工具包，用于快速构建符合模型上下文协议（MCP）标准的服务端应用。它的核心作用是让现有的 PHP 后端功能能够被主流 AI 助手（如 Claude、Cursor、ChatGPT 等）直接识别和调用，从而打破传统后端与人工智能之间的交互壁垒。\n\n通过 server，开发者无需编写繁琐的适配代码，只需在 PHP 方法上添加简单的属性标记（如 `#[McpTool]`），即可将业务逻辑自动暴露为 AI 可理解的“工具”、“资源”或“提示词”。这不仅解决了 AI 难以直接操作私有后端数据的痛点，还实现了从代码定义到 AI 交互的零配置对接。\n\n该工具特别适合熟悉 PHP 生态的后端工程师使用，尤其是那些希望将现有系统智能化，或正在探索 AI Agent 落地场景的开发团队。其技术亮点在于充分利用了 PHP 8.1+ 的现代特性，支持基于属性的自动化注册、智能 JSON 模式生成以及多种通信传输方式（包括标准的输入输出流、HTTP SSE 及可恢复的流式 HTTP）。此外，它还内置了事件驱动架构以支持高并发处理，并提供完善的会话管理与依赖注入支持，帮助开发者轻松构建生产级、高可用的 AI 集成服务。","# PHP MCP Server SDK\n\n[![Latest Version on Packagist](https:\u002F\u002Fimg.shields.io\u002Fpackagist\u002Fv\u002Fphp-mcp\u002Fserver.svg?style=flat-square)](https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fphp-mcp\u002Fserver)\n[![Total Downloads](https:\u002F\u002Fimg.shields.io\u002Fpackagist\u002Fdt\u002Fphp-mcp\u002Fserver.svg?style=flat-square)](https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fphp-mcp\u002Fserver)\n[![Tests](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Fphp-mcp\u002Fserver\u002Ftests.yml?branch=main&style=flat-square)](https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Factions\u002Fworkflows\u002Ftests.yml)\n[![License](https:\u002F\u002Fimg.shields.io\u002Fpackagist\u002Fl\u002Fphp-mcp\u002Fserver.svg?style=flat-square)](LICENSE)\n\n**A comprehensive PHP SDK for building [Model Context Protocol (MCP)](https:\u002F\u002Fmodelcontextprotocol.io\u002Fintroduction) servers. Create production-ready MCP servers in PHP with modern architecture, extensive testing, and flexible transport options.**\n\nThis SDK enables you to expose your PHP application's functionality as standardized MCP **Tools**, **Resources**, and **Prompts**, allowing AI assistants (like Anthropic's Claude, Cursor IDE, OpenAI's ChatGPT, etc.) to interact with your backend using the MCP standard.\n\n## 🚀 Key Features\n\n- **🏗️ Modern Architecture**: Built with PHP 8.1+ features, PSR standards, and modular design\n- **📡 Multiple Transports**: Supports `stdio`, `http+sse`, and new **streamable HTTP** with resumability\n- **🎯 Attribute-Based Definition**: Use PHP 8 Attributes (`#[McpTool]`, `#[McpResource]`, etc.) for zero-config element registration\n- **🔧 Flexible Handlers**: Support for closures, class methods, static methods, and invokable classes\n- **📝 Smart Schema Generation**: Automatic JSON schema generation from method signatures with optional `#[Schema]` attribute enhancements\n- **⚡ Session Management**: Advanced session handling with multiple storage backends\n- **🔄 Event-Driven**: ReactPHP-based for high concurrency and non-blocking operations  \n- **📊 Batch Processing**: Full support for JSON-RPC batch requests\n- **💾 Smart Caching**: Intelligent caching of discovered elements with manual override precedence\n- **🧪 Completion Providers**: Built-in support for argument completion in tools and prompts\n- **🔌 Dependency Injection**: Full PSR-11 container support with auto-wiring\n- **📋 Comprehensive Testing**: Extensive test suite with integration tests for all transports\n\nThis package supports the **2025-03-26** version of the Model Context Protocol with backward compatibility.\n\n## 📋 Requirements\n\n- **PHP** >= 8.1\n- **Composer**\n- **For HTTP Transport**: An event-driven PHP environment (CLI recommended)\n- **Extensions**: `json`, `mbstring`, `pcre` (typically enabled by default)\n\n## 📦 Installation\n\n```bash\ncomposer require php-mcp\u002Fserver\n```\n\n> **💡 Laravel Users**: Consider using [`php-mcp\u002Flaravel`](https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Flaravel) for enhanced framework integration, configuration management, and Artisan commands.\n\n## ⚡ Quick Start: Stdio Server with Discovery\n\nThis example demonstrates the most common usage pattern - a `stdio` server using attribute discovery.\n\n**1. Define Your MCP Elements**\n\nCreate `src\u002FCalculatorElements.php`:\n\n```php\n\u003C?php\n\nnamespace App;\n\nuse PhpMcp\\Server\\Attributes\\McpTool;\nuse PhpMcp\\Server\\Attributes\\Schema;\n\nclass CalculatorElements\n{\n    \u002F**\n     * Adds two numbers together.\n     * \n     * @param int $a The first number\n     * @param int $b The second number  \n     * @return int The sum of the two numbers\n     *\u002F\n    #[McpTool(name: 'add_numbers')]\n    public function add(int $a, int $b): int\n    {\n        return $a + $b;\n    }\n\n    \u002F**\n     * Calculates power with validation.\n     *\u002F\n    #[McpTool(name: 'calculate_power')]\n    public function power(\n        #[Schema(type: 'number', minimum: 0, maximum: 1000)]\n        float $base,\n        \n        #[Schema(type: 'integer', minimum: 0, maximum: 10)]\n        int $exponent\n    ): float {\n        return pow($base, $exponent);\n    }\n}\n```\n\n**2. Create the Server Script**\n\nCreate `mcp-server.php`:\n\n```php\n#!\u002Fusr\u002Fbin\u002Fenv php\n\u003C?php\n\ndeclare(strict_types=1);\n\nrequire_once __DIR__ . '\u002Fvendor\u002Fautoload.php';\n\nuse PhpMcp\\Server\\Server;\nuse PhpMcp\\Server\\Transports\\StdioServerTransport;\n\ntry {\n    \u002F\u002F Build server configuration\n    $server = Server::make()\n        ->withServerInfo('PHP Calculator Server', '1.0.0') \n        ->build();\n\n    \u002F\u002F Discover MCP elements via attributes\n    $server->discover(\n        basePath: __DIR__,\n        scanDirs: ['src']\n    );\n\n    \u002F\u002F Start listening via stdio transport\n    $transport = new StdioServerTransport();\n    $server->listen($transport);\n\n} catch (\\Throwable $e) {\n    fwrite(STDERR, \"[CRITICAL ERROR] \" . $e->getMessage() . \"\\n\");\n    exit(1);\n}\n```\n\n**3. Configure Your MCP Client**\n\nAdd to your client configuration (e.g., `.cursor\u002Fmcp.json`):\n\n```json\n{\n    \"mcpServers\": {\n        \"php-calculator\": {\n            \"command\": \"php\",\n            \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fyour\u002Fmcp-server.php\"]\n        }\n    }\n}\n```\n\n**4. Test the Server**\n\nYour AI assistant can now call:\n- `add_numbers` - Add two integers\n- `calculate_power` - Calculate power with validation constraints\n\n## 🏗️ Architecture Overview\n\nThe PHP MCP Server uses a modern, decoupled architecture:\n\n```\n┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐\n│   MCP Client    │◄──►│   Transport      │◄──►│   Protocol      │\n│  (Claude, etc.) │    │ (Stdio\u002FHTTP\u002FSSE) │    │   (JSON-RPC)    │\n└─────────────────┘    └──────────────────┘    └─────────────────┘\n                                                         │\n                       ┌─────────────────┐               │\n                       │ Session Manager │◄──────────────┤\n                       │ (Multi-backend) │               │\n                       └─────────────────┘               │\n                                                         │\n┌─────────────────┐    ┌──────────────────┐              │\n│   Dispatcher    │◄───│   Server Core    │◄─────────────┤\n│ (Method Router) │    │   Configuration  │              │\n└─────────────────┘    └──────────────────┘              │\n         │                                               │\n         ▼                                               │\n┌─────────────────┐    ┌──────────────────┐              │\n│    Registry     │    │   Elements       │◄─────────────┘\n│  (Element Store)│◄──►│ (Tools\u002FResources │\n└─────────────────┘    │  Prompts\u002Fetc.)   │\n                       └──────────────────┘\n```\n\n### Core Components\n\n- **`ServerBuilder`**: Fluent configuration interface (`Server::make()->...->build()`)\n- **`Server`**: Central coordinator containing all configured components\n- **`Protocol`**: JSON-RPC 2.0 handler bridging transports and core logic\n- **`SessionManager`**: Multi-backend session storage (array, cache, custom)\n- **`Dispatcher`**: Method routing and request processing\n- **`Registry`**: Element storage with smart caching and precedence rules\n- **`Elements`**: Registered MCP components (Tools, Resources, Prompts, Templates)\n\n### Transport Options\n\n1. **`StdioServerTransport`**: Standard I\u002FO for direct client launches\n2. **`HttpServerTransport`**: HTTP + Server-Sent Events for web integration  \n3. **`StreamableHttpServerTransport`**: Enhanced HTTP with resumability and event sourcing\n\n## ⚙️ Server Configuration\n\n### Basic Configuration\n\n```php\nuse PhpMcp\\Server\\Server;\nuse PhpMcp\\Schema\\ServerCapabilities;\n\n$server = Server::make()\n    ->withServerInfo('My App Server', '2.1.0')\n    ->withCapabilities(ServerCapabilities::make(\n        resources: true,\n        resourcesSubscribe: true,\n        prompts: true,\n        tools: true\n    ))\n    ->withPaginationLimit(100)\n    ->build();\n```\n\n### Advanced Configuration with Dependencies\n\n```php\nuse Psr\\Log\\Logger;\nuse Psr\\SimpleCache\\CacheInterface;\nuse Psr\\Container\\ContainerInterface;\n\n$server = Server::make()\n    ->withServerInfo('Production Server', '1.0.0')\n    ->withLogger($myPsrLogger)                    \u002F\u002F PSR-3 Logger\n    ->withCache($myPsrCache)                      \u002F\u002F PSR-16 Cache  \n    ->withContainer($myPsrContainer)              \u002F\u002F PSR-11 Container\n    ->withSession('cache', 7200)                  \u002F\u002F Cache-backed sessions, 2hr TTL\n    ->withPaginationLimit(50)                     \u002F\u002F Limit list responses\n    ->build();\n```\n\n### Session Management Options\n\n```php\n\u002F\u002F In-memory sessions (default, not persistent)\n->withSession('array', 3600)\n\n\u002F\u002F Cache-backed sessions (persistent across restarts)  \n->withSession('cache', 7200)\n\n\u002F\u002F Custom session handler (implement SessionHandlerInterface)\n->withSessionHandler(new MyCustomSessionHandler(), 1800)\n```\n\n## 🎯 Defining MCP Elements\n\nThe server provides two powerful ways to define MCP elements: **Attribute-Based Discovery** (recommended) and **Manual Registration**. Both can be combined, with manual registrations taking precedence.\n\n### Element Types\n\n- **🔧 Tools**: Executable functions\u002Factions (e.g., `calculate`, `send_email`, `query_database`)\n- **📄 Resources**: Static content\u002Fdata (e.g., `config:\u002F\u002Fsettings`, `file:\u002F\u002Freadme.txt`)\n- **📋 Resource Templates**: Dynamic resources with URI patterns (e.g., `user:\u002F\u002F{id}\u002Fprofile`)  \n- **💬 Prompts**: Conversation starters\u002Ftemplates (e.g., `summarize`, `translate`)\n\n### 1. 🏷️ Attribute-Based Discovery (Recommended)\n\nUse PHP 8 attributes to mark methods or invokable classes as MCP elements. The server will discover them via filesystem scanning.\n\n```php\nuse PhpMcp\\Server\\Attributes\\{McpTool, McpResource, McpResourceTemplate, McpPrompt};\n\nclass UserManager\n{\n    \u002F**\n     * Creates a new user account.\n     *\u002F\n    #[McpTool(name: 'create_user')]\n    public function createUser(string $email, string $password, string $role = 'user'): array\n    {\n        \u002F\u002F Create user logic\n        return ['id' => 123, 'email' => $email, 'role' => $role];\n    }\n\n    \u002F**\n     * Get user configuration.\n     *\u002F\n    #[McpResource(\n        uri: 'config:\u002F\u002Fuser\u002Fsettings',\n        mimeType: 'application\u002Fjson'\n    )]\n    public function getUserConfig(): array\n    {\n        return ['theme' => 'dark', 'notifications' => true];\n    }\n\n    \u002F**\n     * Get user profile by ID.\n     *\u002F\n    #[McpResourceTemplate(\n        uriTemplate: 'user:\u002F\u002F{userId}\u002Fprofile',\n        mimeType: 'application\u002Fjson'\n    )]\n    public function getUserProfile(string $userId): array\n    {\n        return ['id' => $userId, 'name' => 'John Doe'];\n    }\n\n    \u002F**\n     * Generate welcome message prompt.\n     *\u002F\n    #[McpPrompt(name: 'welcome_user')]\n    public function welcomeUserPrompt(string $username, string $role): array\n    {\n        return [\n            ['role' => 'user', 'content' => \"Create a welcome message for {$username} with role {$role}\"]\n        ];\n    }\n}\n```\n\n**Discovery Process:**\n\n```php\n\u002F\u002F Build server first\n$server = Server::make()\n    ->withServerInfo('My App Server', '1.0.0')\n    ->build();\n\n\u002F\u002F Then discover elements\n$server->discover(\n    basePath: __DIR__,\n    scanDirs: ['src\u002FHandlers', 'src\u002FServices'],  \u002F\u002F Directories to scan\n    excludeDirs: ['src\u002FTests'],                  \u002F\u002F Directories to skip\n    saveToCache: true                            \u002F\u002F Cache results (default: true)\n);\n```\n\n**Available Attributes:**\n\n- **`#[McpTool]`**: Executable actions\n- **`#[McpResource]`**: Static content accessible via URI\n- **`#[McpResourceTemplate]`**: Dynamic resources with URI templates  \n- **`#[McpPrompt]`**: Conversation templates and prompt generators\n\n### 2. 🔧 Manual Registration \n\nRegister elements programmatically using the `ServerBuilder` before calling `build()`. Useful for dynamic registration, closures, or when you prefer explicit control.\n\n```php\nuse App\\Handlers\\{EmailHandler, ConfigHandler, UserHandler, PromptHandler};\nuse PhpMcp\\Schema\\{ToolAnnotations, Annotations};\n\n$server = Server::make()\n    ->withServerInfo('Manual Registration Server', '1.0.0')\n    \n    \u002F\u002F Register a tool with handler method\n    ->withTool(\n        [EmailHandler::class, 'sendEmail'],     \u002F\u002F Handler: [class, method]\n        name: 'send_email',                     \u002F\u002F Tool name (optional)\n        description: 'Send email to user',     \u002F\u002F Description (optional)\n        annotations: ToolAnnotations::make(     \u002F\u002F Annotations (optional)\n            title: 'Send Email Tool'\n        )\n    )\n    \n    \u002F\u002F Register invokable class as tool\n    ->withTool(UserHandler::class)             \u002F\u002F Handler: Invokable class\n    \n    \u002F\u002F Register a closure as tool\n    ->withTool(\n        function(int $a, int $b): int {         \u002F\u002F Handler: Closure\n            return $a + $b;\n        },\n        name: 'add_numbers',\n        description: 'Add two numbers together'\n    )\n    \n    \u002F\u002F Register a resource with closure\n    ->withResource(\n        function(): array {                     \u002F\u002F Handler: Closure\n            return ['timestamp' => time(), 'server' => 'php-mcp'];\n        },\n        uri: 'config:\u002F\u002Fruntime\u002Fstatus',         \u002F\u002F URI (required)\n        mimeType: 'application\u002Fjson'           \u002F\u002F MIME type (optional)\n    )\n    \n    \u002F\u002F Register a resource template\n    ->withResourceTemplate(\n        [UserHandler::class, 'getUserProfile'],\n        uriTemplate: 'user:\u002F\u002F{userId}\u002Fprofile'  \u002F\u002F URI template (required)\n    )\n    \n    \u002F\u002F Register a prompt with closure\n    ->withPrompt(\n        function(string $topic, string $tone = 'professional'): array {\n            return [\n                ['role' => 'user', 'content' => \"Write about {$topic} in a {$tone} tone\"]\n            ];\n        },\n        name: 'writing_prompt'                  \u002F\u002F Prompt name (optional)\n    )\n    \n    ->build();\n```\n\nThe server supports three flexible handler formats: `[ClassName::class, 'methodName']` for class method handlers, `InvokableClass::class` for invokable class handlers (classes with `__invoke` method), and any PHP callable including closures, static methods like `[SomeClass::class, 'staticMethod']`, or function names. Class-based handlers are resolved via the configured PSR-11 container for dependency injection. Manual registrations are never cached and take precedence over discovered elements with the same identifier.\n\n> [!IMPORTANT]\n> When using closures as handlers, the server generates minimal JSON schemas based only on PHP type hints since there are no docblocks or class context available. For more detailed schemas with validation constraints, descriptions, and formats, you have two options:\n> \n> - Use the [`#[Schema]` attribute](#-schema-generation-and-validation) for enhanced schema generation\n> - Provide a custom `$inputSchema` parameter when registering tools with `->withTool()`\n\n### 🏆 Element Precedence & Discovery\n\n**Precedence Rules:**\n- Manual registrations **always** override discovered\u002Fcached elements with the same identifier\n- Discovered elements are cached for performance (configurable)\n- Cache is automatically invalidated on fresh discovery runs\n\n**Discovery Process:**\n\n```php\n$server->discover(\n    basePath: __DIR__,\n    scanDirs: ['src\u002FHandlers', 'src\u002FServices'],  \u002F\u002F Scan these directories\n    excludeDirs: ['tests', 'vendor'],            \u002F\u002F Skip these directories\n    force: false,                                \u002F\u002F Force re-scan (default: false)\n    saveToCache: true                            \u002F\u002F Save to cache (default: true)\n);\n```\n\n**Caching Behavior:**\n- Only **discovered** elements are cached (never manual registrations)\n- Cache loaded automatically during `build()` if available\n- Fresh `discover()` calls clear and rebuild cache\n- Use `force: true` to bypass discovery-already-ran check\n\n## 🚀 Running the Server (Transports)\n\nThe server core is transport-agnostic. Choose a transport based on your deployment needs:\n\n### 1. 📟 Stdio Transport\n\n**Best for**: Direct client execution, command-line tools, simple deployments\n\n```php\nuse PhpMcp\\Server\\Transports\\StdioServerTransport;\n\n$server = Server::make()\n    ->withServerInfo('Stdio Server', '1.0.0')\n    ->build();\n\n$server->discover(__DIR__, ['src']);\n\n\u002F\u002F Create stdio transport (uses STDIN\u002FSTDOUT by default)\n$transport = new StdioServerTransport();\n\n\u002F\u002F Start listening (blocking call)\n$server->listen($transport);\n```\n\n**Client Configuration:**\n```json\n{\n    \"mcpServers\": {\n        \"my-php-server\": {\n            \"command\": \"php\",\n            \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fserver.php\"]\n        }\n    }\n}\n```\n\n> ⚠️ **Important**: When using stdio transport, **never** write to `STDOUT` in your handlers (use `STDERR` for debugging). `STDOUT` is reserved for JSON-RPC communication.\n\n### 2. 🌐 HTTP + Server-Sent Events Transport (Deprecated)\n\n> ⚠️ **Note**: This transport is deprecated in the latest MCP protocol version but remains available for backwards compatibility. For new projects, use the [StreamableHttpServerTransport](#3--streamable-http-transport-new) which provides enhanced features and better protocol compliance.\n\n**Best for**: Legacy applications requiring backwards compatibility\n\n```php\nuse PhpMcp\\Server\\Transports\\HttpServerTransport;\n\n$server = Server::make()\n    ->withServerInfo('HTTP Server', '1.0.0')\n    ->withLogger($logger)  \u002F\u002F Recommended for HTTP\n    ->build();\n\n$server->discover(__DIR__, ['src']);\n\n\u002F\u002F Create HTTP transport\n$transport = new HttpServerTransport(\n    host: '127.0.0.1',      \u002F\u002F MCP protocol prohibits 0.0.0.0\n    port: 8080,             \u002F\u002F Port number\n    mcpPathPrefix: 'mcp'    \u002F\u002F URL prefix (\u002Fmcp\u002Fsse, \u002Fmcp\u002Fmessage)\n);\n\n$server->listen($transport);\n```\n\n**Client Configuration:**\n```json\n{\n    \"mcpServers\": {\n        \"my-http-server\": {\n            \"url\": \"http:\u002F\u002Flocalhost:8080\u002Fmcp\u002Fsse\"\n        }\n    }\n}\n```\n\n**Endpoints:**\n- **SSE Connection**: `GET \u002Fmcp\u002Fsse`\n- **Message Sending**: `POST \u002Fmcp\u002Fmessage?clientId={clientId}`\n\n### 3. 🔄 Streamable HTTP Transport (Recommended)\n\n**Best for**: Production deployments, remote MCP servers, multiple clients, resumable connections\n\n```php\nuse PhpMcp\\Server\\Transports\\StreamableHttpServerTransport;\n\n$server = Server::make()\n    ->withServerInfo('Streamable Server', '1.0.0')\n    ->withLogger($logger)\n    ->withCache($cache)     \u002F\u002F Required for resumability\n    ->build();\n\n$server->discover(__DIR__, ['src']);\n\n\u002F\u002F Create streamable transport with resumability\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',      \u002F\u002F MCP protocol prohibits 0.0.0.0\n    port: 8080,\n    mcpPathPrefix: 'mcp',\n    enableJsonResponse: false,  \u002F\u002F Use SSE streaming (default)\n    stateless: false            \u002F\u002F Enable stateless mode for session-less clients\n);\n\n$server->listen($transport);\n```\n\n**JSON Response Mode:**\n\nThe `enableJsonResponse` option controls how responses are delivered:\n\n- **`false` (default)**: Uses Server-Sent Events (SSE) streams for responses. Best for tools that may take time to process.\n- **`true`**: Returns immediate JSON responses without opening SSE streams. Use this when your tools execute quickly and don't need streaming.\n\n```php\n\u002F\u002F For fast-executing tools, enable JSON mode\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',\n    port: 8080,\n    enableJsonResponse: true  \u002F\u002F Immediate JSON responses\n);\n```\n\n**Stateless Mode:**\n\nFor clients that have issues with session management, enable stateless mode:\n\n```php\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',\n    port: 8080,\n    stateless: true  \u002F\u002F Each request is independent\n);\n```\n\nIn stateless mode, session IDs are generated internally but not exposed to clients, and each request is treated as independent without persistent session state.\n\n**Features:**\n- **Resumable connections** - clients can reconnect and replay missed events\n- **Event sourcing** - all events are stored for replay\n- **JSON mode** - optional JSON-only responses for fast tools\n- **Enhanced session management** - persistent session state\n- **Multiple client support** - designed for concurrent clients\n- **Stateless mode** - session-less operation for simple clients\n\n## 📋 Schema Generation and Validation\n\nThe server automatically generates JSON schemas for tool parameters using a sophisticated priority system that combines PHP type hints, docblock information, and the optional `#[Schema]` attribute. These generated schemas are used both for input validation and for providing schema information to MCP clients.\n\n### Schema Generation Priority\n\nThe server follows this order of precedence when generating schemas:\n\n1. **`#[Schema]` attribute with `definition`** - Complete schema override (highest precedence)\n2. **Parameter-level `#[Schema]` attribute** - Parameter-specific schema enhancements\n3. **Method-level `#[Schema]` attribute** - Method-wide schema configuration\n4. **PHP type hints + docblocks** - Automatic inference from code (lowest precedence)\n\nWhen a `definition` is provided in the Schema attribute, all automatic inference is bypassed and the complete definition is used as-is.\n\n### Parameter-Level Schema Attributes\n\n```php\nuse PhpMcp\\Server\\Attributes\\{McpTool, Schema};\n\n#[McpTool(name: 'validate_user')]\npublic function validateUser(\n    #[Schema(format: 'email')]              \u002F\u002F PHP already knows it's string\n    string $email,\n    \n    #[Schema(\n        pattern: '^[A-Z][a-z]+$',\n        description: 'Capitalized name'\n    )]\n    string $name,\n    \n    #[Schema(minimum: 18, maximum: 120)]    \u002F\u002F PHP already knows it's integer\n    int $age\n): bool {\n    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;\n}\n```\n\n### Method-Level Schema\n\n```php\n\u002F**\n * Process user data with nested validation.\n *\u002F\n#[McpTool(name: 'create_user')]\n#[Schema(\n    properties: [\n        'profile' => [\n            'type' => 'object',\n            'properties' => [\n                'name' => ['type' => 'string', 'minLength' => 2],\n                'age' => ['type' => 'integer', 'minimum' => 18],\n                'email' => ['type' => 'string', 'format' => 'email']\n            ],\n            'required' => ['name', 'email']\n        ]\n    ],\n    required: ['profile']\n)]\npublic function createUser(array $userData): array\n{\n    \u002F\u002F PHP type hint provides base 'array' type\n    \u002F\u002F Method-level Schema adds object structure validation\n    return ['id' => 123, 'status' => 'created'];\n}\n```\n\n### Complete Schema Override (Method-Level Only)\n\n```php\n#[McpTool(name: 'process_api_request')]\n#[Schema(definition: [\n    'type' => 'object',\n    'properties' => [\n        'endpoint' => ['type' => 'string', 'format' => 'uri'],\n        'method' => ['type' => 'string', 'enum' => ['GET', 'POST', 'PUT', 'DELETE']],\n        'headers' => [\n            'type' => 'object',\n            'patternProperties' => [\n                '^[A-Za-z0-9-]+$' => ['type' => 'string']\n            ]\n        ]\n    ],\n    'required' => ['endpoint', 'method']\n])]\npublic function processApiRequest(string $endpoint, string $method, array $headers): array\n{\n    \u002F\u002F PHP type hints are completely ignored when definition is provided\n    \u002F\u002F The schema definition above takes full precedence\n    return ['status' => 'processed', 'endpoint' => $endpoint];\n}\n```\n\n> ⚠️ **Important**: Complete schema definition override should rarely be used. It bypasses all automatic schema inference and requires you to define the entire JSON schema manually. Only use this if you're well-versed with JSON Schema specification and have complex validation requirements that cannot be achieved through the priority system. In most cases, parameter-level and method-level `#[Schema]` attributes provide sufficient flexibility.\n\n## 🎨 Return Value Formatting\n\nThe server automatically formats return values from your handlers into appropriate MCP content types:\n\n### Automatic Formatting\n\n```php\n\u002F\u002F Simple values are auto-wrapped in TextContent\npublic function getString(): string { return \"Hello World\"; }           \u002F\u002F → TextContent\npublic function getNumber(): int { return 42; }                        \u002F\u002F → TextContent  \npublic function getBool(): bool { return true; }                       \u002F\u002F → TextContent\npublic function getArray(): array { return ['key' => 'value']; }       \u002F\u002F → TextContent (JSON)\n\n\u002F\u002F Null handling\npublic function getNull(): ?string { return null; }                    \u002F\u002F → TextContent(\"(null)\")\npublic function returnVoid(): void { \u002F* no return *\u002F }                 \u002F\u002F → Empty content\n```\n\n### Advanced Content Types\n\n```php\nuse PhpMcp\\Schema\\Content\\{TextContent, ImageContent, AudioContent, ResourceContent};\n\npublic function getFormattedCode(): TextContent\n{\n    return TextContent::code('\u003C?php echo \"Hello\";', 'php');\n}\n\npublic function getMarkdown(): TextContent  \n{\n    return TextContent::make('# Title\\n\\nContent here');\n}\n\npublic function getImage(): ImageContent\n{\n    return ImageContent::make(\n        data: base64_encode(file_get_contents('image.png')),\n        mimeType: 'image\u002Fpng'\n    );\n}\n\npublic function getAudio(): AudioContent\n{\n    return AudioContent::make(\n        data: base64_encode(file_get_contents('audio.mp3')),\n        mimeType: 'audio\u002Fmpeg'\n    );\n}\n```\n\n### File and Stream Handling\n\n```php\n\u002F\u002F File objects are automatically read and formatted\npublic function getFileContent(): \\SplFileInfo\n{\n    return new \\SplFileInfo('\u002Fpath\u002Fto\u002Ffile.txt');  \u002F\u002F Auto-detects MIME type\n}\n\n\u002F\u002F Stream resources are read completely\npublic function getStreamContent()\n{\n    $stream = fopen('\u002Fpath\u002Fto\u002Fdata.json', 'r');\n    return $stream;  \u002F\u002F Will be read and closed automatically\n}\n\n\u002F\u002F Structured resource responses\npublic function getStructuredResource(): array\n{\n    return [\n        'text' => 'File content here',\n        'mimeType' => 'text\u002Fplain'\n    ];\n    \n    \u002F\u002F Or for binary data:\n    \u002F\u002F return [\n    \u002F\u002F     'blob' => base64_encode($binaryData),\n    \u002F\u002F     'mimeType' => 'application\u002Foctet-stream'\n    \u002F\u002F ];\n}\n```\n\n## 🔄 Batch Processing\n\nThe server automatically handles JSON-RPC batch requests:\n\n```php\n\u002F\u002F Client can send multiple requests in a single HTTP call:\n[\n    {\"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"tools\u002Fcall\", \"params\": {...}},\n    {\"jsonrpc\": \"2.0\", \"method\": \"notifications\u002Fping\"},              \u002F\u002F notification\n    {\"jsonrpc\": \"2.0\", \"id\": \"2\", \"method\": \"tools\u002Fcall\", \"params\": {...}}\n]\n\n\u002F\u002F Server returns batch response (excluding notifications):\n[\n    {\"jsonrpc\": \"2.0\", \"id\": \"1\", \"result\": {...}},\n    {\"jsonrpc\": \"2.0\", \"id\": \"2\", \"result\": {...}}\n]\n```\n\n## 🔧 Advanced Features\n\n### Completion Providers\n\nCompletion providers enable MCP clients to offer auto-completion suggestions in their user interfaces. They are specifically designed for **Resource Templates** and **Prompts** to help users discover available options for dynamic parts like template variables or prompt arguments.\n\n> **Note**: Tools and resources can be discovered via standard MCP commands (`tools\u002Flist`, `resources\u002Flist`), so completion providers are not needed for them. Completion providers are used only for resource templates (URI variables) and prompt arguments.\n\nThe `#[CompletionProvider]` attribute supports three types of completion sources:\n\n#### 1. Custom Provider Classes\n\nFor complex completion logic, implement the `CompletionProviderInterface`:\n\n```php\nuse PhpMcp\\Server\\Contracts\\CompletionProviderInterface;\nuse PhpMcp\\Server\\Contracts\\SessionInterface;\nuse PhpMcp\\Server\\Attributes\\{McpResourceTemplate, CompletionProvider};\n\nclass UserIdCompletionProvider implements CompletionProviderInterface\n{\n    public function __construct(private DatabaseService $db) {}\n\n    public function getCompletions(string $currentValue, SessionInterface $session): array\n    {\n        \u002F\u002F Dynamic completion from database\n        return $this->db->searchUsers($currentValue);\n    }\n}\n\nclass UserService\n{\n    #[McpResourceTemplate(uriTemplate: 'user:\u002F\u002F{userId}\u002Fprofile')]\n    public function getUserProfile(\n        #[CompletionProvider(provider: UserIdCompletionProvider::class)]  \u002F\u002F Class string - resolved from container\n        string $userId\n    ): array {\n        return ['id' => $userId, 'name' => 'John Doe'];\n    }\n}\n```\n\nYou can also pass pre-configured provider instances:\n\n```php\nclass DocumentService  \n{\n    #[McpPrompt(name: 'document_prompt')]\n    public function generatePrompt(\n        #[CompletionProvider(provider: new UserIdCompletionProvider($database))]  \u002F\u002F Pre-configured instance\n        string $userId,\n        \n        #[CompletionProvider(provider: $this->categoryProvider)]  \u002F\u002F Instance from property\n        string $category\n    ): array {\n        return [['role' => 'user', 'content' => \"Generate document for user {$userId} in {$category}\"]];\n    }\n}\n```\n\n#### 2. Simple List Completions\n\nFor static completion lists, use the `values` parameter:\n\n```php\nuse PhpMcp\\Server\\Attributes\\{McpPrompt, CompletionProvider};\n\nclass ContentService\n{\n    #[McpPrompt(name: 'content_generator')]\n    public function generateContent(\n        #[CompletionProvider(values: ['blog', 'article', 'tutorial', 'guide', 'documentation'])]\n        string $contentType,\n        \n        #[CompletionProvider(values: ['beginner', 'intermediate', 'advanced', 'expert'])]\n        string $difficulty\n    ): array {\n        return [['role' => 'user', 'content' => \"Create a {$difficulty} level {$contentType}\"]];\n    }\n}\n```\n\n#### 3. Enum-Based Completions\n\nFor enum classes, use the `enum` parameter:\n\n```php\nenum Priority: string\n{\n    case LOW = 'low';\n    case MEDIUM = 'medium';\n    case HIGH = 'high';\n    case CRITICAL = 'critical';\n}\n\nenum Status  \u002F\u002F Unit enum (no backing values)\n{\n    case DRAFT;\n    case PUBLISHED;\n    case ARCHIVED;\n}\n\nclass TaskService\n{\n    #[McpTool(name: 'create_task')]\n    public function createTask(\n        string $title,\n        \n        #[CompletionProvider(enum: Priority::class)]  \u002F\u002F String-backed enum uses values\n        string $priority,\n        \n        #[CompletionProvider(enum: Status::class)]    \u002F\u002F Unit enum uses case names\n        string $status\n    ): array {\n        return ['id' => 123, 'title' => $title, 'priority' => $priority, 'status' => $status];\n    }\n}\n```\n\n#### Manual Registration with Completion Providers\n\n```php\n$server = Server::make()\n    ->withServerInfo('Completion Demo', '1.0.0')\n    \n    \u002F\u002F Using provider class (resolved from container)\n    ->withPrompt(\n        [DocumentHandler::class, 'generateReport'],\n        name: 'document_report'\n        \u002F\u002F Completion providers are auto-discovered from method attributes\n    )\n    \n    \u002F\u002F Using closure with inline completion providers\n    ->withPrompt(\n        function(\n            #[CompletionProvider(values: ['json', 'xml', 'csv', 'yaml'])]\n            string $format,\n            \n            #[CompletionProvider(enum: Priority::class)]\n            string $priority\n        ): array {\n            return [['role' => 'user', 'content' => \"Export data in {$format} format with {$priority} priority\"]];\n        },\n        name: 'export_data'\n    )\n    \n    ->build();\n```\n\n#### Completion Provider Resolution\n\nThe server automatically handles provider resolution:\n\n- **Class strings** (`MyProvider::class`) → Resolved from PSR-11 container with dependency injection\n- **Instances** (`new MyProvider()`) → Used directly as-is\n- **Values arrays** (`['a', 'b', 'c']`) → Automatically wrapped in `ListCompletionProvider`\n- **Enum classes** (`MyEnum::class`) → Automatically wrapped in `EnumCompletionProvider`\n\n> **Important**: Completion providers only offer suggestions to users in the MCP client interface. Users can still input any value, so always validate parameters in your handlers regardless of completion provider constraints.\n\n### Custom Dependency Injection\n\nYour MCP element handlers can use constructor dependency injection to access services like databases, APIs, or other business logic. When handlers have constructor dependencies, you must provide a pre-configured PSR-11 container that contains those dependencies.\n\nBy default, the server uses a `BasicContainer` - a simple implementation that attempts to auto-wire dependencies by instantiating classes with parameterless constructors. For dependencies that require configuration (like database connections), you can either manually add them to the BasicContainer or use a more advanced PSR-11 container like PHP-DI or Laravel's container.\n\n```php\nuse Psr\\Container\\ContainerInterface;\n\nclass DatabaseService\n{\n    public function __construct(private \\PDO $pdo) {}\n    \n    #[McpTool(name: 'query_users')]\n    public function queryUsers(): array\n    {\n        $stmt = $this->pdo->query('SELECT * FROM users');\n        return $stmt->fetchAll();\n    }\n}\n\n\u002F\u002F Option 1: Use the basic container and manually add dependencies\n$basicContainer = new \\PhpMcp\\Server\\Defaults\\BasicContainer();\n$basicContainer->set(\\PDO::class, new \\PDO('sqlite::memory:'));\n\n\u002F\u002F Option 2: Use any PSR-11 compatible container (PHP-DI, Laravel, etc.)\n$container = new \\DI\\Container();\n$container->set(\\PDO::class, new \\PDO('mysql:host=localhost;dbname=app', $user, $pass));\n\n$server = Server::make()\n    ->withContainer($basicContainer)  \u002F\u002F Handlers get dependencies auto-injected\n    ->build();\n```\n\n### Resource Subscriptions\n\n```php\nuse PhpMcp\\Schema\\ServerCapabilities;\n\n$server = Server::make()\n    ->withCapabilities(ServerCapabilities::make(\n        resourcesSubscribe: true,  \u002F\u002F Enable resource subscriptions\n        prompts: true,\n        tools: true\n    ))\n    ->build();\n\n\u002F\u002F In your resource handler, you can notify clients of changes:\n#[McpResource(uri: 'file:\u002F\u002Fconfig.json')]\npublic function getConfig(): array\n{\n    \u002F\u002F When config changes, notify subscribers\n    $this->notifyResourceChange('file:\u002F\u002Fconfig.json');\n    return ['setting' => 'value'];\n}\n```\n\n### Resumability and Event Store\n\nFor production deployments using `StreamableHttpServerTransport`, you can implement resumability with event sourcing by providing a custom event store:\n\n```php\nuse PhpMcp\\Server\\Contracts\\EventStoreInterface;\nuse PhpMcp\\Server\\Defaults\\InMemoryEventStore;\nuse PhpMcp\\Server\\Transports\\StreamableHttpServerTransport;\n\n\u002F\u002F Use the built-in in-memory event store (for development\u002Ftesting)\n$eventStore = new InMemoryEventStore();\n\n\u002F\u002F Or implement your own persistent event store\nclass DatabaseEventStore implements EventStoreInterface\n{\n    public function storeEvent(string $streamId, string $message): string\n    {\n        \u002F\u002F Store event in database and return unique event ID\n        return $this->database->insert('events', [\n            'stream_id' => $streamId,\n            'message' => $message,\n            'created_at' => now()\n        ]);\n    }\n\n    public function replayEventsAfter(string $lastEventId, callable $sendCallback): void\n    {\n        \u002F\u002F Replay events for resumability\n        $events = $this->database->getEventsAfter($lastEventId);\n        foreach ($events as $event) {\n            $sendCallback($event['id'], $event['message']);\n        }\n    }\n}\n\n\u002F\u002F Configure transport with event store\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',\n    port: 8080,\n    eventStore: new DatabaseEventStore()  \u002F\u002F Enable resumability\n);\n```\n\n### Custom Session Handlers\n\nImplement custom session storage by creating a class that implements `SessionHandlerInterface`:\n\n```php\nuse PhpMcp\\Server\\Contracts\\SessionHandlerInterface;\n\nclass DatabaseSessionHandler implements SessionHandlerInterface\n{\n    public function __construct(private \\PDO $db) {}\n\n    public function read(string $id): string|false\n    {\n        $stmt = $this->db->prepare('SELECT data FROM sessions WHERE id = ?');\n        $stmt->execute([$id]);\n        $session = $stmt->fetch(\\PDO::FETCH_ASSOC);\n        return $session ? $session['data'] : false;\n    }\n\n    public function write(string $id, string $data): bool\n    {\n        $stmt = $this->db->prepare(\n            'INSERT OR REPLACE INTO sessions (id, data, updated_at) VALUES (?, ?, ?)'\n        );\n        return $stmt->execute([$id, $data, time()]);\n    }\n\n    public function destroy(string $id): bool\n    {\n        $stmt = $this->db->prepare('DELETE FROM sessions WHERE id = ?');\n        return $stmt->execute([$id]);\n    }\n\n    public function gc(int $maxLifetime): array\n    {\n        $cutoff = time() - $maxLifetime;\n        $stmt = $this->db->prepare('DELETE FROM sessions WHERE updated_at \u003C ?');\n        $stmt->execute([$cutoff]);\n        return []; \u002F\u002F Return array of cleaned session IDs if needed\n    }\n}\n\n\u002F\u002F Use custom session handler\n$server = Server::make()\n    ->withSessionHandler(new DatabaseSessionHandler(), 3600)\n    ->build();\n```\n\n### Middleware Support\n\nBoth `HttpServerTransport` and `StreamableHttpServerTransport` support PSR-7 compatible middleware for intercepting and modifying HTTP requests and responses. Middleware allows you to extract common functionality like authentication, logging, CORS handling, and request validation into reusable components.\n\nMiddleware must be a valid PHP callable that accepts a PSR-7 `ServerRequestInterface` as the first argument and a `callable` as the second argument.\n\n```php\nuse Psr\\Http\\Message\\ServerRequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse React\\Promise\\PromiseInterface;\n\nclass AuthMiddleware\n{\n    public function __invoke(ServerRequestInterface $request, callable $next)\n    {\n        $apiKey = $request->getHeaderLine('Authorization');\n        if (empty($apiKey)) {\n            return new Response(401, [], 'Authorization required');\n        }\n        \n        $request = $request->withAttribute('user_id', $this->validateApiKey($apiKey));\n        $result = $next($request);\n        \n        return match (true) {\n            $result instanceof PromiseInterface => $result->then(fn($response) => $this->handle($response)),\n            $result instanceof ResponseInterface => $this->handle($result),\n            default => $result\n        };\n    }\n    \n    private function handle($response)\n    {\n        return $response instanceof ResponseInterface\n            ? $response->withHeader('X-Auth-Provider', 'mcp-server')\n            : $response;\n    }\n}\n\n$middlewares = [\n    new AuthMiddleware(),\n    new LoggingMiddleware(),\n    function(ServerRequestInterface $request, callable $next) {\n        $result = $next($request);\n        return match (true) {\n            $result instanceof PromiseInterface => $result->then(function($response) {\n                return $response instanceof ResponseInterface \n                    ? $response->withHeader('Access-Control-Allow-Origin', '*')\n                    : $response;\n            }),\n            $result instanceof ResponseInterface => $result->withHeader('Access-Control-Allow-Origin', '*'),\n            default => $result\n        };\n    }\n];\n\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',\n    port: 8080,\n    middlewares: $middlewares\n);\n```\n\n**Important Considerations:**\n\n- **Response Handling**: Middleware must handle both synchronous `ResponseInterface` and asynchronous `PromiseInterface` returns from `$next($request)`, since ReactPHP operates asynchronously\n- **Invokable Pattern**: The recommended pattern is to use invokable classes with a separate `handle()` method to process responses, making the async logic reusable\n- **Execution Order**: Middleware executes in the order provided, with the last middleware being closest to your MCP handlers\n\n### SSL Context Configuration\n\nFor HTTPS deployments of `StreamableHttpServerTransport`, configure SSL context options:\n\n```php\n$sslContext = [\n    'ssl' => [\n        'local_cert' => '\u002Fpath\u002Fto\u002Fcertificate.pem',\n        'local_pk' => '\u002Fpath\u002Fto\u002Fprivate-key.pem',\n        'verify_peer' => false,\n        'allow_self_signed' => true,\n    ]\n];\n\n$transport = new StreamableHttpServerTransport(\n    host: '0.0.0.0',\n    port: 8443,\n    sslContext: $sslContext\n);\n```\n\n> **SSL Context Reference**: For complete SSL context options, see the [PHP SSL Context Options documentation](https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Fcontext.ssl.php).\n## 🔍 Error Handling & Debugging\n\nThe server provides comprehensive error handling and debugging capabilities:\n\n### Exception Handling\n\nTool handlers can throw any PHP exception when errors occur. The server automatically converts these exceptions into proper JSON-RPC error responses for MCP clients.\n\n```php\n#[McpTool(name: 'divide_numbers')]\npublic function divideNumbers(float $dividend, float $divisor): float\n{\n    if ($divisor === 0.0) {\n        \u002F\u002F Any exception with descriptive message will be sent to client\n        throw new \\InvalidArgumentException('Division by zero is not allowed');\n    }\n    \n    return $dividend \u002F $divisor;\n}\n\n#[McpTool(name: 'calculate_factorial')]\npublic function calculateFactorial(int $number): int\n{\n    if ($number \u003C 0) {\n        throw new \\InvalidArgumentException('Factorial is not defined for negative numbers');\n    }\n    \n    if ($number > 20) {\n        throw new \\OverflowException('Number too large, factorial would cause overflow');\n    }\n    \n    \u002F\u002F Implementation continues...\n    return $this->factorial($number);\n}\n```\n\nThe server will convert these exceptions into appropriate JSON-RPC error responses that MCP clients can understand and display to users.\n\n### Logging and Debugging\n\n```php\nuse Psr\\Log\\LoggerInterface;\n\nclass DebugAwareHandler\n{\n    public function __construct(private LoggerInterface $logger) {}\n    \n    #[McpTool(name: 'debug_tool')]\n    public function debugTool(string $data): array\n    {\n        $this->logger->info('Processing debug tool', ['input' => $data]);\n        \n        \u002F\u002F For stdio transport, use STDERR for debug output\n        fwrite(STDERR, \"Debug: Processing data length: \" . strlen($data) . \"\\n\");\n        \n        return ['processed' => true];\n    }\n}\n```\n\n## 🚀 Production Deployment\n\nSince `$server->listen()` runs a persistent process, you can deploy it using any strategy that suits your infrastructure needs. The server can be deployed on VPS, cloud instances, containers, or any environment that supports long-running processes.\n\nHere are two popular deployment approaches to consider:\n\n### Option 1: VPS with Supervisor + Nginx (Recommended)\n\n**Best for**: Most production deployments, cost-effective, full control\n\n```bash\n# 1. Install your application on VPS\ngit clone https:\u002F\u002Fgithub.com\u002Fyourorg\u002Fyour-mcp-server.git \u002Fvar\u002Fwww\u002Fmcp-server\ncd \u002Fvar\u002Fwww\u002Fmcp-server\ncomposer install --no-dev --optimize-autoloader\n\n# 2. Install Supervisor\nsudo apt-get install supervisor\n\n# 3. Create Supervisor configuration\nsudo nano \u002Fetc\u002Fsupervisor\u002Fconf.d\u002Fmcp-server.conf\n```\n\n**Supervisor Configuration:**\n```ini\n[program:mcp-server]\nprocess_name=%(program_name)s_%(process_num)02d\ncommand=php \u002Fvar\u002Fwww\u002Fmcp-server\u002Fserver.php --transport=http --host=127.0.0.1 --port=8080\nautostart=true\nautorestart=true\nstopasgroup=true\nkillasgroup=true\nuser=www-data\nnumprocs=1\nredirect_stderr=true\nstdout_logfile=\u002Fvar\u002Flog\u002Fmcp-server.log\nstdout_logfile_maxbytes=10MB\nstdout_logfile_backups=3\n```\n\n**Nginx Configuration with SSL:**\n```nginx\n# \u002Fetc\u002Fnginx\u002Fsites-available\u002Fmcp-server\nserver {\n    listen 443 ssl http2;\n    listen [::]:443 ssl http2;\n    server_name mcp.yourdomain.com;\n\n    # SSL configuration\n    ssl_certificate \u002Fetc\u002Fletsencrypt\u002Flive\u002Fmcp.yourdomain.com\u002Ffullchain.pem;\n    ssl_certificate_key \u002Fetc\u002Fletsencrypt\u002Flive\u002Fmcp.yourdomain.com\u002Fprivkey.pem;\n    \n    # Security headers\n    add_header X-Frame-Options \"SAMEORIGIN\" always;\n    add_header X-Content-Type-Options \"nosniff\" always;\n    add_header X-XSS-Protection \"1; mode=block\" always;\n\n    # MCP Server proxy\n    location \u002F {\n        proxy_http_version 1.1;\n        proxy_set_header Host $http_host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        \n        # Important for SSE connections\n        proxy_buffering off;\n        proxy_cache off;\n        \n        proxy_pass http:\u002F\u002F127.0.0.1:8080\u002F;\n    }\n}\n\n# Redirect HTTP to HTTPS\nserver {\n    listen 80;\n    listen [::]:80;\n    server_name mcp.yourdomain.com;\n    return 301 https:\u002F\u002F$server_name$request_uri;\n}\n```\n\n**Start Services:**\n```bash\n# Enable and start supervisor\nsudo supervisorctl reread\nsudo supervisorctl update\nsudo supervisorctl start mcp-server:*\n\n# Enable and start nginx\nsudo systemctl enable nginx\nsudo systemctl restart nginx\n\n# Check status\nsudo supervisorctl status\n```\n\n**Client Configuration:**\n```json\n{\n  \"mcpServers\": {\n    \"my-server\": {\n      \"url\": \"https:\u002F\u002Fmcp.yourdomain.com\u002Fmcp\"\n    }\n  }\n}\n```\n\n### Option 2: Docker Deployment\n\n**Best for**: Containerized environments, Kubernetes, cloud platforms\n\n**Production Dockerfile:**\n```dockerfile\nFROM php:8.3-fpm-alpine\n\n# Install system dependencies\nRUN apk --no-cache add \\\n    nginx \\\n    supervisor \\\n    && docker-php-ext-enable opcache\n\n# Install PHP extensions for MCP\nRUN docker-php-ext-install pdo_mysql pdo_sqlite opcache\n\n# Create application directory\nWORKDIR \u002Fvar\u002Fwww\u002Fmcp\n\n# Copy application code\nCOPY . \u002Fvar\u002Fwww\u002Fmcp\nCOPY docker\u002Fnginx.conf \u002Fetc\u002Fnginx\u002Fnginx.conf\nCOPY docker\u002Fsupervisord.conf \u002Fetc\u002Fsupervisord.conf\nCOPY docker\u002Fphp.ini \u002Fusr\u002Flocal\u002Fetc\u002Fphp\u002Fconf.d\u002Fproduction.ini\n\n# Install Composer dependencies\nRUN composer install --no-dev --optimize-autoloader --no-interaction\n\n# Set permissions\nRUN chown -R www-data:www-data \u002Fvar\u002Fwww\u002Fmcp\n\n# Expose port\nEXPOSE 80\n\n# Start supervisor\nCMD [\"\u002Fusr\u002Fbin\u002Fsupervisord\", \"-c\", \"\u002Fetc\u002Fsupervisord.conf\"]\n```\n\n**docker-compose.yml:**\n```yaml\nservices:\n  mcp-server:\n    build: .\n    ports:\n      - \"8080:80\"\n    environment:\n      - MCP_ENV=production\n      - MCP_LOG_LEVEL=info\n    volumes:\n      - .\u002Fstorage:\u002Fvar\u002Fwww\u002Fmcp\u002Fstorage\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http:\u002F\u002Flocalhost\u002Fhealth\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n\n  # Optional: Add database if needed\n  database:\n    image: mysql:8.0\n    environment:\n      MYSQL_ROOT_PASSWORD: secure_password\n      MYSQL_DATABASE: mcp_server\n    volumes:\n      - mysql_data:\u002Fvar\u002Flib\u002Fmysql\n    restart: unless-stopped\n\nvolumes:\n  mysql_data:\n```\n\n### Security Best Practices\n\n1. **Firewall Configuration:**\n```bash\n# Only allow necessary ports\nsudo ufw allow ssh\nsudo ufw allow 80\nsudo ufw allow 443\nsudo ufw deny 8080  # MCP port should not be publicly accessible\nsudo ufw enable\n```\n\n2. **SSL\u002FTLS Setup:**\n```bash\n# Install Certbot for Let's Encrypt\nsudo apt install certbot python3-certbot-nginx\n\n# Generate SSL certificate\nsudo certbot --nginx -d mcp.yourdomain.com\n```\n\n## 📚 Examples & Use Cases\n\nExplore comprehensive examples in the [`examples\u002F`](.\u002Fexamples\u002F) directory:\n\n### Available Examples\n\n- **`01-discovery-stdio-calculator\u002F`** - Basic stdio calculator with attribute discovery\n- **`02-discovery-http-userprofile\u002F`** - HTTP server with user profile management  \n- **`03-manual-registration-stdio\u002F`** - Manual element registration patterns\n- **`04-combined-registration-http\u002F`** - Combining manual and discovered elements\n- **`05-stdio-env-variables\u002F`** - Environment variable handling\n- **`06-custom-dependencies-stdio\u002F`** - Dependency injection with task management\n- **`07-complex-tool-schema-http\u002F`** - Advanced schema validation examples\n- **`08-schema-showcase-streamable\u002F`** - Comprehensive schema feature showcase\n\n### Running Examples\n\n```bash\n# Navigate to an example directory\ncd examples\u002F01-discovery-stdio-calculator\u002F\n\n# Make the server executable\nchmod +x server.php\n\n# Run the server (or configure it in your MCP client)\n.\u002Fserver.php\n```\n\n## 🚧 Migration from v2.x\n\nIf migrating from version 2.x, note these key changes:\n\n### Schema Updates\n- Uses `php-mcp\u002Fschema` package for DTOs instead of internal classes\n- Content types moved to `PhpMcp\\Schema\\Content\\*` namespace\n- Updated method signatures for better type safety\n\n### Session Management\n- New session management with multiple backends\n- Use `->withSession()` or `->withSessionHandler()` for configuration\n- Sessions are now persistent across reconnections (with cache backend)\n\n### Transport Changes\n- New `StreamableHttpServerTransport` with resumability\n- Enhanced error handling and event sourcing\n- Better batch request processing\n\n## 🧪 Testing\n\n```bash\n# Install development dependencies\ncomposer install --dev\n\n# Run the test suite\ncomposer test\n\n# Run tests with coverage (requires Xdebug)\ncomposer test:coverage\n\n# Run code style checks\ncomposer lint\n```\n\n## 🤝 Contributing\n\nWe welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n## 📄 License\n\nThe MIT License (MIT). See [LICENSE](LICENSE) for details.\n\n## 🙏 Acknowledgments\n\n- Built on the [Model Context Protocol](https:\u002F\u002Fmodelcontextprotocol.io\u002F) specification\n- Powered by [ReactPHP](https:\u002F\u002Freactphp.org\u002F) for async operations\n- Uses [PSR standards](https:\u002F\u002Fwww.php-fig.org\u002F) for maximum interoperability\n","# PHP MCP 服务器 SDK\n\n[![Packagist 最新版本](https:\u002F\u002Fimg.shields.io\u002Fpackagist\u002Fv\u002Fphp-mcp\u002Fserver.svg?style=flat-square)](https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fphp-mcp\u002Fserver)\n[![总下载量](https:\u002F\u002Fimg.shields.io\u002Fpackagist\u002Fdt\u002Fphp-mcp\u002Fserver.svg?style=flat-square)](https:\u002F\u002Fpackagist.org\u002Fpackages\u002Fphp-mcp\u002Fserver)\n[![测试](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Fphp-mcp\u002Fserver\u002Ftests.yml?branch=main&style=flat-square)](https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Factions\u002Fworkflows\u002Ftests.yml)\n[![许可证](https:\u002F\u002Fimg.shields.io\u002Fpackagist\u002Fl\u002Fphp-mcp\u002Fserver.svg?style=flat-square)](LICENSE)\n\n**用于构建【模型上下文协议（MCP）】服务器的全面 PHP SDK。通过现代架构、丰富的测试以及灵活的传输选项，用 PHP 快速创建可投入生产的 MCP 服务器。**\n\n此 SDK 可让您将 PHP 应用程序的功能作为标准化的 MCP **工具**、**资源** 和**提示**公开，从而让 AI 助手（如 Anthropic 的 Claude、Cursor IDE、OpenAI 的 ChatGPT 等）能够以 MCP 标准与您的后端进行交互。\n\n## 🚀 主要特性\n\n- **🏗️ 现代架构**：采用 PHP 8.1+ 特性、PSR 标准和模块化设计\n- **📡 多种传输方式**：支持 `stdio`、`http+sse` 以及全新的**可流式 HTTP**，具备断点续传功能\n- **🎯 基于属性的定义**：使用 PHP 8 属性（`#[McpTool]`、`#[McpResource]` 等）实现零配置元素注册\n- **🔧 灵活的处理器**：支持闭包、类方法、静态方法和可调用类\n- **📝 智能模式生成**：根据方法签名自动生成 JSON 模式，可选使用 `#[Schema]` 属性增强功能\n- **⚡ 会话管理**：支持多种存储后端的高级会话处理\n- **🔄 事件驱动**：基于 ReactPHP，实现高并发和非阻塞操作  \n- **📊 批处理支持**：全面支持 JSON-RPC 批量请求\n- **💾 智能缓存**：对发现的元素进行智能缓存，手动覆盖优先\n- **🧪 补全提供者**：内置工具和提示的参数补全支持\n- **🔌 依赖注入**：完全支持 PSR-11 容器，并具备自动装配功能\n- **📋 全面测试**：丰富的测试套件，包含所有传输方式的集成测试\n\n本包支持【2025-03-26】版本的模型上下文协议，同时具备向后兼容性。\n\n## 📋 要求\n\n- **PHP** >= 8.1\n- **Composer**\n- **对于 HTTP 传输**：事件驱动的 PHP 环境（推荐使用 CLI）\n- **扩展**：`json`、`mbstring`、`pcre`（通常默认启用）\n\n## 📦 安装\n\n```bash\ncomposer require php-mcp\u002Fserver\n```\n\n> **💡 Laravel 用户**：建议使用 [`php-mcp\u002Flaravel`](https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Flaravel)，以获得更佳的框架集成、配置管理和 Artisan 命令支持。\n\n## ⚡ 快速入门：带发现功能的 Stdio 服务器\n\n本示例展示了最常见的使用模式——基于属性发现的 `stdio` 服务器。\n\n**1. 定义您的 MCP 元素**\n\n创建 `src\u002FCalculatorElements.php`：\n\n```php\n\u003C?php\n\nnamespace App;\n\nuse PhpMcp\\Server\\Attributes\\McpTool;\nuse PhpMcp\\Server\\Attributes\\Schema;\n\nclass CalculatorElements\n{\n    \u002F**\n     * 将两个数字相加。\n     * \n     * @param int $a 第一个数字\n     * @param int $b 第二个数字  \n     * @return int 两个数字之和\n     *\u002F\n    #[McpTool(name: 'add_numbers')]\n    public function add(int $a, int $b): int\n    {\n        return $a + $b;\n    }\n\n    \u002F**\n     * 计算幂并进行验证。\n     *\u002F\n    #[McpTool(name: 'calculate_power')]\n    public function power(\n        #[Schema(type: 'number', minimum: 0, maximum: 1000)]\n        float $base,\n        \n        #[Schema(type: 'integer', minimum: 0, maximum: 10)]\n        int $exponent\n    ): float {\n        return pow($base, $exponent);\n    }\n}\n```\n\n**2. 创建服务器脚本**\n\n创建 `mcp-server.php`：\n\n```php\n#!\u002Fusr\u002Fbin\u002Fenv php\n\u003C?php\n\ndeclare(strict_types=1);\n\nrequire_once __DIR__ . '\u002Fvendor\u002Fautoload.php';\n\nuse PhpMcp\\Server\\Server;\nuse PhpMcp\\Server\\Transports\\StdioServerTransport;\n\ntry {\n    \u002F\u002F 构建服务器配置\n    $server = Server::make()\n        ->withServerInfo('PHP 计算器服务器', '1.0.0') \n        ->build();\n\n    \u002F\u002F 通过属性发现 MCP 元素\n    $server->discover(\n        basePath: __DIR__,\n        scanDirs: ['src']\n    );\n\n    \u002F\u002F 通过 stdio 传输开始监听\n    $transport = new StdioServerTransport();\n    $server->listen($transport);\n\n} catch (\\Throwable $e) {\n    fwrite(STDERR, \"[严重错误] \" . $e->getMessage() . \"\\n\");\n    exit(1);\n}\n```\n\n**3. 配置您的 MCP 客户端**\n\n添加到您的客户端配置（例如 `.cursor\u002Fmcp.json`）：\n\n```json\n{\n    \"mcpServers\": {\n        \"php-calculator\": {\n            \"command\": \"php\",\n            \"args\": [\"\u002F绝对路径\u002F到\u002F您的\u002Fmcp-server.php\"]\n        }\n    }\n}\n```\n\n**4. 测试服务器**\n\n您的 AI 助手现在可以调用：\n- `add_numbers` —— 两个整数相加\n- `calculate_power` —— 计算幂并施加验证约束\n\n## 🏗️ 架构概览\n\nPHP MCP 服务器采用现代化的解耦架构：\n\n```\n┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐\n│   MCP 客户端    │◄──►│   传输方式      │◄──►│   协议          │\n│  (Claude 等)    │    │ (Stdio\u002FHTTP\u002FSSE) │    │   (JSON-RPC)    │\n└─────────────────┘    └──────────────────┘    └─────────────────┘\n                                                         │\n                       ┌─────────────────┐               │\n                       │ 会话管理器     │◄──────────────┤\n                       │ (多后端)        │               │\n                       └─────────────────┘               │\n                                                         │\n┌─────────────────┐    ┌──────────────────┐              │\n│   分发器        │◄───│   服务器核心     │◄─────────────┤\n│ (方法路由)      │    │   配置           │              │\n└─────────────────┘    └──────────────────┘              │\n         │                                               │\n         ▼                                               │\n┌─────────────────┐    ┌──────────────────┐              │\n│    注册表       │    │   元素           │◄─────────────┘\n│  (元素存储)     │◄──►│ (工具\u002F资源\u002F提示等)│\n└─────────────────┘    └──────────────────┘\n```\n\n### 核心组件\n\n- **`ServerBuilder`**：流畅的配置接口（`Server::make()->...->build()`）\n- **`Server`**：中央协调器，包含所有已配置的组件\n- **`Protocol`**：JSON-RPC 2.0 处理器，连接传输方式与核心逻辑\n- **`SessionManager`**：多后端会话存储（数组、缓存、自定义）\n- **`Dispatcher`**：方法路由与请求处理\n- **`Registry`**：元素存储，具备智能缓存与优先级规则\n- **`Elements`**：已注册的 MCP 组件（工具、资源、提示、模板）\n\n### 传输选项\n\n1. **`StdioServerTransport`**：用于直接启动客户端的标准 I\u002FO\n2. **`HttpServerTransport`**：用于 Web 集成的 HTTP + 服务器发送事件\n3. **`StreamableHttpServerTransport`**：增强型 HTTP，支持断点续传和事件溯源\n\n## ⚙️ 服务器配置\n\n### 基本配置\n\n```php\nuse PhpMcp\\Server\\Server;\nuse PhpMcp\\Schema\\ServerCapabilities;\n\n$server = Server::make()\n    ->withServerInfo('我的应用服务器', '2.1.0')\n    ->withCapabilities(ServerCapabilities::make(\n        resources: true,\n        resourcesSubscribe: true,\n        prompts: true,\n        tools: true\n    ))\n    ->withPaginationLimit(100)\n    ->build();\n```\n\n### 带依赖项的高级配置\n\n```php\nuse Psr\\Log\\Logger;\nuse Psr\\SimpleCache\\CacheInterface;\nuse Psr\\Container\\ContainerInterface;\n\n$server = Server::make()\n    ->withServerInfo('生产环境服务器', '1.0.0')\n    ->withLogger($myPsrLogger)                    \u002F\u002F PSR-3 日志记录器\n    ->withCache($myPsrCache)                      \u002F\u002F PSR-16 缓存  \n    ->withContainer($myPsrContainer)              \u002F\u002F PSR-11 容器\n    ->withSession('cache', 7200)                  \u002F\u002F 基于缓存的会话，TTL 2小时\n    ->withPaginationLimit(50)                     \u002F\u002F 限制列表响应\n    ->build();\n```\n\n### 会话管理选项\n\n```php\n\u002F\u002F 内存中会话（默认，非持久化）\n->withSession('array', 3600)\n\n\u002F\u002F 基于缓存的会话（重启后仍有效）  \n->withSession('cache', 7200)\n\n\u002F\u002F 自定义会话处理器（实现 SessionHandlerInterface）\n->withSessionHandler(new MyCustomSessionHandler(), 1800)\n```\n\n## 🎯 定义 MCP 元素\n\n服务器提供了两种强大的方式来定义 MCP 元素：**基于属性的发现**（推荐）和**手动注册**。两者可以结合使用，且手动注册优先。\n\n### 元素类型\n\n- **🔧 工具**：可执行的函数\u002F操作（例如 `calculate`、`send_email`、`query_database`）\n- **📄 资源**：静态内容\u002F数据（例如 `config:\u002F\u002Fsettings`、`file:\u002F\u002Freadme.txt`）\n- **📋 资源模板**：带有 URI 模式的动态资源（例如 `user:\u002F\u002F{id}\u002Fprofile`）  \n- **💬 提示**：对话开场白\u002F模板（例如 `summarize`、`translate`）\n\n### 1. 🏷️ 基于属性的发现（推荐）\n\n使用 PHP 8 属性将方法或可调用类标记为 MCP 元素。服务器将通过文件系统扫描来发现它们。\n\n```php\nuse PhpMcp\\Server\\Attributes\\{McpTool, McpResource, McpResourceTemplate, McpPrompt};\n\nclass UserManager\n{\n    \u002F**\n     * 创建新用户账户。\n     *\u002F\n    #[McpTool(name: 'create_user')]\n    public function createUser(string $email, string $password, string $role = 'user'): array\n    {\n        \u002F\u002F 创建用户逻辑\n        return ['id' => 123, 'email' => $email, 'role' => $role];\n    }\n\n    \u002F**\n     * 获取用户配置。\n     *\u002F\n    #[McpResource(\n        uri: 'config:\u002F\u002Fuser\u002Fsettings',\n        mimeType: 'application\u002Fjson'\n    )]\n    public function getUserConfig(): array\n    {\n        return ['theme' => 'dark', 'notifications' => true];\n    }\n\n    \u002F**\n     * 根据 ID 获取用户个人资料。\n     *\u002F\n    #[McpResourceTemplate(\n        uriTemplate: 'user:\u002F\u002F{userId}\u002Fprofile',\n        mimeType: 'application\u002Fjson'\n    )]\n    public function getUserProfile(string $userId): array\n    {\n        return ['id' => $userId, 'name' => 'John Doe'];\n    }\n\n    \u002F**\n     * 生成欢迎消息提示。\n     *\u002F\n    #[McpPrompt(name: 'welcome_user')]\n    public function welcomeUserPrompt(string $username, string $role): array\n    {\n        return [\n            ['role' => 'user', 'content' => \"为 {$username} 创建一条欢迎信息，角色为 {$role}\"]\n        ];\n    }\n}\n```\n\n**发现过程：**\n\n```php\n\u002F\u002F 先构建服务器\n$server = Server::make()\n    ->withServerInfo('我的应用服务器', '1.0.0')\n    ->build();\n\n\u002F\u002F 然后发现元素\n$server->discover(\n    basePath: __DIR__,\n    scanDirs: ['src\u002FHandlers', 'src\u002FServices'],  \u002F\u002F 需要扫描的目录\n    excludeDirs: ['src\u002FTests'],                  \u002F\u002F 需要跳过的目录\n    saveToCache: true                            \u002F\u002F 缓存结果（默认为 true）\n);\n```\n\n**可用属性：**\n\n- **`#[McpTool]`**：可执行的操作\n- **`#[McpResource]`**：可通过 URI 访问的静态内容\n- **`#[McpResourceTemplate]`**：带有 URI 模板的动态资源  \n- **`#[McpPrompt]`**：对话模板和提示生成器\n\n### 2. 🔧 手动注册\n\n在调用 `build()` 之前，使用 `ServerBuilder` 以编程方式注册元素。这在动态注册、闭包或您希望获得明确控制时非常有用。\n\n```php\nuse App\\Handlers\\{EmailHandler, ConfigHandler, UserHandler, PromptHandler};\nuse PhpMcp\\Schema\\{ToolAnnotations, Annotations};\n\n$server = Server::make()\n    ->withServerInfo('手动注册服务器', '1.0.0')\n    \n    \u002F\u002F 注册带有处理方法的工具\n    ->withTool(\n        [EmailHandler::class, 'sendEmail'],     \u002F\u002F 处理方法：[类, 方法]\n        name: 'send_email',                     \u002F\u002F 工具名称（可选）\n        description: '向用户发送电子邮件',     \u002F\u002F 描述（可选）\n        annotations: ToolAnnotations::make(     \u002F\u002F 注解（可选）\n            title: '发送电子邮件工具'\n        )\n    )\n    \n    \u002F\u002F 将可调用类注册为工具\n    ->withTool(UserHandler::class)             \u002F\u002F 处理方法：可调用类\n    \n    \u002F\u002F 将闭包注册为工具\n    ->withTool(\n        function(int $a, int $b): int {         \u002F\u002F 处理方法：闭包\n            return $a + $b;\n        },\n        name: 'add_numbers',\n        description: '将两个数字相加'\n    )\n    \n    \u002F\u002F 注册带有闭包的资源\n    ->withResource(\n        function(): array {                     \u002F\u002F 处理方法：闭包\n            return ['timestamp' => time(), 'server' => 'php-mcp'];\n        },\n        uri: 'config:\u002F\u002Fruntime\u002Fstatus',         \u002F\u002F URI（必填）\n        mimeType: 'application\u002Fjson'           \u002F\u002F MIME 类型（可选）\n    )\n    \n    \u002F\u002F 注册资源模板\n    ->withResourceTemplate(\n        [UserHandler::class, 'getUserProfile'],\n        uriTemplate: 'user:\u002F\u002F{userId}\u002Fprofile'  \u002F\u002F URI 模板（必填）\n    )\n    \n    \u002F\u002F 注册带有闭包的提示\n    ->withPrompt(\n        function(string $topic, string $tone = 'professional'): array {\n            return [\n                ['role' => 'user', 'content' => \"写一篇关于 {$topic} 的文章，语气为 {$tone}\"]\n            ];\n        },\n        name: 'writing_prompt'                  \u002F\u002F 提示名称（可选）\n    )\n    \n    ->build();\n```\n\n该服务器支持三种灵活的处理程序格式：`[ClassName::class, 'methodName']` 用于类方法处理程序，`InvokableClass::class` 用于可调用类处理程序（具有 `__invoke` 方法的类），以及任何 PHP 可调用对象，包括闭包、静态方法如 `[SomeClass::class, 'staticMethod']` 或函数名。基于类的处理程序通过配置的 PSR-11 容器进行解析，以实现依赖注入。手动注册的元素不会被缓存，并且优先于具有相同标识符的已发现元素。\n\n> [!重要]\n> 当使用闭包作为处理程序时，服务器仅根据 PHP 类型提示生成最小化的 JSON 模式，因为没有文档块或类上下文可用。若要获取包含验证约束、描述和格式的更详细模式，您可以选择以下两种方式：\n> \n> - 使用 [`#[Schema]` 属性](#-schema-generation-and-validation)以增强模式生成\n> - 在使用 `->withTool()` 注册工具时，提供自定义的 `$inputSchema` 参数\n\n### 🏆 元素优先级与发现\n\n**优先级规则：**\n- 手动注册的元素**始终**覆盖具有相同标识符的已发现\u002F已缓存元素\n- 已发现的元素会被缓存以提高性能（可配置）\n- 缓存会在每次重新发现时自动失效\n\n**发现流程：**\n\n```php\n$server->discover(\n    basePath: __DIR__,\n    scanDirs: ['src\u002FHandlers', 'src\u002FServices'],  \u002F\u002F 扫描这些目录\n    excludeDirs: ['tests', 'vendor'],            \u002F\u002F 跳过这些目录\n    force: false,                                \u002F\u002F 强制重新扫描（默认：false）\n    saveToCache: true                            \u002F\u002F 保存到缓存（默认：true）\n);\n```\n\n**缓存行为：**\n- 只有**已发现**的元素会被缓存（绝不会缓存手动注册的元素）\n- 缓存在 `build()` 期间自动加载（如果可用）\n- 新的 `discover()` 调用会清除并重建缓存\n- 使用 `force: true` 可绕过已运行发现检查\n\n## 🚀 运行服务器（传输方式）\n\n服务器核心与传输方式无关。根据您的部署需求选择合适的传输方式：\n\n### 1. 📟 Stdio 传输\n\n**最适合**：直接客户端执行、命令行工具、简单部署\n\n```php\nuse PhpMcp\\Server\\Transports\\StdioServerTransport;\n\n$server = Server::make()\n    ->withServerInfo('Stdio 服务器', '1.0.0')\n    ->build();\n\n$server->discover(__DIR__, ['src']);\n\n\u002F\u002F 创建 stdio 传输（默认使用 STDIN\u002FSTDOUT）\n$transport = new StdioServerTransport();\n\n\u002F\u002F 开始监听（阻塞调用）\n$server->listen($transport);\n```\n\n**客户端配置：**\n```json\n{\n    \"mcpServers\": {\n        \"my-php-server\": {\n            \"command\": \"php\",\n            \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fserver.php\"]\n        }\n    }\n}\n```\n\n> ⚠️ **重要提示**：使用 stdio 传输时，**切勿**在处理程序中向 `STDOUT` 写入内容（调试时请使用 `STDERR`）。`STDOUT` 保留用于 JSON-RPC 通信。\n\n### 2. 🌐 HTTP + 服务器发送事件传输（已弃用）\n\n> ⚠️ **注意**：此传输方式已在最新 MCP 协议版本中弃用，但仍保留以兼容旧版本。对于新项目，请使用 [StreamableHttpServerTransport](#3--streamable-http-transport-new)，它提供了增强功能和更好的协议合规性。\n\n**最适合**：需要向后兼容的旧应用\n\n```php\nuse PhpMcp\\Server\\Transports\\HttpServerTransport;\n\n$server = Server::make()\n    ->withServerInfo('HTTP 服务器', '1.0.0')\n    ->withLogger($logger)  \u002F\u002F 推荐用于 HTTP\n    ->build();\n\n$server->discover(__DIR__, ['src']);\n\n\u002F\u002F 创建 HTTP 传输\n$transport = new HttpServerTransport(\n    host: '127.0.0.1',      \u002F\u002F MCP 协议禁止使用 0.0.0.0\n    port: 8080,             \u002F\u002F 端口号\n    mcpPathPrefix: 'mcp'    \u002F\u002F URL 前缀 (\u002Fmcp\u002Fsse, \u002Fmcp\u002Fmessage)\n);\n\n$server->listen($transport);\n```\n\n**客户端配置：**\n```json\n{\n    \"mcpServers\": {\n        \"my-http-server\": {\n            \"url\": \"http:\u002F\u002Flocalhost:8080\u002Fmcp\u002Fsse\"\n        }\n    }\n}\n```\n\n**端点：**\n- **SSE 连接**：`GET \u002Fmcp\u002Fsse`\n- **消息发送**：`POST \u002Fmcp\u002Fmessage?clientId={clientId}`\n\n### 3. 🔄 可流式 HTTP 传输（推荐）\n\n**适用场景**：生产部署、远程 MCP 服务器、多客户端、可恢复连接\n\n```php\nuse PhpMcp\\Server\\Transports\\StreamableHttpServerTransport;\n\n$server = Server::make()\n    ->withServerInfo('Streamable Server', '1.0.0')\n    ->withLogger($logger)\n    ->withCache($cache)     \u002F\u002F 恢复功能所需\n    ->build();\n\n$server->discover(__DIR__, ['src']);\n\n\u002F\u002F 创建支持恢复功能的可流式传输\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',      \u002F\u002F MCP 协议禁止使用 0.0.0.0\n    port: 8080,\n    mcpPathPrefix: 'mcp',\n    enableJsonResponse: false,  \u002F\u002F 使用 SSE 流式传输（默认）\n    stateless: false            \u002F\u002F 启用无状态模式，适用于无会话客户端\n);\n\n$server->listen($transport);\n```\n\n**JSON 响应模式：**\n\n`enableJsonResponse` 选项控制响应的交付方式：\n\n- **`false`（默认）**：使用服务器发送事件（SSE）流式传输响应。适合处理时间较长的工具。\n- **`true`**：立即返回 JSON 响应，不开启 SSE 流。适用于执行速度快、无需流式传输的工具。\n\n```php\n\u002F\u002F 对于执行快速的工具，启用 JSON 模式\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',\n    port: 8080,\n    enableJsonResponse: true  \u002F\u002F 立即返回 JSON 响应\n);\n```\n\n**无状态模式：**\n\n对于会话管理存在问题的客户端，可启用无状态模式：\n\n```php\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',\n    port: 8080,\n    stateless: true  \u002F\u002F 每个请求独立处理\n);\n```\n\n在无状态模式下，会话 ID 在内部生成但不会暴露给客户端，每个请求都被视为独立请求，不会保留持久化会话状态。\n\n**特性：**\n- **可恢复连接**：客户端可重新连接并重播遗漏的事件\n- **事件溯源**：所有事件均存储以供重播\n- **JSON 模式**：可选仅返回 JSON 响应，适合快速工具\n- **增强会话管理**：持久化会话状态\n- **多客户端支持**：专为并发客户端设计\n- **无状态模式**：适用于简单客户端的无会话操作\n\n## 📋 模式生成与验证\n\n服务器会自动为工具参数生成 JSON 模式，采用一种复杂的优先级系统，结合 PHP 类型提示、文档块信息以及可选的 `#[Schema]` 属性。这些生成的模式既用于输入验证，也用于向 MCP 客户端提供模式信息。\n\n### 模式生成优先级\n\n服务器在生成模式时遵循以下优先级顺序：\n\n1. **带有 `definition` 的 `#[Schema]` 属性**：完全覆盖模式（最高优先级）\n2. **参数级别的 `#[Schema]` 属性**：针对特定参数的模式增强\n3. **方法级别的 `#[Schema]` 属性**：方法范围内的模式配置\n4. **PHP 类型提示 + 文档块**：从代码中自动推断（最低优先级）\n\n当 `Schema` 属性中提供了 `definition` 时，所有自动推断将被忽略，直接使用完整的定义。\n\n### 参数级别的模式属性\n\n```php\nuse PhpMcp\\Server\\Attributes\\{McpTool, Schema};\n\n#[McpTool(name: 'validate_user')]\npublic function validateUser(\n    #[Schema(format: 'email')]              \u002F\u002F PHP 已知是字符串\n    string $email,\n    \n    #[Schema(\n        pattern: '^[A-Z][a-z]+$',\n        description: '首字母大写的名称'\n    )]\n    string $name,\n    \n    #[Schema(minimum: 18, maximum: 120)]    \u002F\u002F PHP 已知是整数\n    int $age\n): bool {\n    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;\n}\n```\n\n### 方法级别的模式\n\n```php\n\u002F**\n * 处理用户数据并进行嵌套验证。\n *\u002F\n#[McpTool(name: 'create_user')]\n#[Schema(\n    properties: [\n        'profile' => [\n            'type' => 'object',\n            'properties' => [\n                'name' => ['type' => 'string', 'minLength' => 2],\n                'age' => ['type' => 'integer', 'minimum' => 18],\n                'email' => ['type' => 'string', 'format' => 'email']\n            ],\n            'required' => ['name', 'email']\n        ]\n    ],\n    required: ['profile']\n)]\npublic function createUser(array $userData): array\n{\n    \u002F\u002F PHP 类型提示提供基础的 'array' 类型\n    \u002F\u002F 方法级别的 Schema 添加对象结构验证\n    return ['id' => 123, 'status' => 'created'];\n}\n```\n\n### 完全模式覆盖（仅限方法级别）\n\n```php\n#[McpTool(name: 'process_api_request')]\n#[Schema(definition: [\n    'type' => 'object',\n    'properties' => [\n        'endpoint' => ['type' => 'string', 'format' => 'uri'],\n        'method' => ['type' => 'string', 'enum' => ['GET', 'POST', 'PUT', 'DELETE']],\n        'headers' => [\n            'type' => 'object',\n            'patternProperties' => [\n                '^[A-Za-z0-9-]+$' => ['type' => 'string']\n            ]\n        ]\n    ],\n    'required' => ['endpoint', 'method']\n])]\npublic function processApiRequest(string $endpoint, string $method, array $headers): array\n{\n    \u002F\u002F 当提供 definition 时，PHP 类型提示完全被忽略\n    \u002F\u002F 上述模式定义具有最高优先级\n    return ['status' => 'processed', 'endpoint' => $endpoint];\n}\n```\n\n> ⚠️ **重要提示**：完全模式覆盖应尽量少用。它会绕过所有自动模式推断，要求您手动定义整个 JSON 模式。只有在您对 JSON 模式规范非常熟悉且有复杂验证需求、无法通过优先级系统实现时，才使用此方式。大多数情况下，参数级别和方法级别的 `#[Schema]` 属性已能提供足够的灵活性。\n\n## 🎨 返回值格式化\n\n服务器会自动将您的处理器返回值格式化为合适的 MCP 内容类型：\n\n### 自动格式化\n\n```php\n\u002F\u002F 简单值会自动包装为 TextContent\npublic function getString(): string { return \"Hello World\"; }           \u002F\u002F → TextContent\npublic function getNumber(): int { return 42; }                        \u002F\u002F → TextContent  \npublic function getBool(): bool { return true; }                       \u002F\u002F → TextContent\npublic function getArray(): array { return ['key' => 'value']; }       \u002F\u002F → TextContent (JSON)\n\n\u002F\u002F 空值处理\npublic function getNull(): ?string { return null; }                    \u002F\u002F → TextContent(\"(null)\")\npublic function returnVoid(): void { \u002F* 无返回 *\u002F }                 \u002F\u002F → 空内容\n```\n\n### 高级内容类型\n\n```php\nuse PhpMcp\\Schema\\Content\\{TextContent, ImageContent, AudioContent, ResourceContent};\n\npublic function getFormattedCode(): TextContent\n{\n    return TextContent::code('\u003C?php echo \"Hello\";', 'php');\n}\n\npublic function getMarkdown(): TextContent  \n{\n    return TextContent::make('# 标题\\n\\n内容这里');\n}\n\npublic function getImage(): ImageContent\n{\n    return ImageContent::make(\n        data: base64_encode(file_get_contents('image.png')),\n        mimeType: 'image\u002Fpng'\n    );\n}\n\npublic function getAudio(): AudioContent\n{\n    return AudioContent::make(\n        data: base64_encode(file_get_contents('audio.mp3')),\n        mimeType: 'audio\u002Fmpeg'\n    );\n}\n```\n\n### 文件与流处理\n\n```php\n\u002F\u002F 文件对象会自动读取并格式化\npublic function getFileContent(): \\SplFileInfo\n{\n    return new \\SplFileInfo('\u002Fpath\u002Fto\u002Ffile.txt');  \u002F\u002F 自动检测 MIME 类型\n}\n\n\u002F\u002F 流资源会被完整读取\npublic function getStreamContent()\n{\n    $stream = fopen('\u002Fpath\u002Fto\u002Fdata.json', 'r');\n    return $stream;  \u002F\u002F 将自动读取并关闭\n}\n\n\u002F\u002F 结构化资源响应\npublic function getStructuredResource(): array\n{\n    return [\n        'text' => '文件内容这里',\n        'mimeType' => 'text\u002Fplain'\n    ];\n    \n    \u002F\u002F 或者用于二进制数据：\n    \u002F\u002F return [\n    \u002F\u002F     'blob' => base64_encode($binaryData),\n    \u002F\u002F     'mimeType' => 'application\u002Foctet-stream'\n    \u002F\u002F ];\n}\n```\n\n## 🔄 批量处理\n\n服务器会自动处理 JSON-RPC 批量请求：\n\n```php\n\u002F\u002F 客户端可在一次 HTTP 调用中发送多个请求：\n[\n    {\"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"tools\u002Fcall\", \"params\": {...}},\n    {\"jsonrpc\": \"2.0\", \"method\": \"notifications\u002Fping\"},              \u002F\u002F 通知\n    {\"jsonrpc\": \"2.0\", \"id\": \"2\", \"method\": \"tools\u002Fcall\", \"params\": {...}}\n]\n\n\u002F\u002F 服务器返回批量响应（不包括通知）：\n[\n    {\"jsonrpc\": \"2.0\", \"id\": \"1\", \"result\": {...}},\n    {\"jsonrpc\": \"2.0\", \"id\": \"2\", \"result\": {...}}\n]\n```\n\n## 🔧 高级功能\n\n### 补全提供程序\n\n补全提供程序使 MCP 客户端能够在用户界面中提供自动补全建议。它们专为**资源模板**和**提示**设计，以帮助用户发现模板变量或提示参数等动态部分的可用选项。\n\n> **注意**：工具和资源可通过标准 MCP 命令（`tools\u002Flist`、`resources\u002Flist`）进行查找，因此无需使用补全提供程序。补全提供程序仅用于资源模板（URI 变量）和提示参数。\n\n`#[CompletionProvider]` 属性支持三种类型的补全源：\n\n#### 1. 自定义提供程序类\n\n对于复杂的补全逻辑，实现 `CompletionProviderInterface`：\n\n```php\nuse PhpMcp\\Server\\Contracts\\CompletionProviderInterface;\nuse PhpMcp\\Server\\Contracts\\SessionInterface;\nuse PhpMcp\\Server\\Attributes\\{McpResourceTemplate, CompletionProvider};\n\nclass UserIdCompletionProvider implements CompletionProviderInterface\n{\n    public function __construct(private DatabaseService $db) {}\n\n    public function getCompletions(string $currentValue, SessionInterface $session): array\n    {\n        \u002F\u002F 从数据库获取动态补全\n        return $this->db->searchUsers($currentValue);\n    }\n}\n\nclass UserService\n{\n    #[McpResourceTemplate(uriTemplate: 'user:\u002F\u002F{userId}\u002Fprofile')]\n    public function getUserProfile(\n        #[CompletionProvider(provider: UserIdCompletionProvider::class)]  \u002F\u002F 类字符串 - 由容器解析\n        string $userId\n    ): array {\n        return ['id' => $userId, 'name' => 'John Doe'];\n    }\n}\n```\n\n您也可以传递预配置的提供程序实例：\n\n```php\nclass DocumentService  \n{\n    #[McpPrompt(name: 'document_prompt')]\n    public function generatePrompt(\n        #[CompletionProvider(provider: new UserIdCompletionProvider($database))]  \u002F\u002F 预配置实例\n        string $userId,\n        \n        #[CompletionProvider(provider: $this->categoryProvider)]  \u002F\u002F 属性中的实例\n        string $category\n    ): array {\n        return [['role' => 'user', 'content' => \"为用户 {$userId} 生成 {$category} 文档\"]];\n    }\n}\n```\n\n#### 2. 简单列表补全\n\n对于静态补全列表，使用 `values` 参数：\n\n```php\nuse PhpMcp\\Server\\Attributes\\{McpPrompt, CompletionProvider};\n\nclass ContentService\n{\n    #[McpPrompt(name: 'content_generator')]\n    public function generateContent(\n        #[CompletionProvider(values: ['blog', 'article', 'tutorial', 'guide', 'documentation'])]\n        string $contentType,\n        \n        #[CompletionProvider(values: ['beginner', 'intermediate', 'advanced', 'expert'])]\n        string $difficulty\n    ): array {\n        return [['role' => 'user', 'content' => \"创建一个 {$difficulty} 级别的 {$contentType}\"]];\n    }\n}\n```\n\n#### 3. 枚举类型补全\n\n对于枚举类，使用 `enum` 参数：\n\n```php\nenum Priority: string\n{\n    case LOW = 'low';\n    case MEDIUM = 'medium';\n    case HIGH = 'high';\n    case CRITICAL = 'critical';\n}\n\nenum Status  \u002F\u002F 单位枚举（无后备值）\n{\n    case DRAFT;\n    case PUBLISHED;\n    case ARCHIVED;\n}\n\nclass TaskService\n{\n    #[McpTool(name: 'create_task')]\n    public function createTask(\n        string $title,\n        \n        #[CompletionProvider(enum: Priority::class)]  \u002F\u002F 字符串支持的枚举使用 values\n        string $priority,\n        \n        #[CompletionProvider(enum: Status::class)]    \u002F\u002F 单位枚举使用 case 名称\n        string $status\n    ): array {\n        return ['id' => 123, 'title' => $title, 'priority' => $priority, 'status' => $status];\n    }\n}\n```\n\n#### 手动注册补全提供程序\n\n```php\n$server = Server::make()\n    ->withServerInfo('补全演示', '1.0.0')\n    \n    \u002F\u002F 使用提供程序类（由容器解析）\n    ->withPrompt(\n        [DocumentHandler::class, 'generateReport'],\n        name: 'document_report'\n        \u002F\u002F 补全提供程序会自动从方法属性中发现\n    )\n    \n    \u002F\u002F 使用闭包并内联补全提供程序\n    ->withPrompt(\n        function(\n            #[CompletionProvider(values: ['json', 'xml', 'csv', 'yaml'])]\n            string $format,\n            \n            #[CompletionProvider(enum: Priority::class)]\n            string $priority\n        ): array {\n            return [['role' => 'user', 'content' => \"以 {$format} 格式导出数据，优先级为 {$priority}\"]];\n        },\n        name: 'export_data'\n    )\n    \n    ->build();\n```\n\n#### 补全提供程序解析\n\n服务器会自动处理提供程序解析：\n\n- **类字符串** (`MyProvider::class`) → 通过 PSR-11 容器解析，并进行依赖注入\n- **实例** (`new MyProvider()`) → 直接原样使用\n- **值数组** (`['a', 'b', 'c']`) → 自动包装为 `ListCompletionProvider`\n- **枚举类** (`MyEnum::class`) → 自动包装为 `EnumCompletionProvider`\n\n> **重要提示**：补全提供程序仅在 MCP 客户端界面中为用户提供建议。用户仍可输入任意值，因此无论补全提供程序有何限制，您都应在处理器中始终对参数进行验证。\n\n### 自定义依赖注入\n\n您的 MCP 元素处理器可以使用构造函数依赖注入来访问数据库、API 或其他业务逻辑服务。当处理器具有构造函数依赖时，您必须提供一个预配置的 PSR-11 容器，其中包含这些依赖。\n\n默认情况下，服务器使用 `BasicContainer` —— 一种简单的实现，尝试通过实例化无参构造函数的类来自动注入依赖。对于需要配置的依赖（如数据库连接），您可以手动将其添加到 BasicContainer，或者使用更高级的 PSR-11 容器，例如 PHP-DI 或 Laravel 的容器。\n\n```php\nuse Psr\\Container\\ContainerInterface;\n\nclass DatabaseService\n{\n    public function __construct(private \\PDO $pdo) {}\n    \n    #[McpTool(name: 'query_users')]\n    public function queryUsers(): array\n    {\n        $stmt = $this->pdo->query('SELECT * FROM users');\n        return $stmt->fetchAll();\n    }\n}\n\n\u002F\u002F 选项 1：使用基本容器并手动添加依赖\n$basicContainer = new \\PhpMcp\\Server\\Defaults\\BasicContainer();\n$basicContainer->set(\\PDO::class, new \\PDO('sqlite::memory:'));\n\n\u002F\u002F 选项 2：使用任何兼容 PSR-11 的容器（PHP-DI、Laravel 等）\n$container = new \\DI\\Container();\n$container->set(\\PDO::class, new \\PDO('mysql:host=localhost;dbname=app', $user, $pass));\n\n$server = Server::make()\n    ->withContainer($basicContainer)  \u002F\u002F 处理器会自动注入依赖\n    ->build();\n```\n\n### 资源订阅\n\n```php\nuse PhpMcp\\Schema\\ServerCapabilities;\n\n$server = Server::make()\n    ->withCapabilities(ServerCapabilities::make(\n        resourcesSubscribe: true,  \u002F\u002F 启用资源订阅\n        prompts: true,\n        tools: true\n    ))\n    ->build();\n\n\u002F\u002F 在您的资源处理器中，您可以通知客户端发生的变化：\n#[McpResource(uri: 'file:\u002F\u002Fconfig.json')]\npublic function getConfig(): array\n{\n    \u002F\u002F 当配置发生变化时，通知订阅者\n    $this->notifyResourceChange('file:\u002F\u002Fconfig.json');\n    return ['setting' => 'value'];\n}\n```\n\n### 可恢复性和事件存储\n\n对于使用 `StreamableHttpServerTransport` 的生产部署，您可以通过提供自定义事件存储来实现可恢复性与事件溯源：\n\n```php\nuse PhpMcp\\Server\\Contracts\\EventStoreInterface;\nuse PhpMcp\\Server\\Defaults\\InMemoryEventStore;\nuse PhpMcp\\Server\\Transports\\StreamableHttpServerTransport;\n\n\u002F\u002F 使用内置的内存事件存储（用于开发和测试）\n$eventStore = new InMemoryEventStore();\n\n\u002F\u002F 或者实现您自己的持久化事件存储\nclass DatabaseEventStore implements EventStoreInterface\n{\n    public function storeEvent(string $streamId, string $message): string\n    {\n        \u002F\u002F 将事件存储到数据库并返回唯一事件ID\n        return $this->database->insert('events', [\n            'stream_id' => $streamId,\n            'message' => $message,\n            'created_at' => now()\n        ]);\n    }\n\n    public function replayEventsAfter(string $lastEventId, callable $sendCallback): void\n    {\n        \u002F\u002F 重放事件以实现可恢复性\n        $events = $this->database->getEventsAfter($lastEventId);\n        foreach ($events as $event) {\n            $sendCallback($event['id'], $event['message']);\n        }\n    }\n}\n\n\u002F\u002F 配置传输层并指定事件存储\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',\n    port: 8080,\n    eventStore: new DatabaseEventStore()  \u002F\u002F 启用可恢复性\n);\n```\n\n### 自定义会话处理器\n\n通过创建实现 `SessionHandlerInterface` 的类，您可以实现自定义会话存储：\n\n```php\nuse PhpMcp\\Server\\Contracts\\SessionHandlerInterface;\n\nclass DatabaseSessionHandler implements SessionHandlerInterface\n{\n    public function __construct(private \\PDO $db) {}\n\n    public function read(string $id): string|false\n    {\n        $stmt = $this->db->prepare('SELECT data FROM sessions WHERE id = ?');\n        $stmt->execute([$id]);\n        $session = $stmt->fetch(\\PDO::FETCH_ASSOC);\n        return $session ? $session['data'] : false;\n    }\n\n    public function write(string $id, string $data): bool\n    {\n        $stmt = $this->db->prepare(\n            'INSERT OR REPLACE INTO sessions (id, data, updated_at) VALUES (?, ?, ?)'\n        );\n        return $stmt->execute([$id, $data, time()]);\n    }\n\n    public function destroy(string $id): bool\n    {\n        $stmt = $this->db->prepare('DELETE FROM sessions WHERE id = ?');\n        return $stmt->execute([$id]);\n    }\n\n    public function gc(int $maxLifetime): array\n    {\n        $cutoff = time() - $maxLifetime;\n        $stmt = $this->db->prepare('DELETE FROM sessions WHERE updated_at \u003C ?');\n        $stmt->execute([$cutoff]);\n        return []; \u002F\u002F 如果需要，返回已清理的会话ID数组\n    }\n}\n\n\u002F\u002F 使用自定义会话处理器\n$server = Server::make()\n    ->withSessionHandler(new DatabaseSessionHandler(), 3600)\n    ->build();\n```\n\n### 中间件支持\n\n`HttpServerTransport` 和 `StreamableHttpServerTransport` 均支持符合 PSR-7 标准的中间件，用于拦截和修改 HTTP 请求与响应。中间件允许您将认证、日志记录、CORS 处理和请求验证等通用功能提取为可复用组件。\n\n中间件必须是一个有效的 PHP 可调用对象，它接受一个 PSR-7 的 `ServerRequestInterface` 作为第一个参数，以及一个 `callable` 作为第二个参数。\n\n```php\nuse Psr\\Http\\Message\\ServerRequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse React\\Promise\\PromiseInterface;\n\nclass AuthMiddleware\n{\n    public function __invoke(ServerRequestInterface $request, callable $next)\n    {\n        $apiKey = $request->getHeaderLine('Authorization');\n        if (empty($apiKey)) {\n            return new Response(401, [], 'Authorization required');\n        }\n        \n        $request = $request->withAttribute('user_id', $this->validateApiKey($apiKey));\n        $result = $next($request);\n        \n        return match (true) {\n            $result instanceof PromiseInterface => $result->then(fn($response) => $this->handle($response)),\n            $result instanceof ResponseInterface => $this->handle($response),\n            default => $result\n        };\n    }\n    \n    private function handle($response)\n    {\n        return $response instanceof ResponseInterface\n            ? $response->withHeader('X-Auth-Provider', 'mcp-server')\n            : $response;\n    }\n}\n\n$middlewares = [\n    new AuthMiddleware(),\n    new LoggingMiddleware(),\n    function(ServerRequestInterface $request, callable $next) {\n        $result = $next($request);\n        return match (true) {\n            $result instanceof PromiseInterface => $result->then(function($response) {\n                return $response instanceof ResponseInterface \n                    ? $response->withHeader('Access-Control-Allow-Origin', '*')\n                    : $response;\n            }),\n            $result instanceof ResponseInterface => $result->withHeader('Access-Control-Allow-Origin', '*'),\n            default => $result\n        };\n    }\n];\n\n$transport = new StreamableHttpServerTransport(\n    host: '127.0.0.1',\n    port: 8080,\n    middlewares: $middlewares\n);\n```\n\n**重要注意事项：**\n\n- **响应处理**：中间件必须同时处理 `$next($request)` 返回的同步 `ResponseInterface` 和异步 `PromiseInterface`，因为 ReactPHP 是异步运行的。\n- **可调用模式**：推荐使用可调用类，并单独定义 `handle()` 方法来处理响应，这样可以复用异步逻辑。\n- **执行顺序**：中间件按照提供的顺序执行，最后一个中间件最接近您的 MCP 处理器。\n\n### SSL 上下文配置\n\n对于 `StreamableHttpServerTransport` 的 HTTPS 部署，您可以配置 SSL 上下文选项：\n\n```php\n$sslContext = [\n    'ssl' => [\n        'local_cert' => '\u002Fpath\u002Fto\u002Fcertificate.pem',\n        'local_pk' => '\u002Fpath\u002Fto\u002Fprivate-key.pem',\n        'verify_peer' => false,\n        'allow_self_signed' => true,\n    ]\n];\n\n$transport = new StreamableHttpServerTransport(\n    host: '0.0.0.0',\n    port: 8443,\n    sslContext: $sslContext\n);\n```\n\n> **SSL 上下文参考**：有关完整的 SSL 上下文选项，请参阅 [PHP SSL 上下文选项文档](https:\u002F\u002Fwww.php.net\u002Fmanual\u002Fen\u002Fcontext.ssl.php)。\n## 🔍 错误处理与调试\n\n服务器提供了全面的错误处理与调试功能：\n\n### 异常处理\n\n工具处理器在出现错误时可以抛出任意 PHP 异常。服务器会自动将这些异常转换为适合 MCP 客户端的 JSON-RPC 错误响应。\n\n```php\n#[McpTool(name: 'divide_numbers')]\npublic function divideNumbers(float $dividend, float $divisor): float\n{\n    if ($divisor === 0.0) {\n        \u002F\u002F 包含描述性信息的任何异常都会发送给客户端\n        throw new \\InvalidArgumentException('除数不能为零');\n    }\n    \n    return $dividend \u002F $divisor;\n}\n\n#[McpTool(name: 'calculate_factorial')]\npublic function calculateFactorial(int $number): int\n{\n    if ($number \u003C 0) {\n        throw new \\InvalidArgumentException('负数没有阶乘定义');\n    }\n    \n    if ($number > 20) {\n        throw new \\OverflowException('数字过大，阶乘会导致溢出');\n    }\n    \n    \u002F\u002F 实现继续...\n    return $this->factorial($number);\n}\n```\n\n服务器会将这些异常转换为 MCP 客户端能够理解并显示给用户的适当 JSON-RPC 错误响应。\n\n### 日志记录与调试\n\n```php\nuse Psr\\Log\\LoggerInterface;\n\nclass DebugAwareHandler\n{\n    public function __construct(private LoggerInterface $logger) {}\n    \n    #[McpTool(name: 'debug_tool')]\n    public function debugTool(string $data): array\n    {\n        $this->logger->info('正在处理调试工具', ['input' => $data]);\n        \n        \u002F\u002F 对于标准输入输出传输，使用 STDERR 输出调试信息\n        fwrite(STDERR, \"调试：处理数据长度: \" . strlen($data) . \"\\n\");\n        \n        return ['processed' => true];\n    }\n}\n```\n\n## 🚀 生产环境部署\n\n由于 `$server->listen()` 运行的是一个持久进程，您可以根据自己的基础设施需求采用任何合适的策略进行部署。该服务器可以部署在 VPS、云实例、容器或任何支持长时间运行进程的环境中。\n\n以下是两种常见的部署方案供您参考：\n\n### 方案一：使用 Supervisor + Nginx 的 VPS（推荐）\n\n**适用场景**：大多数生产环境部署，性价比高，完全可控\n\n```bash\n# 1. 在 VPS 上安装您的应用\ngit clone https:\u002F\u002Fgithub.com\u002Fyourorg\u002Fyour-mcp-server.git \u002Fvar\u002Fwww\u002Fmcp-server\ncd \u002Fvar\u002Fwww\u002Fmcp-server\ncomposer install --no-dev --optimize-autoloader\n\n# 2. 安装 Supervisor\nsudo apt-get install supervisor\n\n# 3. 创建 Supervisor 配置文件\nsudo nano \u002Fetc\u002Fsupervisor\u002Fconf.d\u002Fmcp-server.conf\n```\n\n**Supervisor 配置文件：**\n```ini\n[program:mcp-server]\nprocess_name=%(program_name)s_%(process_num)02d\ncommand=php \u002Fvar\u002Fwww\u002Fmcp-server\u002Fserver.php --transport=http --host=127.0.0.1 --port=8080\nautostart=true\nautorestart=true\nstopasgroup=true\nkillasgroup=true\nuser=www-data\nnumprocs=1\nredirect_stderr=true\nstdout_logfile=\u002Fvar\u002Flog\u002Fmcp-server.log\nstdout_logfile_maxbytes=10MB\nstdout_logfile_backups=3\n```\n\n**Nginx 配置（带 SSL）：**\n```nginx\n# \u002Fetc\u002Fnginx\u002Fsites-available\u002Fmcp-server\nserver {\n    listen 443 ssl http2;\n    listen [::]:443 ssl http2;\n    server_name mcp.yourdomain.com;\n\n    # SSL 配置\n    ssl_certificate \u002Fetc\u002Fletsencrypt\u002Flive\u002Fmcp.yourdomain.com\u002Ffullchain.pem;\n    ssl_certificate_key \u002Fetc\u002Fletsencrypt\u002Flive\u002Fmcp.yourdomain.com\u002Fprivkey.pem;\n    \n    # 安全头设置\n    add_header X-Frame-Options \"SAMEORIGIN\" always;\n    add_header X-Content-Type-Options \"nosniff\" always;\n    add_header X-XSS-Protection \"1; mode=block\" always;\n\n    # MCP 服务器代理\n    location \u002F {\n        proxy_http_version 1.1;\n        proxy_set_header Host $http_host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        \n        # 对 SSE 连接很重要\n        proxy_buffering off;\n        proxy_cache off;\n        \n        proxy_pass http:\u002F\u002F127.0.0.1:8080\u002F;\n    }\n}\n\n# 将 HTTP 重定向到 HTTPS\nserver {\n    listen 80;\n    listen [::]:80;\n    server_name mcp.yourdomain.com;\n    return 301 https:\u002F\u002F$server_name$request_uri;\n}\n```\n\n**启动服务：**\n```bash\n# 启用并启动 Supervisor\nsudo supervisorctl reread\nsudo supervisorctl update\nsudo supervisorctl start mcp-server:*\n\n# 启用并启动 Nginx\nsudo systemctl enable nginx\nsudo systemctl restart nginx\n\n# 检查状态\nsudo supervisorctl status\n```\n\n**客户端配置：**\n```json\n{\n  \"mcpServers\": {\n    \"my-server\": {\n      \"url\": \"https:\u002F\u002Fmcp.yourdomain.com\u002Fmcp\"\n    }\n  }\n}\n```\n\n### 方案二：Docker 部署\n\n**适用场景**：容器化环境、Kubernetes、云平台\n\n**生产 Dockerfile：**\n```dockerfile\nFROM php:8.3-fpm-alpine\n\n# 安装系统依赖\nRUN apk --no-cache add \\\n    nginx \\\n    supervisor \\\n    && docker-php-ext-enable opcache\n\n# 安装 PHP 扩展以支持 MCP\nRUN docker-php-ext-install pdo_mysql pdo_sqlite opcache\n\n# 创建应用目录\nWORKDIR \u002Fvar\u002Fwww\u002Fmcp\n\n# 复制应用代码\nCOPY . \u002Fvar\u002Fwww\u002Fmcp\nCOPY docker\u002Fnginx.conf \u002Fetc\u002Fnginx\u002Fnginx.conf\nCOPY docker\u002Fsupervisord.conf \u002Fetc\u002Fsupervisord.conf\nCOPY docker\u002Fphp.ini \u002Fusr\u002Flocal\u002Fetc\u002Fphp\u002Fconf.d\u002Fproduction.ini\n\n# 安装 Composer 依赖\nRUN composer install --no-dev --optimize-autoloader --no-interaction\n\n# 设置权限\nRUN chown -R www-data:www-data \u002Fvar\u002Fwww\u002Fmcp\n\n# 暴露端口\nEXPOSE 80\n\n# 启动 Supervisor\nCMD [\"\u002Fusr\u002Fbin\u002Fsupervisord\", \"-c\", \"\u002Fetc\u002Fsupervisord.conf\"]\n```\n\n**docker-compose.yml：**\n```yaml\nservices:\n  mcp-server:\n    build: .\n    ports:\n      - \"8080:80\"\n    environment:\n      - MCP_ENV=production\n      - MCP_LOG_LEVEL=info\n    volumes:\n      - .\u002Fstorage:\u002Fvar\u002Fwww\u002Fmcp\u002Fstorage\n    restart: unless-stopped\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http:\u002F\u002Flocalhost\u002Fhealth\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n\n  # 可选：如果需要数据库，可添加\n  database:\n    image: mysql:8.0\n    environment:\n      MYSQL_ROOT_PASSWORD: secure_password\n      MYSQL_DATABASE: mcp_server\n    volumes:\n      - mysql_data:\u002Fvar\u002Flib\u002Fmysql\n    restart: unless-stopped\n\nvolumes:\n  mysql_data:\n```\n\n### 安全最佳实践\n\n1. **防火墙配置：**\n```bash\n# 只开放必要的端口\nsudo ufw allow ssh\nsudo ufw allow 80\nsudo ufw allow 443\nsudo ufw deny 8080  # MCP 端口不应对外公开\nsudo ufw enable\n```\n\n2. **SSL\u002FTLS 设置：**\n```bash\n# 安装 Certbot 以获取 Let's Encrypt 证书\nsudo apt install certbot python3-certbot-nginx\n\n# 生成 SSL 证书\nsudo certbot --nginx -d mcp.yourdomain.com\n```\n\n## 📚 示例与使用场景\n\n请查看 [`examples\u002F`](.\u002Fexamples\u002F) 目录中的完整示例：\n\n### 可用示例\n\n- **`01-discovery-stdio-calculator\u002F`** - 带属性发现的基本标准输入计算器\n- **`02-discovery-http-userprofile\u002F`** - 带用户个人资料管理的HTTP服务器  \n- **`03-manual-registration-stdio\u002F`** - 手动元素注册模式\n- **`04-combined-registration-http\u002F`** - 手动与发现元素的组合\n- **`05-stdio-env-variables\u002F`** - 环境变量处理\n- **`06-custom-dependencies-stdio\u002F`** - 带任务管理的依赖注入\n- **`07-complex-tool-schema-http\u002F`** - 高级模式验证示例\n- **`08-schema-showcase-streamable\u002F`** - 全面模式功能展示\n\n### 运行示例\n\n```bash\n# 切换到某个示例目录\ncd examples\u002F01-discovery-stdio-calculator\u002F\n\n# 使服务器可执行\nchmod +x server.php\n\n# 运行服务器（或在您的MCP客户端中进行配置）\n.\u002Fserver.php\n```\n\n## 🚧 从v2.x迁移\n\n如果要从版本2.x迁移，请注意以下关键变化：\n\n### 模式更新\n- 使用`php-mcp\u002Fschema`包来处理DTO，不再使用内部类\n- 内容类型已移至`PhpMcp\\Schema\\Content\\*`命名空间\n- 更新了方法签名，以提供更好的类型安全性\n\n### 会话管理\n- 新增多后端会话管理机制\n- 使用`->withSession()`或`->withSessionHandler()`进行配置\n- 会话现在可在重新连接时保持持久化（配合缓存后端）\n\n### 传输变更\n- 新增`StreamableHttpServerTransport`，支持断点续传\n- 增强了错误处理和事件溯源功能\n- 改进了批量请求处理能力\n\n## 🧪 测试\n\n```bash\n# 安装开发依赖\ncomposer install --dev\n\n# 运行测试套件\ncomposer test\n\n# 带覆盖率运行测试（需安装Xdebug）\ncomposer test:coverage\n\n# 运行代码风格检查\ncomposer lint\n```\n\n## 🤝 贡献\n\n我们欢迎贡献！请参阅[CONTRIBUTING.md](CONTRIBUTING.md)了解相关指南。\n\n## 📄 许可证\n\nMIT许可证（MIT）。详情请参阅[LICENSE](LICENSE)。\n\n## 🙏 致谢\n\n- 基于[模型上下文协议](https:\u002F\u002Fmodelcontextprotocol.io\u002F)规范构建\n- 由[ReactPHP](https:\u002F\u002Freactphp.org\u002F)提供异步操作支持\n- 采用[PSR标准](https:\u002F\u002Fwww.php-fig.org\u002F)以实现最大程度的互操作性","# PHP MCP Server SDK 快速上手指南\n\n本指南帮助中国开发者快速使用 **PHP MCP Server SDK** 构建符合 Model Context Protocol (MCP) 标准的服务端，使 AI 助手（如 Claude、Cursor、ChatGPT）能够调用你的 PHP 应用功能。\n\n## 环境准备\n\n在开始之前，请确保你的开发环境满足以下要求：\n\n*   **PHP 版本**: >= 8.1 (需开启 `json`, `mbstring`, `pcre` 扩展，通常默认开启)\n*   **包管理器**: Composer\n*   **运行环境**: \n    *   若使用 `stdio` 传输：任意 CLI 环境即可。\n    *   若使用 `HTTP\u002FSSE` 传输：推荐事件驱动环境 (如 ReactPHP)。\n*   **IDE\u002F客户端**: 支持 MCP 协议的客户端 (如 Cursor IDE, Claude Desktop 等)。\n\n> 💡 **Laravel 用户提示**: 如果你在使用 Laravel 框架，建议直接使用 [`php-mcp\u002Flaravel`](https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Flaravel) 包，它提供了更好的框架集成和 Artisan 命令支持。\n\n## 安装步骤\n\n使用 Composer 安装核心库。国内开发者若遇到下载速度慢的问题，可配置阿里云镜像源加速。\n\n**1. (可选) 配置国内镜像源**\n```bash\ncomposer config -g repo.packagist composer https:\u002F\u002Fmirrors.aliyun.com\u002Fcomposer\u002F\n```\n\n**2. 安装 SDK**\n在项目根目录执行：\n```bash\ncomposer require php-mcp\u002Fserver\n```\n\n## 基本使用\n\n以下示例展示如何创建一个基于 `stdio` 的最简 MCP 服务器，并通过属性注解自动注册工具。\n\n### 第一步：定义 MCP 工具\n\n创建文件 `src\u002FCalculatorElements.php`，使用 `#[McpTool]` 属性标记需要暴露给 AI 的方法。\n\n```php\n\u003C?php\n\nnamespace App;\n\nuse PhpMcp\\Server\\Attributes\\McpTool;\nuse PhpMcp\\Server\\Attributes\\Schema;\n\nclass CalculatorElements\n{\n    \u002F**\n     * 两数相加\n     * \n     * @param int $a 第一个数字\n     * @param int $b 第二个数字  \n     * @return int 求和结果\n     *\u002F\n    #[McpTool(name: 'add_numbers')]\n    public function add(int $a, int $b): int\n    {\n        return $a + $b;\n    }\n\n    \u002F**\n     * 计算幂次方（带参数验证）\n     *\u002F\n    #[McpTool(name: 'calculate_power')]\n    public function power(\n        #[Schema(type: 'number', minimum: 0, maximum: 1000)]\n        float $base,\n        \n        #[Schema(type: 'integer', minimum: 0, maximum: 10)]\n        int $exponent\n    ): float {\n        return pow($base, $exponent);\n    }\n}\n```\n\n### 第二步：创建服务器入口脚本\n\n创建文件 `mcp-server.php`，初始化服务器并扫描上述类。\n\n```php\n#!\u002Fusr\u002Fbin\u002Fenv php\n\u003C?php\n\ndeclare(strict_types=1);\n\nrequire_once __DIR__ . '\u002Fvendor\u002Fautoload.php';\n\nuse PhpMcp\\Server\\Server;\nuse PhpMcp\\Server\\Transports\\StdioServerTransport;\n\ntry {\n    \u002F\u002F 1. 构建服务器配置\n    $server = Server::make()\n        ->withServerInfo('PHP Calculator Server', '1.0.0') \n        ->build();\n\n    \u002F\u002F 2. 自动发现带有注解的 MCP 元素\n    $server->discover(\n        basePath: __DIR__,\n        scanDirs: ['src'] \u002F\u002F 扫描 src 目录\n    );\n\n    \u002F\u002F 3. 启动 stdio 监听\n    $transport = new StdioServerTransport();\n    $server->listen($transport);\n\n} catch (\\Throwable $e) {\n    fwrite(STDERR, \"[CRITICAL ERROR] \" . $e->getMessage() . \"\\n\");\n    exit(1);\n}\n```\n\n赋予执行权限：\n```bash\nchmod +x mcp-server.php\n```\n\n### 第三步：配置 MCP 客户端\n\n在你的 AI 客户端配置文件中添加该服务器。以 **Cursor IDE** 为例，编辑 `.cursor\u002Fmcp.json`：\n\n```json\n{\n    \"mcpServers\": {\n        \"php-calculator\": {\n            \"command\": \"php\",\n            \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fyour\u002Fmcp-server.php\"]\n        }\n    }\n}\n```\n> ⚠️ 注意：请将 `\u002Fabsolute\u002Fpath\u002Fto\u002Fyour\u002Fmcp-server.php` 替换为你本地文件的**绝对路径**。\n\n### 第四步：测试运行\n\n重启你的 AI 客户端或重新加载 MCP 服务。现在你可以直接在对话框中让 AI 执行以下操作：\n*   \"帮我计算 5 加 3\" (调用 `add_numbers`)\n*   \"计算 2 的 10 次方\" (调用 `calculate_power`)\n\nSDK 会自动处理参数验证、JSON Schema 生成以及与 AI 的通信协议。","某电商团队的 PHP 后端工程师需要将订单查询、库存校验等核心业务逻辑暴露给内部部署的 Claude 代码助手，以便开发人员能通过自然语言直接操作生产数据。\n\n### 没有 server 时\n- **开发效率低下**：每次新增功能都需手动编写繁琐的 JSON-RPC 解析代码和 Schema 定义，重复劳动多且易出错。\n- **架构耦合严重**：为了适配 AI 调用，不得不修改现有业务类结构，破坏了原本清晰的领域模型设计。\n- **并发性能瓶颈**：传统同步脚本难以处理多个 AI 助手的并发请求，容易导致阻塞，影响开发体验。\n- **维护成本高昂**：缺乏统一的会话管理和缓存机制，调试复杂，且无法利用 PHP 8 的新特性简化代码。\n\n### 使用 server 后\n- **零配置快速接入**：仅需在方法上添加 `#[McpTool]` 属性，server 即可自动注册工具并生成标准 JSON Schema，无需手写协议代码。\n- **非侵入式集成**：完全兼容现有类结构，支持闭包、静态方法及可调用类，业务逻辑与 AI 接口层彻底解耦。\n- **高并发异步处理**：基于 ReactPHP 构建的事件驱动架构，轻松支撑多个 IDE 插件同时发起的流式 HTTP 或 Stdio 请求。\n- **企业级特性完备**：内置智能缓存、会话管理及参数自动补全功能，结合 PSR-11 依赖注入，让生产级 MCP 服务开箱即用。\n\nserver 将复杂的 MCP 协议实现简化为简单的 PHP 属性标记，让后端团队能以最小代价赋予 AI 助手安全、高效地调用核心业务的能力。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fphp-mcp_server_2fa3a81e.png","php-mcp","PHP MCP","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Fphp-mcp_bb19cd12.png","Bringing the Model Context Protocol (MCP) to the PHP ecosystem",null,"https:\u002F\u002Fgithub.com\u002Fphp-mcp",[83],{"name":84,"color":85,"percentage":86},"PHP","#4F5D95",100,828,61,"2026-03-30T15:01:49","MIT","Linux, macOS, Windows","不需要 GPU","未说明",{"notes":95,"python":96,"dependencies":97},"这是一个 PHP SDK，不是 Python 工具。运行需要 PHP 8.1 及以上版本和 Composer。若使用 HTTP 传输模式，建议在 CLI（命令行）事件驱动环境下运行。Laravel 用户可参考专用的 php-mcp\u002Flaravel 包以获得更好的集成体验。","不适用",[98,99,100,101,102],"PHP >= 8.1","Composer","ext-json","ext-mbstring","ext-pcre",[13,15],"2026-03-27T02:49:30.150509","2026-04-06T06:56:29.441472",[107,112,117,122,127,131],{"id":108,"question_zh":109,"answer_zh":110,"source_url":111},9309,"如何在 Tool 处理函数中访问 PSR-7 中间件注入的用户 ID（如 auth user_id）？","由于构造函数依赖注入无法获取每请求的 PSR-7 属性，且直接在处理函数中添加 `ServerRequestInterface` 参数会改变 Tool 的 Schema，推荐的解决方案是将 `Context` 对象作为可选参数添加到 Tool 处理函数的末尾。这样可以在不破坏 Schema 的前提下访问上下文信息。\n\n示例代码：\n```php\npublic function searchContent(\n    #[Schema(type: 'string', description: '查询内容')]\n    string $query,\n    \u002F\u002F 其他参数...\n    ?Context $context = null \u002F\u002F 必须放在最后，且设为可选\n): array {\n    \u002F\u002F 通过 $context 访问相关信息\n}\n```\n注意：如果使用属性顺序约束，`Context` 必须是可选的或者放在所有必需参数之后。","https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fissues\u002F73",{"id":113,"question_zh":114,"answer_zh":115,"source_url":116},9310,"JSON Schema 中的 `date-time` 格式具体指什么？为什么我的日期字段验证失败？","`date-time` 格式遵循 RFC3339 标准。如果字段名包含 \"date\" 等词汇，Schema 生成器可能会自动推断该格式，从而要求输入必须是严格的 RFC3339 日期时间字符串。\n\n有效格式示例：\n- `YYYY-MM-DDTHH:MM:SSZ` (例如：2023-10-05T14:48:00Z)\n- `YYYY-MM-DDTHH:MM:SS+HH:MM` (带时区偏移)\n\n解决方案：\n1. 确保传入的日期字符串严格符合上述格式。\n2. 或者在 v2.1.0 及以上版本中，使用 `#[Schema]` 属性显式指定格式或避免自动推断：\n```php\n#[Schema(format: 'email')] \u002F\u002F 示例：显式指定其他格式\nstring $email;\n```\n3. 如果不需要日期格式，可以尝试重命名字段（例如去掉 \"_at\" 后缀）以避免自动推断。","https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fissues\u002F4",{"id":118,"question_zh":119,"answer_zh":120,"source_url":121},9311,"注册可调用类（Invokable Class）作为 Tool 处理器时出现 \"Function does not exist\" 错误怎么办？","这是一个已知的 Bug，当使用实现了 `__invoke` 方法的类作为 Tool 处理器时，旧版本代码在反射解析时会错误地尝试查找函数而非方法，导致 `ReflectionException`。\n\n解决方案：\n请升级 `php-mcp\u002Fserver` 包到最新版本（维护者已在收到报告后迅速修复了此问题）。修复后，系统将正确识别可调用类的方法签名，不再报错。","https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fissues\u002F46",{"id":123,"question_zh":124,"answer_zh":125,"source_url":126},9312,"是否支持标准的 PSR-15 中间件接口？如何复用现有的框架中间件？","早期版本使用了自定义的中间件签名 `(ServerRequestInterface $request, callable $next)`，这与标准的 PSR-15 `MiddlewareInterface` 不兼容，导致无法直接复用现有的认证、CORS 等中间件。\n\n更新进展：\n维护者已确认将原生支持 PSR-15 标准签名：\n```php\nfunction(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface\n```\n在更新后的版本中，您可以直接使用现有的 PSR-15 中间件（如 Spiral 框架中的中间件），无需编写适配包装器。如果您当前遇到此问题，建议检查是否已升级到包含此改进的最新开发版或发布版。","https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fissues\u002F64",{"id":128,"question_zh":129,"answer_zh":130,"source_url":111},9313,"如何将多个 Tool 捆绑到一个 PHP 类中并正确使用构造函数依赖注入？","可以通过将 Tool 定义在同一个类中，并使用数组语法 `->withTool([ClassName::class, 'methodName'])` 来注册它们。这种方式允许您在类的构造函数中进行依赖注入（例如注入 Application 容器）。\n\n示例结构：\n```php\nclass Content\n{\n    public function __construct(private Application $app) {}\n\n    #[McpTool(name: 'content.search', description: '搜索内容')]\n    public function searchContent(\n        #[Schema(type: 'string')] string $query,\n        ?Context $context = null\n    ): array {\n        \u002F\u002F 使用 $this->app 访问依赖\n        return ['results' => []];\n    }\n}\n\n\u002F\u002F 注册方式\n$server->withTool([Content::class, 'searchContent']);\n```\n注意：为了确保上下文（Context）能正确传递，建议将 `Context $context` 参数设为可选并放在参数列表的最后。",{"id":132,"question_zh":133,"answer_zh":134,"source_url":116},9314,"如何为字符串类型的参数指定特定的格式（如 email, uri 等）？","从 v2.1.0 版本开始，您可以通过 `#[Schema]` 属性为字符串类型添加额外的元数据，包括指定 `format`。\n\n使用方法：\n```php\nuse PhpMcp\\Server\\Attributes\\Schema;\n\npublic function myTool(\n    #[Schema(format: 'email', description: '用户邮箱')]\n    string $email,\n    \n    #[Schema(format: 'uri', description: '资源链接')]\n    string $url\n): void {\n    \u002F\u002F ...\n}\n```\n这将生成的 JSON Schema 中包含相应的 format 字段，帮助客户端进行更准确的验证和提示。",[136,141,146,151,156,161,166,171,176,181,186,191,196,201,206,211,216,221],{"id":137,"version":138,"summary_zh":139,"released_at":140},106681,"3.3.0","## What's Changed\r\n* Feat: Add stateless mode for StreamableHttpServerTransport by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F48\r\n* Fix: Make PCNTL extension optional for StdioServerTransport by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F49\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F3.2.2...3.3.0","2025-07-12T22:22:59",{"id":142,"version":143,"summary_zh":144,"released_at":145},106682,"3.2.2","## What's Changed\r\n* Fix Architecture graph by @szepeviktor in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F42\r\n* Fix: Correctly handle invokable class tool handlers by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F47\r\n\r\n## New Contributors\r\n* @szepeviktor made their first contribution in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F42\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F3.2.1...3.2.2","2025-07-09T12:21:31",{"id":147,"version":148,"summary_zh":149,"released_at":150},106683,"3.2.1","## What's Changed\r\n* feat:  use callable instead of Closure|array|string for handler type by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F41\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F3.2.0...3.2.1","2025-06-30T22:12:10",{"id":152,"version":153,"summary_zh":154,"released_at":155},106684,"3.2.0","## What's Changed\r\n* fix: resolve cache session handler index inconsistencies by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F36\r\n* feat: Add comprehensive callable handler support for closures, static methods, and invokable classes by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F38\r\n* feat: Enhanced Completion Providers with Values and Enum Support by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F40\r\n\r\n\r\n##  Upgrade Guide\r\n\r\nIf you're using the `CompletionProvider` attribute with the named `providerClass` parameter, consider updating to the new `provider` parameter for consistency:\r\n\r\n```php\r\n\u002F\u002F Before (still works)\r\n#[CompletionProvider(providerClass: UserProvider::class)]\r\n\r\n\u002F\u002F After (recommended)\r\n#[CompletionProvider(provider: UserProvider::class)]\r\n```\r\n\r\nThe old `providerClass` parameter continues to work for backward compatibility, but may be dropped in a future major version release. \r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F3.1.1...3.2.0","2025-06-30T21:30:28",{"id":157,"version":158,"summary_zh":159,"released_at":160},106685,"3.1.1","## What's Changed\r\n* Fix: implement proper MCP protocol version negotiation by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F35\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F3.1.0...3.1.1","2025-06-26T08:44:56",{"id":162,"version":163,"summary_zh":164,"released_at":165},106686,"3.1.0","## What's Changed\r\n* Refactor: expose session garbage collection method for integration by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F31\r\n* feat: add instructions in server initialization result by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F32\r\n* fix(cache): handle missing session in index for CacheSessionHandler by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F33\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F3.0.2...3.1.0","2025-06-25T22:57:44",{"id":167,"version":168,"summary_zh":169,"released_at":170},106687,"3.0.2","## What's Changed\r\n* fix: Registry cache clearing bug preventing effective caching by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F29\r\n* Fix ServerBuilder error handling for manual element registration by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F30\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F3.0.1...3.0.2","2025-06-25T03:42:49",{"id":172,"version":173,"summary_zh":174,"released_at":175},106688,"3.0.1","## What's Changed\r\n* Fix validation failure for MCP tools without parameters by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F28\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F3.0.0...3.0.1","2025-06-24T09:08:10",{"id":177,"version":178,"summary_zh":179,"released_at":180},106689,"3.0.0","This release brings support for the latest MCP protocol version along with enhanced schema generation, new transport capabilities, and streamlined APIs.\r\n\r\n## ✨ New Features\r\n\r\n* **StreamableHttpServerTransport**: New transport with resumability, event sourcing, and JSON response mode for production deployments\r\n* **Smart Schema Generation**: Automatic JSON schema generation from method signatures with optional `#[Schema]` attribute enhancements\r\n* **Completion Providers**: `#[CompletionProvider]` attribute for auto-completion in resource templates and prompts\r\n* **Batch Request Processing**: Full support for JSON-RPC 2.0 batch requests\r\n* **Enhanced Session Management**: Multiple session backends (array, cache, custom) with persistence and garbage collection\r\n\r\n## 🔥 Breaking Changes\r\n\r\n* **Schema Package Integration**: Now uses `php-mcp\u002Fschema` package for all DTOs, requests, responses, and content types\r\n* **Session Management**: `ClientStateManager` replaced with `SessionManager` and `Session` classes\r\n* **Component Reorganization**: `Support\\*` classes moved to `Utils\\*` namespace\r\n* **Request Processing**: `RequestHandler` renamed to `Dispatcher`\r\n\r\n*Note: Most of these changes are internal and won't affect your existing MCP element definitions and handlers.*\r\n\r\n## 🔧 Enhanced Features\r\n\r\n* **Improved Schema System**: The `#[Schema]` attribute can now be used at both method-level and parameter-level (previously parameter-level only)\r\n* **Better Error Handling**: Enhanced JSON-RPC error responses with proper status codes\r\n* **PSR-20 Clock Interface**: Time management with `SystemClock` implementation\r\n* **Event Store Interface**: Pluggable event storage for resumable connections\r\n\r\n## 📦 Dependencies\r\n\r\n* Now requires `php-mcp\u002Fschema` ^1.0\r\n* Enhanced PSR compliance (PSR-3, PSR-11, PSR-16, PSR-20)\r\n\r\n## 🚧 Migration Guide\r\n\r\n### Capabilities Configuration\r\n**Before:**\r\n```php\r\n->withCapabilities(Capabilities::forServer(\r\n    resourcesEnabled: true,\r\n    promptsEnabled: true,\r\n    toolsEnabled: true,\r\n    resourceSubscribe: true\r\n))\r\n```\r\n\r\n**After:**\r\n```php\r\n->withCapabilities(ServerCapabilities::make(\r\n    resources: true,\r\n    prompts: true,\r\n    tools: true,\r\n    resourcesSubscribe: true\r\n))\r\n```\r\n\r\n### Transport Upgrade (Optional)\r\nFor production HTTP deployments, consider upgrading to the new `StreamableHttpServerTransport`:\r\n\r\n**Before:**\r\n```php\r\n$transport = new HttpServerTransport(host: '127.0.0.1', port: 8080);\r\n```\r\n\r\n**After:**\r\n```php\r\n$transport = new StreamableHttpServerTransport(host: '127.0.0.1',  port: 8080);\r\n```\r\n\r\n## 📚 Documentation\r\n\r\n* Complete README rewrite with comprehensive examples and deployment guides\r\n* New production deployment section covering VPS, Docker, and SSL setup\r\n* Enhanced schema generation documentation\r\n* Migration guide for v2.x users\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F2.3.1...3.0.0","2025-06-21T19:12:06",{"id":182,"version":183,"summary_zh":184,"released_at":185},106690,"2.3.1","## What's Changed\r\n* Streamline Registry Notifications and Add Discovery Suppression Support by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F22\r\n* Disable registry notifications during manual registrations to prevent unwanted triggers\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F2.3.0...2.3.1","2025-06-13T11:06:31",{"id":187,"version":188,"summary_zh":189,"released_at":190},106691,"2.3.0","## What's Changed\r\n* Fix: Require react\u002Fpromise ^3.0 for Promise API Compatibility by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F18\r\n* Fix: Correct object serialization in FileCache using serialize\u002Funserialize by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F19\r\n* check the the header X-Forwarded-Proto for scheme by @bangnokia in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F14\r\n* Feat: Improve HttpServerTransport Extensibility via Protected Methods by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F20\r\n\r\n## New Contributors\r\n* @bangnokia made their first contribution in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F14\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F2.2.1...2.3.0","2025-06-12T12:24:36",{"id":192,"version":193,"summary_zh":194,"released_at":195},106692,"2.2.1","## What's Changed\r\n* Fix tool name generation for invokable classes with MCP attributes by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F13\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F2.2.0...2.2.1","2025-06-07T15:59:56",{"id":197,"version":198,"summary_zh":199,"released_at":200},106693,"2.2.0","## What's Changed\r\n\r\n*   feat(pagination): Added configuration for a server-wide pagination limit, enabling more controlled data retrieval for list-based MCP operations. This limit is utilized by the `RequestProcessor`.\r\n*   feat(handlers): Introduced `HandlerResolver` to provide more robust validation and resolution mechanisms for MCP element handlers, improving the reliability of element registration and invocation.\r\n*   refactor(server): Modified the server listening mechanism to allow initialization and transport binding without an immediately blocking event loop. This enhances flexibility for embedding the server or managing its lifecycle in diverse application environments.\r\n*   refactor(core): Performed general cleanup and enhancements to the internal architecture and dependencies, contributing to improved code maintainability and overall system stability.\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F2.1.0...2.2.0","2025-06-03T23:06:15",{"id":202,"version":203,"summary_zh":204,"released_at":205},106694,"2.1.0","## What's Changed\r\n* feat(schema): add Schema attributes and enhance DocBlock array type parsing by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F8\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F2.0.1...2.1.0","2025-05-17T16:01:31",{"id":207,"version":208,"summary_zh":209,"released_at":210},106695,"2.0.1","## What's Changed\r\n* Fix: Ensure react\u002Fhttp is a runtime dependency for HttpServerTransport by @CodeWithKyrian in https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fpull\u002F7\r\n\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F2.0.0...2.0.1","2025-05-11T18:41:19",{"id":212,"version":213,"summary_zh":214,"released_at":215},106696,"2.0.0","This release marks a significant architectural refactoring of the package, aimed at improving modularity, testability, flexibility, and aligning its structure more closely with the `php-mcp\u002Fclient` library. The core functionality remains, but the way servers are configured, run, and integrated has fundamentally changed.\r\n\r\n## What's Changed\r\n\r\n### Core Architecture Overhaul\r\n\r\n*   **Decoupled Design:** The server core logic is now separated from the transport (network\u002FIO) layer.\r\n    *   **`ServerBuilder`:** A new fluent builder (`Server::make()`) is the primary way to configure server identity, dependencies (Logger, Cache, Container, Loop), capabilities, and manually registered elements.\r\n    *   **`Server` Object:** The main `Server` class, created by the builder, now holds the configured core components (`Registry`, `Processor`, `ClientStateManager`, `Configuration`) but is transport-agnostic itself.\r\n    *   **`ServerTransportInterface`:** A new event-driven interface defines the contract for server-side transports (Stdio, Http). Transports are now responsible solely for listening and raw data transfer, emitting events for lifecycle and messages.\r\n    *   **`Protocol`:** A new internal class acts as a bridge, listening to events from a bound `ServerTransportInterface` and coordinating interactions with the `Processor` and `ClientStateManager`.\r\n*   **Explicit Server Execution:**\r\n    *   The old `$server->run(?string)` method is **removed**.\r\n    *   **`$server->listen(ServerTransportInterface $transport)`:** Introduced as the primary way to start a *standalone* server. It binds the `Protocol` to the provided transport, starts the listener, and runs the event loop (making it a blocking call).\r\n\r\n### Discovery and Caching Refinements\r\n\r\n*   **Explicit Discovery:** Attribute discovery is no longer triggered automatically during `build()`. You must now explicitly call `$server->discover(basePath: ..., scanDirs: ...)` *after* building the server instance if you want to find elements via attributes.\r\n*   **Caching Behavior:**\r\n    *   Only *discovered* elements are eligible for caching. Manually registered elements (via `ServerBuilder->with*` methods) are **never cached**.\r\n    *   The `Registry` attempts to load discovered elements from cache upon instantiation (during `ServerBuilder::build()`).\r\n    *   Calling `$server->discover()` will first clear any previously discovered\u002Fcached elements from the registry before scanning. It then saves the *newly discovered* results to the cache if enabled (`saveToCache: true`).\r\n    *   `Registry` cache methods renamed for clarity: `saveDiscoveredElementsToCache()` and `clearDiscoveredElements()`.\r\n    *   `Registry::isLoaded()` renamed to `discoveryRanOrCached()` for better clarity.\r\n*   **Manual vs. Discovered Precedence:** If an element is registered both manually and found via discovery\u002Fcache with the same identifier (name\u002FURI), the **manually registered version always takes precedence**.\r\n\r\n### Dependency Injection and Configuration\r\n\r\n*   **`ConfigurationRepositoryInterface` Removed:** This interface and its default implementation (`ArrayConfigurationRepository`) have been removed.\r\n*   **`Configuration` Value Object:** A new `PhpMcp\\Server\\Configuration` readonly value object bundles core dependencies (Logger, Loop, Cache, Container, Server Info, Capabilities, TTLs) assembled by the `ServerBuilder`.\r\n*   **Simplified Dependencies:** Core components (`Registry`, `Processor`, `ClientStateManager`, `DocBlockParser`, `Discoverer`) now have simpler constructors, accepting direct dependencies.\r\n*   **PSR-11 Container Role:** The container provided via `ServerBuilder->withContainer()` (or the default `BasicContainer`) is now primarily used by the `Processor` to resolve *user-defined handler classes* and their dependencies.\r\n*   **Improved `BasicContainer`:** The default DI container (`PhpMcp\\Server\\Defaults\\BasicContainer`) now supports simple constructor auto-wiring.\r\n*   **`ClientStateManager` Default Cache:** If no `CacheInterface` is provided to the `ClientStateManager`, it now defaults to an in-memory `PhpMcp\\Server\\Defaults\\ArrayCache`.\r\n\r\n### Schema Generation and Validation\r\n\r\n*   **Removed Optimistic String Format Inference:** The `SchemaGenerator` no longer automatically infers JSON Schema `format` keywords (like \"date-time\", \"email\") for string parameters. This makes default schemas less strict, avoiding validation issues for users with simpler string formats. Specific format validation should now be handled within tool\u002Fresource methods or via future explicit schema annotation features.\r\n*   **Improved Tool Call Validation Error Messages:** When `tools\u002Fcall` parameters fail schema validation, the JSON-RPC error response now includes a more informative summary message detailing the specific validation failures, in addition to the structured error data.\r\n\r\n\r\n### Transports\r\n\r\n*   **New Implementations:** Introduced `PhpMcp\\Server\\Transports\\StdioServerTranspor","2025-05-11T17:50:04",{"id":217,"version":218,"summary_zh":219,"released_at":220},106697,"1.1.0","## Added\r\n\r\n*   **Manual Element Registration:** Added fluent methods `withTool()`, `withResource()`, `withPrompt()`, and `withResourceTemplate()` to the `Server` class. This allows programmatic registration of MCP elements as an alternative or supplement to attribute discovery. Both `[ClassName::class, 'methodName']` array handlers and invokable class string handlers are supported.\r\n*   **Invokable Class Attribute Discovery:** The server's discovery mechanism now supports placing `#[Mcp*]` attributes directly on invokable PHP class definitions (classes with a public `__invoke` method). The `__invoke` method will be used as the handler.\r\n*   **Discovery Path Configuration:** Added `withBasePath()`, `withScanDirectories()`, and `withExcludeDirectories()` methods to the `Server` class for finer control over which directories are scanned during attribute discovery.\r\n\r\n## Changed\r\n\r\n*   **Dependency Injection:** Refactored internal dependency management. Core server components (`Processor`, `Registry`, `TransportState`, etc.) now resolve `LoggerInterface`, `CacheInterface`, and `ConfigurationRepositoryInterface` Just-In-Time from the provided PSR-11 container. See **Breaking Changes** for implications.\r\n*   **Default Logging Behavior:** Logging is now **disabled by default**. To enable logging, provide a `LoggerInterface` implementation via `withLogger()` (when using the default container) or by registering it within your custom PSR-11 container.\r\n*   **Transport Handler Constructors:** Transport Handlers (e.g., `StdioTransportHandler`, `HttpTransportHandler`) now primarily accept the `Server` instance in their constructor, simplifying their instantiation.\r\n\r\n## Fixed\r\n\r\n*   Prevented potential \"Constant STDERR not defined\" errors in non-CLI environments by changing the default logger behavior (see Changed section).\r\n\r\n## Updated\r\n\r\n*   Extensively updated `README.md` to document manual registration, invokable class discovery, the dependency injection overhaul, discovery path configuration, transport handler changes, and the new default logging behavior.\r\n\r\n## Breaking Changes\r\n\r\n*   **Dependency Injection Responsibility:** Due to the DI refactoring, if you provide a custom PSR-11 container using `withContainer()`, you **MUST** ensure that your container is configured to provide implementations for `LoggerInterface`, `CacheInterface`, and `ConfigurationRepositoryInterface`. The server relies on being able to fetch these from the container.\r\n*   **`withLogger\u002FCache\u002FConfig` Behavior with Custom Container:** When a custom container is provided via `withContainer()`, calls to `->withLogger()`, `->withCache()`, or `->withConfig()` on the `Server` instance will **not** override the services resolved from *your* container during runtime. Configuration for these core services must be done directly within your custom container setup.\r\n*   **Transport Handler Constructor Signatures:** The constructor signatures for `StdioTransportHandler`, `HttpTransportHandler`, and `ReactPhpHttpTransportHandler` have changed. They now primarily require the `Server` instance. Update any direct instantiations of these handlers accordingly.\r\n\r\n**Full Changelog**: https:\u002F\u002Fgithub.com\u002Fphp-mcp\u002Fserver\u002Fcompare\u002F1.0.0...1.1.0","2025-05-01T16:59:51",{"id":222,"version":223,"summary_zh":224,"released_at":225},106698,"1.0.0","## Release v1.0.0 - Initial Release\r\n\r\n🚀 **Initial release of PHP MCP SERVER!**\r\n\r\nThis release introduces the core implementation of the Model Context Protocol (MCP) server for PHP applications. The goal is to provide a robust, flexible, and developer-friendly way to expose parts of your PHP application as MCP Tools, Resources, and Prompts, enabling standardized communication with AI assistants like Claude, Cursor, and others.\r\n\r\n### ✨ Key Features:\r\n\r\n*   **Attribute-Based Definitions:** Easily define MCP Tools (`#[McpTool]`), Resources (`#[McpResource]`, `#[McpResourceTemplate]`), and Prompts (`#[McpPrompt]`) using PHP 8 attributes directly on your methods.\r\n*   **Automatic Metadata Inference:** Leverages method signatures (parameters, type hints) and DocBlocks (`@param`, `@return`, summaries) to automatically generate MCP schemas and descriptions, minimizing boilerplate.\r\n*   **PSR Compliance:** Integrates seamlessly with standard PHP interfaces:\r\n    *   `PSR-3` (LoggerInterface) for flexible logging.\r\n    *   `PSR-11` (ContainerInterface) for dependency injection and class resolution.\r\n    *   `PSR-16` (SimpleCacheInterface) for caching discovered elements and transport state.\r\n*   **Automatic Discovery:** Scans configured directories to find and register your annotated MCP elements.\r\n*   **Flexible Configuration:** Uses a configuration repository (`ConfigurationRepositoryInterface`) for fine-grained control over server behaviour, capabilities, and caching.\r\n*   **Multiple Transports:**\r\n    *   Built-in support for the `stdio` transport, ideal for command-line driven clients.\r\n    *   Includes `HttpTransportHandler` components for building standard `http` (HTTP+SSE) transports (requires integration into an HTTP server).\r\n    *   Provides `ReactPhpHttpTransportHandler` for seamless integration with asynchronous ReactPHP applications.\r\n*   **Protocol Support:** Implements the `2024-11-05` version of the Model Context Protocol.\r\n*   **Framework Agnostic:** Designed to work in vanilla PHP projects or integrated into any framework.\r\n\r\n### 🚀 Getting Started\r\n\r\nPlease refer to the [README.md](README.md) for detailed installation instructions, usage examples, and core concepts. Sample implementations for `stdio` and `reactphp` are available in the `samples\u002F` directory.\r\n\r\n### ⚠️ Important Notes\r\n\r\n*   When implementing the `http` transport using `HttpTransportHandler`, be aware of the critical server environment requirements detailed in the README regarding concurrent request handling for SSE. Standard synchronous PHP servers (like `php artisan serve` or basic Apache\u002FNginx setups) are generally **not suitable** without proper configuration for concurrency (e.g., PHP-FPM with multiple workers, Octane, Swoole, ReactPHP, RoadRunner, FrankenPHP).\r\n\r\n### Future Plans\r\n\r\nWhile this package focuses on the server implementation, future projects within the `php-mcp` organization may include client libraries and other utilities related to MCP in PHP.","2025-04-28T12:29:51"]