Building an MCP Server in PHP for Legacy Code Migration

Teaching AI agents to understand your legacy code by giving them the tools developers use
25.11.2025 — Marc Bernet — 4 min read

The Reality of Legacy Migration

Modernizing a legacy PHP system should be simple: read the old code, understand the rules, rebuild them cleanly in a new Laravel application. In reality, legacy code doesn't behave like that. It's nonlinear, implicit, full of side-effects, and often depends on conventions nobody remembers.

When you pair that with a modern agent like Claude Code, you quickly learn a hard truth: an LLM can write great code, but it cannot guess your business rules. That's exactly why we decided to build our own MCP (Model Context Protocol) server—written in PHP, running next to the legacy code—to give the agent a real window into the system.

Why an MCP Server?

CLI coding agents have changed the workflow. When an agent can read your repo, write files, run tests, and modify code asynchronously, it stops being a chatbot and becomes a collaborator. But to collaborate, it needs context.

In a greenfield Laravel project, that's easy: folders are predictable, patterns repeat, business logic lives in services or actions. But our legacy application was classic spaghetti code—mixing HTML, SQL strings, global functions, procedural includes, inline calculations, and redirect calls.

To migrate this safely, the agent needs to answer questions like: Which tables exist and what do they look like? What does this function really compute? How many places modify this session variable? No prompt can reliably guess that from raw static code. We needed executable access—not just text.

A PHP MCP Server Next to Legacy Code

We used the mcp/capability library, which lets you annotate PHP methods and expose them as MCP tools. The server runs inside the same environment as the legacy application so it can query the DB, include old PHP files, and run legacy functions.

Once exposed through MCP, Claude Code can call these tools directly during a migration task. The server includes capabilities for querying data (read-only), describing tables, extracting PHP logic, analyzing business rules, and even invoking legacy PHP functions inside their original environment.

Running Legacy Functions Directly

Many of the tricky bits—shipping calculations, price adjustments, discount logic—live in small functions scattered across includes. To help Claude understand what these functions actually do, we exposed a tool that loads the original file, includes shared function libraries, sets up the legacy session and DB, and executes the function.

This allows the agent to test the behavior before rewriting the logic in Laravel: "Given these inputs, what shipping cost does the legacy system compute?" The agent can now confirm the legacy behavior instead of hallucinating a new implementation.

Extracting the Real Business Rules

Static analysis also matters. The spaghetti nature of the project means logic is hidden inside branches, inline expressions, SQL statements, and session mutations. One of our MCP tools reads a file and extracts patterns such as conditionals involving pricing, basic validations, SQL queries, redirects, session variables, and arithmetic expressions involving totals, VAT, and discounts.

This gives Claude a compact view of "what this file is really doing," without drowning it in HTML or markup noise. The goal isn't to perfectly understand the code—just to surface the logic the agent must preserve when rewriting it.

How This Changes the Migration Process

Building the MCP server forced us to rethink how we migrate legacy code. Instead of rewriting blindly, the agent explores the system. Instead of guessing rules, it inspects them. Instead of reverse-engineering by hand, we expose the answers via tools.

On the Laravel side, the agent now produces cleaner, more faithful implementations because it's reenacting the reasoning a developer would follow: check the table schema, inspect a function, run it with test data, extract its calculations, and then implement the equivalent Feature, Action, or Service.

It's still a migration project, not magic. But it feels significantly less like archaeology and more like a structured rewrite.

Final Thoughts

Building an MCP server in PHP wasn't part of the original plan. But once we saw how coding agents work—and how much context they need—it became obvious. If you want an AI to collaborate on a rewrite, give it the tools a real developer uses.

We're now able to migrate features more confidently, with less guesswork, and with a clearer separation between legacy inspection and new Laravel code. If you're dealing with a legacy PHP system and planning a modern migration, building a small MCP layer around the old code might be one of the most impactful steps you take.

Laravel
PHP
MySQL

💡 How much does it cost to develop an app for your business? Discover the prices