|
| 1 | +# Symfony MCP Server Development Guidelines |
| 2 | + |
| 3 | +This document provides essential information for developers working on the Symfony MCP Server project. |
| 4 | + |
| 5 | +## Build/Configuration Instructions |
| 6 | + |
| 7 | +### Prerequisites |
| 8 | +- PHP 8.2 or higher |
| 9 | +- Symfony 7.0 |
| 10 | +- Composer |
| 11 | + |
| 12 | +### Installation |
| 13 | + |
| 14 | +1. Clone the repository: |
| 15 | + ```bash |
| 16 | + git clone https://github.com/klapaudius/symfony-mcp-server.git |
| 17 | + ``` |
| 18 | + |
| 19 | +2. Create a new Symfony project (if you don't have one already): |
| 20 | + ```bash |
| 21 | + composer create-project symfony/skeleton my-symfony-project |
| 22 | + cd my-symfony-project |
| 23 | + ``` |
| 24 | + |
| 25 | +3. Add the cloned repository as a local repository in your Symfony project's composer.json: |
| 26 | + ```json |
| 27 | + { |
| 28 | + "repositories": [ |
| 29 | + { |
| 30 | + "type": "path", |
| 31 | + "url": "../symfony-mcp-server" |
| 32 | + } |
| 33 | + ] |
| 34 | + } |
| 35 | + ``` |
| 36 | + Note: Adjust the path "../symfony-mcp-server" to match the relative path from your Symfony project to the cloned repository. |
| 37 | + |
| 38 | +4. Require the package from the local repository: |
| 39 | + ```bash |
| 40 | + composer require klapaudius/symfony-mcp-server:@dev |
| 41 | + ``` |
| 42 | + |
| 43 | +5. Create the configuration file `config/packages/klp_mcp_server.yaml` with the following content: |
| 44 | + ```yaml |
| 45 | + klp_mcp_server: |
| 46 | + enabled: true |
| 47 | + server: |
| 48 | + name: 'My MCP Server' |
| 49 | + version: '1.0.0' |
| 50 | + default_path: 'mcp' |
| 51 | + ping: |
| 52 | + enabled: true |
| 53 | + interval: 30 |
| 54 | + server_provider: 'sse' |
| 55 | + sse_adapter: 'redis' |
| 56 | + adapters: |
| 57 | + redis: |
| 58 | + prefix: 'mcp_sse_' |
| 59 | + host: 'localhost' # Change as needed |
| 60 | + ttl: 100 |
| 61 | + tools: |
| 62 | + - KLP\KlpMcpServer\Services\ToolService\Examples\HelloWorldTool |
| 63 | + - KLP\KlpMcpServer\Services\ToolService\Examples\VersionCheckTool |
| 64 | + ``` |
| 65 | +
|
| 66 | +6. Add routes in your `config/routes.yaml`: |
| 67 | + ```yaml |
| 68 | + klp_mcp_server: |
| 69 | + resource: '@KlpMcpServerBundle/Resources/config/routes.php' |
| 70 | + type: php |
| 71 | + ``` |
| 72 | + |
| 73 | +### Important Configuration Notes |
| 74 | + |
| 75 | +- **Web Server**: This package cannot be used with `symfony server:start` as it requires processing multiple connections concurrently. Use Nginx + PHP-FPM, Apache + PHP-FPM, or a custom Docker setup instead. |
| 76 | +- **Redis Configuration**: Ensure your Redis server is properly configured and accessible at the host specified in the configuration. |
| 77 | +- **Security**: It's strongly recommended to implement OAuth2 Authentication for production use. |
| 78 | + |
| 79 | +### Docker Setup |
| 80 | + |
| 81 | +The project includes a Docker setup that can be used for development. The Docker setup includes: |
| 82 | +- Nginx web server |
| 83 | +- PHP-FPM with Redis extension |
| 84 | +- Redis server |
| 85 | + |
| 86 | +To set up and use the Docker containers: |
| 87 | + |
| 88 | +1. Navigate to the docker directory: |
| 89 | + ```bash |
| 90 | + cd docker |
| 91 | + ``` |
| 92 | + |
| 93 | +2. Configure the environment variables by creating a `.env.local` file: |
| 94 | + ```bash |
| 95 | + # Example configuration |
| 96 | + COMPOSE_PROJECT_NAME=mcp |
| 97 | +
|
| 98 | + NGINX_IP=172.20.0.2 |
| 99 | + NGINX_EXPOSED_PORT=8080 |
| 100 | +
|
| 101 | + PHP_IP=172.20.0.3 |
| 102 | +
|
| 103 | + REDIS_IP=172.20.0.4 |
| 104 | +
|
| 105 | + NETWORK_SUBNET=172.20.0.0/24 |
| 106 | + ``` |
| 107 | + Note: Adjust the IP addresses and port as needed for your environment. |
| 108 | + |
| 109 | +3. Build and start the Docker containers: |
| 110 | + ```bash |
| 111 | + docker-compose up -d |
| 112 | + ``` |
| 113 | + |
| 114 | +4. Access the application in your browser at `http://localhost:8080` (or the port you specified in NGINX_EXPOSED_PORT). |
| 115 | + |
| 116 | +5. To stop the containers: |
| 117 | + ```bash |
| 118 | + docker-compose down |
| 119 | + ``` |
| 120 | + |
| 121 | +6. Update your Symfony configuration to use the Redis server in the Docker container: |
| 122 | + ```yaml |
| 123 | + # config/packages/klp_mcp_server.yaml |
| 124 | + klp_mcp_server: |
| 125 | + # ... |
| 126 | + adapters: |
| 127 | + redis: |
| 128 | + prefix: 'mcp_sse_' |
| 129 | + host: 'redis' # Use the service name from docker-compose.yml |
| 130 | + ttl: 100 |
| 131 | + ``` |
| 132 | + |
| 133 | +## Testing Information |
| 134 | + |
| 135 | +### Running Tests |
| 136 | + |
| 137 | +The project uses PHPUnit for testing. To run all tests: |
| 138 | + |
| 139 | +```bash |
| 140 | +vendor/bin/phpunit |
| 141 | +``` |
| 142 | + |
| 143 | +To run a specific test file: |
| 144 | + |
| 145 | +```bash |
| 146 | +vendor/bin/phpunit tests/path/to/TestFile.php |
| 147 | +``` |
| 148 | + |
| 149 | +To generate code coverage reports: |
| 150 | + |
| 151 | +```bash |
| 152 | +vendor/bin/phpunit --coverage-html build/coverage |
| 153 | +``` |
| 154 | + |
| 155 | +### Adding New Tests |
| 156 | + |
| 157 | +1. **Test Location**: Place tests in the `tests/` directory, mirroring the structure of the `src/` directory. |
| 158 | +2. **Naming Convention**: Name test classes with the suffix `Test` (e.g., `DataUtilTest.php`). |
| 159 | +3. **Test Size**: Use PHPUnit attributes to indicate test size: |
| 160 | + ```php |
| 161 | + #[Small] // For unit tests |
| 162 | + #[Medium] // For integration tests |
| 163 | + #[Large] // For system tests |
| 164 | + ``` |
| 165 | +4. **Mocking**: Use PHPUnit's mocking capabilities for dependencies: |
| 166 | + ```php |
| 167 | + $mockTransport = $this->createMock(SseTransportInterface::class); |
| 168 | + ``` |
| 169 | + |
| 170 | +### Example Test |
| 171 | + |
| 172 | +Here's a simple test for the `DataUtil` class: |
| 173 | + |
| 174 | +```php |
| 175 | +<?php |
| 176 | +
|
| 177 | +namespace KLP\KlpMcpServer\Tests\Utils; |
| 178 | +
|
| 179 | +use KLP\KlpMcpServer\Data\Requests\NotificationData; |
| 180 | +use KLP\KlpMcpServer\Data\Requests\RequestData; |
| 181 | +use KLP\KlpMcpServer\Utils\DataUtil; |
| 182 | +use PHPUnit\Framework\Attributes\Small; |
| 183 | +use PHPUnit\Framework\TestCase; |
| 184 | +
|
| 185 | +#[Small] |
| 186 | +class DataUtilTest extends TestCase |
| 187 | +{ |
| 188 | + public function test_make_request_data_creates_request_data_when_message_has_method_and_id(): void |
| 189 | + { |
| 190 | + $clientId = 'test_client'; |
| 191 | + $message = [ |
| 192 | + 'jsonrpc' => '2.0', |
| 193 | + 'method' => 'test.method', |
| 194 | + 'id' => 1, |
| 195 | + 'params' => ['param1' => 'value1'] |
| 196 | + ]; |
| 197 | +
|
| 198 | + $result = DataUtil::makeRequestData($clientId, $message); |
| 199 | +
|
| 200 | + $this->assertInstanceOf(RequestData::class, $result); |
| 201 | + $this->assertEquals('test.method', $result->method); |
| 202 | + $this->assertEquals('2.0', $result->jsonRpc); |
| 203 | + $this->assertEquals(1, $result->id); |
| 204 | + $this->assertEquals(['param1' => 'value1'], $result->params); |
| 205 | + } |
| 206 | +} |
| 207 | +``` |
| 208 | + |
| 209 | +## Additional Development Information |
| 210 | + |
| 211 | +### Code Style |
| 212 | + |
| 213 | +- The project follows PSR-12 coding standards. |
| 214 | +- Use type hints for method parameters and return types. |
| 215 | +- Document classes and methods with PHPDoc comments. |
| 216 | + |
| 217 | +### Creating MCP Tools |
| 218 | + |
| 219 | +1. Use the provided command to generate a new tool: |
| 220 | + ```bash |
| 221 | + php bin/console make:mcp-tool MyCustomTool |
| 222 | + ``` |
| 223 | + |
| 224 | +2. Implement the `ToolInterface` in your custom tool class: |
| 225 | + ```php |
| 226 | + use KLP\KlpMcpServer\Services\ToolService\ToolInterface; |
| 227 | +
|
| 228 | + class MyCustomTool implements ToolInterface |
| 229 | + { |
| 230 | + // Implementation |
| 231 | + } |
| 232 | + ``` |
| 233 | + |
| 234 | +3. Register your tool in `config/packages/klp_mcp_server.yaml`. |
| 235 | + |
| 236 | +### Testing MCP Tools |
| 237 | + |
| 238 | +Use the provided command to test your MCP tools: |
| 239 | + |
| 240 | +```bash |
| 241 | +# Test a specific tool interactively |
| 242 | +php bin/console mcp:test-tool MyCustomTool |
| 243 | +
|
| 244 | +# List all available tools |
| 245 | +php bin/console mcp:test-tool --list |
| 246 | +
|
| 247 | +# Test with specific JSON input |
| 248 | +php bin/console mcp:test-tool MyCustomTool --input='{"param":"value"}' |
| 249 | +``` |
| 250 | + |
| 251 | +### Debugging |
| 252 | + |
| 253 | +- Enable Symfony's debug mode for detailed error messages. |
| 254 | +- Use the MCP Inspector for visualizing and testing your MCP tools: |
| 255 | + ```bash |
| 256 | + npx @modelcontextprotocol/inspector node build/index.js |
| 257 | + ``` |
| 258 | + |
| 259 | +### Architecture Notes |
| 260 | + |
| 261 | +- The package implements a publish/subscribe (pub/sub) messaging pattern through its adapter system. |
| 262 | +- The default Redis adapter maintains message queues for each client, identified by unique client IDs. |
| 263 | +- Long-lived SSE connections subscribe to messages for their respective clients and deliver them in real-time. |
0 commit comments