Laravel

How to Build Your First MCP Server and Let Claude Desktop Access Local Laravel/Next.js Logs

Author By Chandan Kumar
March 5, 2026
8 min read
Share:

In particular, developers depend on AI-assisted debugging to summarise stack traces, clarify cryptic error messages, and suggest probable fixes to such cryptic errors.

Most modern Laravel and Next.js projects, where critical debugging data — such as application logs, build error output, and runtime failures — are stored on the local machine.

It means there’s a lot of space that does not exist between what AI tools can do and what developers are actually looking for when trying to debug with local AI.

AI tools are incapable of getting local files or the runtime state by default. In response, developers copy and paste logs and error messages into the AI interface.

This is great for small problems to a certain extent, but for large projects, it is fast, not efficient. Frequent context-shifting between terminals, editors, and AI tools complicates workflow, and the sharing of large, out-of-context log snippets often results in major diagnostic detail getting lost.

The Model Context Protocol (MCP) overcomes this restriction by adopting a secure, local-first AI integration solution.

You could also spin up an MCP server (usually using Node.js), allowing developers to expose controlled tools and resources to Claude Desktop without granting unrestricted permissions to the filesystem.

This facilitates access to Claude’s local logs in a supervised, repeatable manner – with the result that structured, secure local AI can be deployed to Laravel and Next.js projects.

What Is the Model Context Protocol (MCP)?

MCP is a client–server protocol for secure, structured AI access in a local development context. To put it simply, Claude Desktop serves as the client; the MCP server will only see what you want and do exactly what the client wants. Two core primitives:  

  • Resources: read-only data (log files, etc.), which we get with a URI.  
  • Tools: named TypeScript functions that are stored in your server, which Claude can invoke to provide a result.  

It uses the server’s list of endpoints at startup to get to resources and tools as found; Claude cannot directly probe the filesystem.

Each file is read, and diagnostic runs to the server; Claude does not touch the local system directly. Permission behavior: Claude Desktop prompts the user before calling the tool.

Once the server is connected, resources are read without prompting.  

Setting Prerequisites and Setting Up the Environment  

Node.js is the target for the majority of MCP tooling and documentation, which provides simple filesystem access and is the runtime supported by the official MCP TypeScript SDK.  

You will need:  

  • A locally running Laravel or Next.js project that provides logs or build outputs that are available.  
  • Node.js (recommended v18 or later).  
  • Claude Desktop installed. MCP support is not just a toggle inside the app, but is enabled through a defined configuration file, claude_desktop_config.json, addressed in the last step below.  

There is no need for cloud infrastructure or the use of remote servers. MCP is built for local development pipelines.

Step 1: Server Identity, Capabilities, and Transport

typescript

import { Server } from "@modelcontextprotocol/sdk/server/index.js";

import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server(

{ name: "local-mcp-server", version: "1.0.0" },

{ capabilities: { resources: {}, tools: {} } }

);

const transport = new StdioServerTransport();

await server.connect(transport);

The .js extensions are needed for ESM module resolution. If you leave them out, the program will crash.

How to talk to each other:

Claude Desktop starts your server as a child process and sends JSON-RPC 2.0 messages through stdin and stdout.

There is no open network port, so you can’t reach the server from outside the local machine. The SDK takes care of serializing JSON-RPC, and in your handlers, you work with typed request/response objects.

Step 2: Making Laravel Logs a Resource

By default, Laravel writes logs to the file storage/logs/laravel.log. Make this a resource. The MCP interaction is read-only, so this is the right pattern whether or not the file is being written to.

Not just plain strings, but Zod schema objects from the SDK are used by request handlers:

typescript
import {
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import fs from "fs";
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [
{ uri: "laravel://logs/errors", name: "Laravel Error Logs", mimeType: "text/plain" },
],
}));
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const raw = fs.readFileSync("storage/logs/laravel.log", "utf-8");
const filtered = raw
.split("\n")
.filter((line) => line.includes(".ERROR") || line.includes(".CRITICAL"))
.slice(-100)
.join("\n");
return {
contents: [{ uri: request.params.uri, mimeType: "text/plain", text: filtered }],
};
});

The server only sends back the last 100 lines that are ERROR or CRITICAL, which keeps Claude’s context clear and focused.

Step 3: Using Next.js Build Errors as a Tool

During the next build, Next.js sends build errors to stderr. They are not saved to a file that can be read. The .next/trace file is not an error log; it is a binary Chrome DevTools performance trace.

It is shown as a tool because making this diagnostic requires starting a new process and reading its output:

import { CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { execSync } from "child_process";
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "getLatestNextBuildErrors") {
try {
execSync("next build", { cwd: "/path/to/nextjs/project" });
return { content: [{ type: "text", text: "Build succeeded." }] };
} catch (error) {
const output = error.stderr?.toString() ?? "";
const errorLines = output
.split("\n")
.filter((line) =>
line.includes("Error:") ||
line.includes("Failed to compile") ||
line.includes("Module not found") ||
line.includes("  at ")
)
.slice(0, 60)
.join("\n");
return {
content: [{ type: "text", text: errorLines || "No parseable errors found." }],
};
}
}
throw new Error(`Unknown tool: ${request.params.name}`);
});

The filter only looks for Error:, Failed to compile, Module not found, and stack frames, ignoring webpack progress lines, timing output, and verbose build chatter.

A quick guide to resources and tools

  • Laravel error logs: read-only, URI-addressable file
  • Errors in the Next.js buildTool needs to run subprocesses and parse them.
  • Behavior of permission: Before using a tool, Claude Desktop asks the user for permission. Once the server is connected, resources can be accessed without a prompt.

Step 4: Linking the MCP Server to the Claude Desktop

Claude Desktop finds MCP servers using the claude_desktop_config.json:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
json
{
"mcpServers": {
"local-mcp-server": {
"command": "node",
"args": ["/absolute/path/to/mcp-server/dist/index.js"]
}
}
}

After you change this file, restart Claude Desktop. When the server starts up, it automatically creates itself. Claude then checks the list of endpoints to see what resources and tools are available.

When to Use MCP and When Not to

MCP runs over stdio, which means it’s on the same machine and in the same process, so latency is very low. No network round-trips and no serialization overhead other than JSON. This makes it perfect for debugging in real time.

MCP works best when:

  • Debugging Laravel or Next.js apps on your own computer while you are still working on them
  • Looking at recent logs, stack traces, or build errors in real time
  • Giving Claude a focused, pre-filtered picture of the local situation
  • You shouldn’t use MCP when you need to:
  • Process or look at gigabytes of log data all at once
  • Run log analysis pipelines that work in batches or take a long time to run
  • Change out centralized observability platforms like Datadog, Grafana, Sentry, and others.

Support logging workflows or production telemetry for the whole team

In real life, MCP adds to the tools that are already there instead of replacing them. It fills the space between “AI can’t see my local state” and “I have to manually paste everything” without needing to change your logging infrastructure or deployment pipeline.

In conclusion

Your implementation, not the protocol itself, decides how secure MCP is. A secure server only registers certain resources and tools and accesses the filesystem internally. A server that lets anyone run shell commands is not. MCP gives you the structure; it’s up to you to keep it up.

Chandan Kumar

Chandan Kumar

Chandan Kumar doesn't just write code; he builds digital legacies. As the Founder and Team Lead at AvyaTech, Chandan combines high-level strategy with granular technical expertise to turn "what if" into "it's live." When he’s not steering his team through complex development sprints, he’s busy architecting the future of scalable, user-first technology.

Related Articles

Continue reading with these hand-picked articles on similar topics.

Laravel Structure: Understanding the Key Aspects of Your Application
Laravel
Laravel Structure: Understanding the Key Aspects of Your Application
Laravel's well-organized file structure follows the MVC architecture, making app development efficient and easy to manage. This post explores key folders like app/, routes/, and resources/, and how they streamline your Laravel projects.
Chandan Kumar October 22, 2024
A Simplified Approach to Configure Your Laravel App Effortlessly
Laravel
A Simplified Approach to Configure Your Laravel App Effortlessly
The Laravel PHP framework’s strength is its configuration system. Laravel configuration files allow users to customize app settings and behaviour as per changing development needs in Laravel. Moreover, it lets users configure different components of the application, like mail server and database connection information. Within the Laravel project, Laravel’s configuration settings exist in the config […]
Chandan Kumar October 21, 2024
Mastering Laravel Form Requests: Several Techniques for Cleaner Validation
Laravel
Mastering Laravel Form Requests: Several Techniques for Cleaner Validation
Laravel Form Requests streamline validation by moving rules from the controller to a separate class, ensuring cleaner, reusable, and maintainable code.
Chandan Kumar October 17, 2024