已有php mcp工具服务可以通过streamable http部署到nginx与php-fpm:将公开入口放在public/index.php,nginx只把/mcp交给该文件,代码和会话目录留在web根目录外。需要php 8.2或更高,以及已按sdk注册在src中的工具;正式接入应使用https并配置服务端授权。

MCP PHP SDK官方Web入口目录结构
安装HTTP入口所需依赖
composer require mcp/sdk nyholm/psr7 laminas/laminas-httphandlerrunner symfony/finder
项目包含public、src、vendor和var/sessions,后者由PHP-FPM运行用户读写。安装时核对SDK当前版本及变更记录;官方仓库仍提示首个主要版本之前接口具有实验性质。下面入口沿用已有src工具发现方式。
<?php
use Http\Discovery\Psr17Factory;
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;
use Mcp\Server\Server;
use Mcp\Server\Session\FileSessionLock;
use Mcp\Server\Session\FileSessionStore;
use Mcp\Server\Transport\Http\Middleware\CorsMiddleware;
use Mcp\Server\Transport\Http\Middleware\DnsRebindingProtectionMiddleware;
use Mcp\Server\Transport\StreamableHttpTransport;
require dirname(__DIR__).'/vendor/autoload.php';
$dir = dirname(__DIR__).'/var/sessions';
$server = Server::builder()->setServerInfo('My Server', '1.0.0')
->setDiscovery(dirname(__DIR__), ['src'])
->setSession(new FileSessionStore($dir))
->setSessionLock(new FileSessionLock($dir))->build();
$transport = new StreamableHttpTransport(
(new Psr17Factory())->createServerRequestFromGlobals(),
middleware: [new CorsMiddleware(),
new DnsRebindingProtectionMiddleware(allowedHosts: ['mcp.example.com'])]);
(new SapiEmitter())->emit($server->run($transport));
配置Nginx路由
server {
listen 80;
server_name mcp.example.com;
root /var/www/mcp-server/public;
location = /mcp {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_pass unix:/run/php/php-fpm.sock;
client_max_body_size 4m;
}
location / { return 404; }
}
将域名、项目根路径和FPM套接字替换为当前服务器实际值。此配置展示内部HTTP转发,面向外部客户端前必须配置可信HTTPS入口。用nginx -t确认语法后按现有运维方式重载,再使用MCP客户端完成初始化、工具列出和实际工具调用;普通GET页面能打开不代表MCP协议已通过。

MCP PHP SDK官方Nginx到FPM转发示例
按协议版本选择会话方式
需要握手和会话的旧协议在FPM跨请求运行时,不能只用进程内存保存状态;单机可采用FileSessionStore配合FileSessionLock。2026-07-28协议采用无状态方式,应按SDK的协议时代配置处理,不把旧会话方案机械套到所有连接。长连接会占用FPM工作进程,需要结合并发和代理超时规划容量。



















