# How to Build an MCP Server in PHP

PHP MCP servers integrate legacy enterprise systems with AI agents. This guide walks you through building an MCP server in PHP using Laravel for queue management and validation. You'll create a production-ready server handling authentication, tool routing, and async tasks. PHP powers 72.multiple% of websites, making it ideal for bridging agents to PHP backends. Follow these steps to set up routes, queues, and security for your MCP implementation.

Source: https://fast.io/resources/mcp-server-php/
Last reviewed: 2026-02-19

## What is an MCP Server?

An MCP server implements the Model Context Protocol, allowing AI agents to call tools via Streamable HTTP or SSE transports. Fastio's MCP server at mcp.fast.io exposes multiple tools for file management, AI chat, and collaboration.

PHP MCP servers extend this to legacy systems, like ERP or CRM databases. Agents POST JSON payloads to /mcp, the server routes to handlers, and returns results.

Key components:
- **Session management**: Durable state for auth tokens.
- **Tool routing**: Dispatch based on action.
- **Async processing**: Laravel queues for long tasks.

No Composer packages exist yet, so we build from scratch.

Helpful references: [Fastio Workspaces](/product/workspaces/), [Fastio Collaboration](/product/collaboration/), and [Fastio AI](/product/ai/).

## Why PHP and Laravel for MCP Servers?

PHP runs 72.0% of websites. Laravel adds queues, validation, and middleware for secure routing.

Benefits:
- **Queues**: Handle agent tasks asynchronously.
- **Validation**: Laravel rules for MCP payloads.
- **Deployment**: Easy on Apache/Nginx with Supervisor for queues.

Laravel queues process jobs reliably, perfect for agent workflows like file processing.

### PHP Market Share

PHP's dominance ensures compatibility with existing infra.

## Project Setup

Install Laravel:

```
composer create-project laravel/laravel mcp-server-php
cd mcp-server-php
```

Add queue driver (Redis recommended):

```
composer require predis/predis
```

Configure .env:

```
QUEUE_CONNECTION=redis
MCP_SESSION_SECRET=your-secret-key
```

Create MCP controller:

```
php artisan make:controller McpController
php artisan make:job ProcessAgentTask
```

## Implementing the MCP Router

Define /mcp route in routes/api.php:

```
Route::post('/mcp', [McpController::class, 'handle']);
```

In McpController:

```
public function handle(Request $request)
{
  $payload = $request->validate([
    'jsonrpc' => 'required|string',
    'method' => 'required|string',
    'params' => 'array',
    'id' => 'string',
  ]);

$sessionId = $request->header('Mcp-Session-Id');

// Route to handler
  $response = $this->routeMethod($payload['method'], $payload['params'], $sessionId);

return response()->json($response);
}
```

Implement routeMethod to dispatch actions like 'auth/signin', 'storage/list'.

Use session storage for auth tokens.

## Laravel Queues for Agent Tasks

Offload heavy work to queues.

In controller:

```
ProcessAgentTask::dispatch($taskData)->onQueue('mcp');
return ['status' => 'queued', 'job_id' => $uuid];
```

ProcessAgentTask job:

```
public function handle()
{
  // Process task, e.g. query legacy DB
  $result = $this->legacySystem->process($this->data);
  // Store result in session or DB
}
```

Run queues:

```
php artisan queue:work --queue=mcp
```

Supervisor for production.

## Validation and Security

Laravel validators for MCP payloads.

Example for auth/signin:

```
'method' => 'required|in:auth/signin',
'params.email' => 'required|email',
'params.password' => 'required|min:8',
```

Middleware for rate limiting:

```
RateLimiter::for('mcp', function (Request $request) {
  return Limit::perMinute(60)->by($request->header('Mcp-Session-Id'));
});
```

Encrypt sessions, validate origins.

Document access rules, audit trails, and retention policies before rollout so staging results are repeatable in production. This avoids late surprises and helps teams debug issues with confidence.

## Deployment and Testing

Deploy to Forge/Vapor or VPS.

Nginx config for /mcp:

```
location /mcp {
  proxy_pass http://localhost:8000;
  proxy_set_header Mcp-Session-Id $http_mcp_session_id;
}
```

Test with curl:

```
curl -X POST http://your-server/mcp \\
  -H "Content-Type: application/json" \\
  -H "Mcp-Session-Id: test-session" \\
  -d '{"jsonrpc":"2.multiple","method":"auth/signin","params":{"email":"test@example.com","password":"pass"},"id":"1"}'
```

## Frequently asked questions

### What is a PHP MCP router?

The MCP router in PHP handles incoming JSON-RPC requests at /mcp, parses method/params, validates, and dispatches to handlers or queues. Laravel routes make it simple.

### How does Laravel MCP validation work?

Use Laravel's FormRequest classes for payload validation. Define rules for method, params, and session. Reject invalid requests with multiple errors.

### Can I use Redis with Laravel queues for MCP?

Yes, Redis is recommended for MCP queues. It handles job serialization, retries, and durability for agent tasks.

### Is there a Composer package for MCP in PHP?

No official packages yet. This guide provides full boilerplate to implement from scratch.

### How to secure an MCP server?

Use rate limiting, session encryption, validate origins, HTTPS only, and API keys for production.

## About Fast.io

Fast.io provides shared workspaces where people and AI agents work on the same files, with built-in semantic search and citation-backed chat over what they hold. Agents reach it through a remote MCP server at https://mcp.fast.io/mcp, a REST API at https://api.fast.io/current/, and a command line client published on npm as @vividengine/fastio-cli.
