php-mcp-server-generator

Par github · awesome-copilot

Générer un projet complet de serveur PHP Model Context Protocol avec des outils, des ressources, des prompts et des tests en utilisant le SDK PHP officiel

npx skills add https://github.com/github/awesome-copilot --skill php-mcp-server-generator

Générateur de serveur PHP MCP

Vous êtes un générateur de serveur PHP MCP. Créez un projet de serveur PHP MCP complet et prêt pour la production en utilisant le SDK PHP officiel.

Configuration requise du projet

Demandez à l'utilisateur :

  1. Nom du projet (par exemple, « mon-serveur-mcp »)
  2. Description du serveur (par exemple, « Un serveur MCP de gestion de fichiers »)
  3. Type de transport (stdio, http, ou les deux)
  4. Outils à inclure (par exemple, « lecture de fichier », « écriture de fichier », « lister le répertoire »)
  5. Si vous devez inclure des ressources et des prompts
  6. Version PHP (8.2+ requise)

Structure du projet

{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

Modèles de fichiers

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}

## Prérequis

- PHP 8.2 ou supérieur
- Composer

## Installation

```bash
composer install

Utilisation

Démarrer le serveur (Stdio)

php server.php

Configurer dans Claude Desktop

{
  "mcpServers": {
    "{project-name}": {
      "command": "php",
      "args": ["/absolute/path/to/server.php"]
    }
  }
}

Tests

vendor/bin/phpunit

Outils

  • {tool_name}: {Tool description}

Développement

Testez avec 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;

// Setup cache for discovery
$cache = new Psr16Cache(new FilesystemAdapter('mcp-discovery', 3600, __DIR__ . '/cache'));

// Build server with discovery
$server = Server::builder()
    ->setServerInfo('{Project Name}', '1.0.0')
    ->setDiscovery(
        basePath: __DIR__,
        scanDirs: ['src'],
        excludeDirs: ['vendor', 'tests', 'cache'],
        cache: $cache
    )
    ->build();

// Run with stdio transport
$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
{
    /**
     * Effectue une salutation avec le nom fourni.
     * 
     * @param string $name Le nom à saluer
     * @return string Un message de salutation
     */
    #[McpTool]
    public function greet(string $name): string
    {
        return "Hello, {$name}!";
    }

    /**
     * Effectue des calculs arithmétiques.
     */
    #[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
{
    /**
     * Fournit la configuration de l'application.
     */
    #[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
{
    /**
     * Fournit des données par catégorie et ID.
     */
    #[McpResourceTemplate(
        uriTemplate: 'data://{category}/{id}',
        name: 'data_resource',
        mimeType: 'application/json'
    )]
    public function getData(string $category, string $id): array
    {
        // Exemple de récupération de données
        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
{
    /**
     * Génère un prompt de revue de code.
     */
    #[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```"
            ]
        ];
    }

    /**
     * Génère un prompt de documentation.
     */
    #[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>

Directives de mise en œuvre

  1. Utilisez les attributs PHP : Exploitez #[McpTool], #[McpResource], #[McpPrompt] pour un code propre
  2. Déclarations de type : Utilisez les types stricts (declare(strict_types=1);) dans tous les fichiers
  3. Norme de codage PSR-12 : Suivez les normes PHP-FIG
  4. Validation de schéma : Utilisez les attributs #[Schema] pour la validation des paramètres
  5. Gestion des erreurs : Levez des exceptions spécifiques avec des messages clairs
  6. Tests : Écrivez des tests PHPUnit pour tous les outils
  7. Documentation : Utilisez des blocs PHPDoc pour toutes les méthodes
  8. Mise en cache : Utilisez toujours le cache PSR-16 pour la découverte en production

Modèles d'outils

Outil simple

#[McpTool]
public function simpleAction(string $input): string
{
    return "Processed: {$input}";
}

Outil avec validation

#[McpTool]
public function validateEmail(
    #[Schema(format: 'email')]
    string $email
): bool {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

Outil avec énumération

enum Status: string {
    case ACTIVE = 'active';
    case INACTIVE = 'inactive';
}

#[McpTool]
public function setStatus(string $id, Status $status): array
{
    return ['id' => $id, 'status' => $status->value];
}

Modèles de ressources

Ressource statique

#[McpResource(uri: 'config://settings', mimeType: 'application/json')]
public function getSettings(): array
{
    return ['key' => 'value'];
}

Ressource dynamique

#[McpResourceTemplate(uriTemplate: 'user://{id}')]
public function getUser(string $id): array
{
    return $this->users[$id] ?? throw new \RuntimeException('User not found');
}

Exécution du serveur

# Installer les dépendances
composer install

# Exécuter les tests
vendor/bin/phpunit

# Démarrer le serveur
php server.php

# Tester avec l'inspecteur
npx @modelcontextprotocol/inspector php server.php

Configuration de Claude Desktop

{
  "mcpServers": {
    "{project-name}": {
      "command": "php",
      "args": ["/absolute/path/to/server.php"]
    }
  }
}

Générez maintenant le projet complet en fonction des exigences de l'utilisateur !

Skills similaires