SKILL.md
readonlyread-only
name
php-mcp-server-generator
description
使用官方 PHP SDK 生成一個完整的 PHP Model Context Protocol 伺服器專案,包含工具、資源、提示詞和測試
PHP MCP Server Generator
你是一個 PHP MCP 伺服器生成器。使用官方 PHP SDK 建立一個完整、可上線的 PHP MCP 伺服器專案。
專案需求
詢問使用者:
- 專案名稱(例如 "my-mcp-server")
- 伺服器描述(例如 "一個檔案管理 MCP 伺服器")
- 傳輸類型(stdio、http 或兩者)
- 要包含的工具(例如 "檔案讀取"、"檔案寫入"、"列出目錄")
- 是否包含資源和提示詞
- PHP 版本(需 8.2 以上)
專案結構
{project-name}/
├── composer.json
├── .gitignore
├── README.md
├── server.php
├── src/
│ ├── Tools/
│ │ └── {ToolClass}.php
│ ├── Resources/
│ │ └── {ResourceClass}.php
│ ├── Prompts/
│ │ └── {PromptClass}.php
│ └── Providers/
│ └── {CompletionProvider}.php
└── tests/
└── ToolsTest.php
檔案範本
composer.json
{
"name": "your-org/{project-name}",
"description": "{Server description}",
"type": "project",
"require": {
"php": "^8.2",
"mcp/sdk": "^0.1"
},
"require-dev": {
"phpunit/phpunit": "^10.0",
"symfony/cache": "^6.4"
},
"autoload": {
"psr-4": {
"App\\\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\\\": "tests/"
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
}
}
.gitignore
/vendor
/cache
composer.lock
.phpunit.cache
phpstan.neon
README.md
# {Project Name}
{Server description}
## 需求
- PHP 8.2 或更高版本
- Composer
## 安裝
```bash
composer install
使用方式
啟動伺服器(Stdio)
php server.php
在 Claude Desktop 中設定
{
"mcpServers": {
"{project-name}": {
"command": "php",
"args": ["/absolute/path/to/server.php"]
}
}
}
測試
vendor/bin/phpunit
工具
- {tool_name}:{Tool description}
開發
使用 MCP Inspector 測試:
npx @modelcontextprotocol/inspector php server.php
#### server.php
```php
#!/usr/bin/env php
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use Mcp\Server;
use Mcp\Server\Transport\StdioTransport;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Psr16Cache;
// 設定快取以用於探索
$cache = new Psr16Cache(new FilesystemAdapter('mcp-discovery', 3600, __DIR__ . '/cache'));
// 建立含探索功能的伺服器
$server = Server::builder()
->setServerInfo('{Project Name}', '1.0.0')
->setDiscovery(
basePath: __DIR__,
scanDirs: ['src'],
excludeDirs: ['vendor', 'tests', 'cache'],
cache: $cache
)
->build();
// 使用 stdio 傳輸執行
$transport = new StdioTransport();
$server->run($transport);
src/Tools/ExampleTool.php
<?php
declare(strict_types=1);
namespace App\Tools;
use Mcp\Capability\Attribute\McpTool;
use Mcp\Capability\Attribute\Schema;
class ExampleTool
{
/**
* 使用提供的名稱進行問候。
*
* @param string $name 要問候的名稱
* @return string 問候訊息
*/
#[McpTool]
public function greet(string $name): string
{
return "Hello, {$name}!";
}
/**
* 執行算術計算。
*/
#[McpTool(name: 'calculate')]
public function performCalculation(
float $a,
float $b,
#[Schema(pattern: '^(add|subtract|multiply|divide)$')]
string $operation
): float {
return match($operation) {
'add' => $a + $b,
'subtract' => $a - $b,
'multiply' => $a * $b,
'divide' => $b != 0 ? $a / $b :
throw new \InvalidArgumentException('Division by zero'),
default => throw new \InvalidArgumentException('Invalid operation')
};
}
}
src/Resources/ConfigResource.php
<?php
declare(strict_types=1);
namespace App\Resources;
use Mcp\Capability\Attribute\McpResource;
class ConfigResource
{
/**
* 提供應用程式設定。
*/
#[McpResource(
uri: 'config://app/settings',
name: 'app_config',
mimeType: 'application/json'
)]
public function getConfiguration(): array
{
return [
'version' => '1.0.0',
'environment' => 'production',
'features' => [
'logging' => true,
'caching' => true
]
];
}
}
src/Resources/DataProvider.php
<?php
declare(strict_types=1);
namespace App\Resources;
use Mcp\Capability\Attribute\McpResourceTemplate;
class DataProvider
{
/**
* 根據類別和 ID 提供資料。
*/
#[McpResourceTemplate(
uriTemplate: 'data://{category}/{id}',
name: 'data_resource',
mimeType: 'application/json'
)]
public function getData(string $category, string $id): array
{
// 範例資料擷取
return [
'category' => $category,
'id' => $id,
'data' => "Sample data for {$category}/{$id}"
];
}
}
src/Prompts/PromptGenerator.php
<?php
declare(strict_types=1);
namespace App\Prompts;
use Mcp\Capability\Attribute\McpPrompt;
use Mcp\Capability\Attribute\CompletionProvider;
class PromptGenerator
{
/**
* 產生程式碼審查提示詞。
*/
#[McpPrompt(name: 'code_review')]
public function reviewCode(
#[CompletionProvider(values: ['php', 'javascript', 'python', 'go', 'rust'])]
string $language,
string $code,
#[CompletionProvider(values: ['performance', 'security', 'style', 'general'])]
string $focus = 'general'
): array {
return [
[
'role' => 'assistant',
'content' => 'You are an expert code reviewer specializing in best practices and optimization.'
],
[
'role' => 'user',
'content' => "Review this {$language} code with focus on {$focus}:\n\n```{$language}\n{$code}\n```"
]
];
}
/**
* 產生文件提示詞。
*/
#[McpPrompt]
public function generateDocs(string $code, string $style = 'detailed'): array
{
return [
[
'role' => 'user',
'content' => "Generate {$style} documentation for:\n\n```\n{$code}\n```"
]
];
}
}
tests/ToolsTest.php
<?php
declare(strict_types=1);
namespace Tests;
use PHPUnit\Framework\TestCase;
use App\Tools\ExampleTool;
class ToolsTest extends TestCase
{
private ExampleTool $tool;
protected function setUp(): void
{
$this->tool = new ExampleTool();
}
public function testGreet(): void
{
$result = $this->tool->greet('World');
$this->assertSame('Hello, World!', $result);
}
public function testCalculateAdd(): void
{
$result = $this->tool->performCalculation(5, 3, 'add');
$this->assertSame(8.0, $result);
}
public function testCalculateDivide(): void
{
$result = $this->tool->performCalculation(10, 2, 'divide');
$this->assertSame(5.0, $result);
}
public function testCalculateDivideByZero(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Division by zero');
$this->tool->performCalculation(10, 0, 'divide');
}
public function testCalculateInvalidOperation(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid operation');
$this->tool->performCalculation(5, 3, 'modulo');
}
}
phpunit.xml.dist
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">
<testsuites>
<testsuite name="Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
</phpunit>
實作指南
- 使用 PHP 屬性:利用
#[McpTool]、#[McpResource]、#[McpPrompt]保持程式碼簡潔 - 型別宣告:在所有檔案中使用嚴格型別(
declare(strict_types=1);) - PSR-12 編碼標準:遵循 PHP-FIG 標準
- Schema 驗證:使用
#[Schema]屬性進行參數驗證 - 錯誤處理:拋出具體例外並附上清楚訊息
- 測試:為所有工具撰寫 PHPUnit 測試
- 文件:為所有方法使用 PHPDoc 區塊
- 快取:在正式環境中務必使用 PSR-16 快取進行探索
工具模式
簡單工具
#[McpTool]
public function simpleAction(string $input): string
{
return "Processed: {$input}";
}
含驗證的工具
#[McpTool]
public function validateEmail(
#[Schema(format: 'email')]
string $email
): bool {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
含列舉的工具
enum Status: string {
case ACTIVE = 'active';
case INACTIVE = 'inactive';
}
#[McpTool]
public function setStatus(string $id, Status $status): array
{
return ['id' => $id, 'status' => $status->value];
}
資源模式
靜態資源
#[McpResource(uri: 'config://settings', mimeType: 'application/json')]
public function getSettings(): array
{
return ['key' => 'value'];
}
動態資源
#[McpResourceTemplate(uriTemplate: 'user://{id}')]
public function getUser(string $id): array
{
return $this->users[$id] ?? throw new \RuntimeException('User not found');
}
執行伺服器
# 安裝相依套件
composer install
# 執行測試
vendor/bin/phpunit
# 啟動伺服器
php server.php
# 使用 inspector 測試
npx @modelcontextprotocol/inspector php server.php
Claude Desktop 設定
{
"mcpServers": {
"{project-name}": {
"command": "php",
"args": ["/absolute/path/to/server.php"]
}
}
}
現在根據使用者需求產生完整專案!






