php-mcp-server

dv-team/php-mcp-server

3.2

If you are the rightful owner of php-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.

This project demonstrates a simple PHP-based MCP Server for handling processes that require near-instant responses.

Tools
2
Resources
0
Prompts
0

PHP MCP Server

This project demonstrates a simple PHP-based MCP Server (JSON-RPC) for handling requests that can respond immediately. It is designed for flexibility and can be adapted to various environments, such as database schema retrieval, prompt output, filesystem tasks, and more.

High-Level Goals

  • Simple PHP and PHP-esque MCP Server for processes that can respond (near) immediately.
  • HTTP and STDIN samples for quick testing; no streaming support.
  • Versatile usage: Suitable for a wide range of environments, including database, prompt handling, and filesystem operations.

Requirements

  • PHP 8.2 or higher
  • Composer

Installation

composer install

Usage

HTTP server (main)

php -S 127.0.0.1:8080 public/index.php

The server listens on http://127.0.0.1:8080/ (POST JSON bodies). A few quick calls:

curl -sS http://127.0.0.1:8080/ \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"0.0"}}}'
curl -sS http://127.0.0.1:8080/ \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

Use test.http to exercise the JSON-RPC methods; replace the host (https://php-mcp.localhost/) with http://127.0.0.1:8080/ if needed.

Logs are written to public/stdio-mcp.log.

Implemented JSON-RPC methods

  • initialize (returns protocolVersion: 2025-03-26)
  • notifications/initialized (accepted; no response)
  • prompts/list, prompts/get
  • tools/list, tools/call
  • resources/list, resources/read
  • resources/templates/list

CLI server (main)

printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"cli","version":"0.0"}}}' | php cli.php

Logs are written to stdio–mcp.log (note the filename contains an en dash ).

Example servers

The examples/ folder is a separate Composer project. Install its dependencies first:

(cd examples && composer install)

HTTP sample that loads prompts/tools from examples/prompts and exposes demo tools:

php -S 127.0.0.1:8080 examples/src/prompts-and-tools-http.php

STDIN sample that logs requests/responses to examples/src/stdio–mcp.log:

printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"cli","version":"0.0"}}}' | php examples/src/prompts-and-tools-cli.php

Example: Registering Prompts

The server uses YAML front-matter to parse Markdown files and register them as prompts, as shown in examples/src/prompts-and-tools-http.php:

$files = [
	__DIR__ . '/../prompts/email--basic-rules.md',
	__DIR__ . '/../prompts/behaviour--basic-rules.md'
];

$responseHandler = new HttpResponseHandler();
$server = new MCPServer('Prompt provider example', $responseHandler);

foreach($files as $file) {
	$document = YamlFrontMatter::parseFile($file);

	/** @var string $name */
	$name = $document->matter('name');

	/** @var string $prompt */
	$prompt = $document->matter('prompt');

	/** @var string $description */
	$description = $document->matter('description');

	$server->registerPrompt(
		name: $name,
		description: $prompt,
		arguments: new MCPPromptArguments(),
		handler: function () use ($description, $document) {
			return new MCPPromptResult(
				description: $description,
				messages: [new PromptResultStringMessage(
					role: RoleEnum::User,
					content: $document->body()
				)]
			);
		}
	);
}

Example: Registering Tools

Here are three simple tools you might register:

$server->registerTool(
	name: 'echo_text',
	description: 'Echoes back the provided text.',
	inputSchema: new MCPToolInputSchema(
		properties: new MCPToolProperties(
			new MCPToolString(name: 'text', description: 'Text to echo', required: true),
		)
	),
	isDangerous: false,
	handler: static function (object $input): MCPToolResult {
		return new MCPToolResult(
			content: (object) ['echo' => (string) ($input->text ?? '')],
			isError: false
		);
	}
);

$server->registerTool(
	name: 'sum_numbers',
	description: 'Adds two integers together.',
	inputSchema: new MCPToolInputSchema(
		properties: new MCPToolProperties(
			new MCPToolInteger(name: 'a', description: 'First addend', required: true),
			new MCPToolInteger(name: 'b', description: 'Second addend', required: true),
		)
	),
	isDangerous: false,
	handler: static function (object $input): MCPToolResult {
		$sum = (int) ($input->a ?? 0) + (int) ($input->b ?? 0);

		return new MCPToolResult(
			content: ['sum' => $sum],
			isError: false
		);
	}
);

$server->registerTool(
	name: 'send_email',
	description: 'Send an email',
	inputSchema: new MCPToolInputSchema(
		properties: new MCPToolProperties(
			new MCPToolString(name: 'to', description: 'The recipient email address', required: true),
			new MCPToolString(name: 'cc', description: 'The cc-recipient email address', required: false),
			new MCPToolString(name: 'from', description: 'The sender email address', required: true),
			new MCPToolString(name: 'subject', description: 'The subject of the email', required: true),
			new MCPToolString(name: 'body', description: 'The body of the email', required: true),
		),
		required: []
	),
	isDangerous: true,
	handler: static function (object $input): MCPToolResult {
		$json = json_encode($input, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
		error_log($json);

		return new MCPToolResult(
			content: ['result' => 'Email queued!'],
			isError: false
		);
	}
);

Example: Attribute-Based Tools

You can mark methods with attributes and let the AttributeToolRegistrar build the MCP tool definitions for you:

use McpSrv\Common\Attributes\MCPDescription;
use McpSrv\Common\Attributes\MCPTool;
use McpSrv\Common\Tools\AttributeToolRegistrar;
use McpSrv\MCPServer;

class MathTools {
	#[MCPTool(
		name: 'add_numbers',
		description: 'Adds two integers together.',
		parametersSchema: [
			'type' => 'object',
			'properties' => [], // left empty; types/required flags are inferred from parameter signatures
		],
		returnSchema: [
			'type' => 'object',
			'properties' => [
				'sum' => ['type' => 'integer', 'description' => 'Result of the addition', 'required' => true],
			],
			'required' => ['sum'],
		],
	)]
	public function add(
		#[MCPDescription('First addend')]
		int $a,
		#[MCPDescription('Second addend')]
		int $b
	): array {
		return ['sum' => $a + $b];
	}
}

$server = new MCPServer('attribute-sample', $responseHandler);

$registrar = new AttributeToolRegistrar();
$registrar->register(new MathTools(), $server);

Descriptions on parameters are copied into the generated schema; when a property is not supplied in parametersSchema, the registrar infers the JSON Schema type and required flag from the method signature.

Notes

  • This server is intended for environments where immediate responses are required (no streaming support).
  • For broader protocol coverage, including streaming, see logiscape/mcp-sdk-php.

License

MIT License