MCP Inspector

Sorry, page is not translated yet.

MCP Inspector is the bridge between any AI tool and your Nette application. It allows AI assistants to look directly at your running app – to see what services you have registered, what your database schema looks like, which routes are defined, and what errors have occurred.

This is what makes the difference between AI that guesses and AI that knows.

MCP Inspector is still in early development and has no stable release yet. Install it with composer require nette/mcp-inspector:@dev and expect the API – tool names, configuration – to keep changing before the first stable release.

Supported AI Tools

MCP Inspector works with any tool that supports the Model Context Protocol (MCP):

  • Claude Code – Full support with dedicated Nette plugin
  • Cursor – Configure via .cursor/mcp.json
  • VS Code + Continue – Configure via Continue settings
  • Any MCP-compatible tool – See manual configuration

Why MCP Matters

Imagine you ask your AI: “Generate an entity for the product table.”

Without MCP Inspector, the AI has to guess what columns your table has. It might assume common patterns like id, name, price – but what if your table has different columns? What if price is called unit_price? What if you have a currency_id foreign key?

With MCP Inspector, the AI doesn't guess. It calls db_get_columns("product") and sees your actual schema:

The result is code that actually works with your database, not code you have to fix.

Installation

If you're using the Nette plugin for Claude Code, installation is simple:

/install-mcp-inspector

This command adds nette/mcp-inspector to your project and configures everything automatically.

For other AI tools or manual installation:

composer require nette/mcp-inspector:@dev

Then create a mcp-bootstrap.php file in your project root (see Configuration) and point your AI tool at the MCP server – see manual configuration below.

Important: After installation, restart your AI tool. The MCP server only connects when the tool starts.

How It Works

MCP Inspector runs as a background process that your AI tool can communicate with. When AI needs information about your application, it sends a request to MCP Inspector, which:

  1. Builds your application's DI container via the mcp-bootstrap.php script (see Configuration)
  2. Executes the requested query (get services, read database schema, etc.)
  3. Returns the result to the AI

The container is rebuilt on every request, so edits to your services.neon and other config files are picked up live – no need to restart the AI tool.

All operations are read-only. MCP Inspector can't modify your database, change configuration, or execute commands.

DI Container Tools

These tools let AI explore your service definitions.

di_get_services

Lists all registered services. You can filter by name or type.

When AI asks “What mail services do I have?”, it calls:

di_get_services("mail")

And gets a list like:

- mail.mailer (Nette\Mail\Mailer)
- App\Model\QueueMailer
- App\Core\SmtpTransport

di_get_service

Gets information about a specific service – its type, tags, and whether it has already been instantiated. Compile-time details like the factory expression or setup calls are intentionally not exposed.

di_get_parameter_names

Lists the names of all configuration parameters. Nested parameters are flattened to dotted notation (e.g. database.default.dsn), so you can discover exactly which keys exist before reading a value.

di_get_parameter

Reads a single configuration parameter by name. Use dotted notation to reach nested values:

di_get_parameter("database.default.dsn")

Note: Sensitive values (passwords, tokens, API keys, connection strings) are automatically masked.

di_get_aliases

Lists all service aliases as a map of alias name to the canonical service name.

di_find_by_tag

Finds services with a specific tag. Useful for discovering CLI commands:

di_find_by_tag("console.command")

di_find_by_type

Finds services implementing a specific interface:

di_find_by_type("Nette\\Security\\Authenticator")

Database Tools

These tools give AI visibility into your database structure.

db_get_tables

Lists all tables in your database.

db_get_columns

Gets detailed column information for a table – types, whether they're nullable, default values, and foreign key relationships.

db_get_columns("order")

Returns something like:

- id: int (PRIMARY KEY)
- customer_id: int (FK → customer.id)
- status: varchar(20)
- total: decimal(10,2)
- created_at: datetime

db_get_relationships

Shows all foreign key relationships in your database – which tables reference which other tables.

db_get_indexes

Lists indexes for a specific table.

db_explain_query

Runs EXPLAIN on a SELECT query to analyze its performance. AI can use this to suggest query optimizations.

db_generate_entity

The most useful tool for quick development. Given a table name, it generates a complete PHP entity class with @property type hints derived from the column types:

db_generate_entity("product")

Generates:

<?php

/**
 * @property-read int $id
 * @property-read string $name
 * @property-read float $unit_price
 * @property-read ?CategoryRow $category
 * @property-read DateTimeImmutable $created_at
 */
final class ProductRow extends Table\ActiveRow
{
}

The generator maps each column to a scalar type (foreign keys stay as their raw *_id columns) and singularizes the table name for the class name. Refine the result – relation properties, the Row suffix, nullability – to match your own conventions.

Router Tools

These tools help AI understand your URL structure.

router_get_routes

Lists all registered routes with their masks and default values.

router_match_url

Given a URL, finds which presenter and action handles it:

router_match_url("/admin/products/edit/5")

Returns:

Presenter: Admin:Product
Action: edit
Parameters: id=5

router_generate_url

Generates a URL for a given presenter and action:

router_generate_url("Admin:Product:edit", {"id": 5})

Tracy Tools

These tools let AI see error logs and help with debugging. They're incredibly useful when something goes wrong – instead of you describing the error, AI can read it directly.

tracy_get_last_exception

Gets the most recent exception from Tracy's log, including the full stack trace. When something breaks, this is the first thing AI checks.

tracy_get_last_exception()

Returns the exception class, message, file, line number, and complete stack trace. AI can analyze this to identify the root cause and suggest a fix.

Example response:

Exception: Nette\Database\UniqueConstraintViolationException
Message: Duplicate entry 'john@example.com' for key 'email'
File: /app/Model/UserService.php:45
Stack trace:
  #0 /app/Presentation/Admin/UserPresenter.php:32
  #1 /vendor/nette/application/src/...

tracy_get_exceptions

Lists recent exception files from Tracy's log directory. Useful for finding patterns or recurring issues.

tracy_get_exceptions(5)

Returns the 5 most recent exception files with timestamps. You can then use tracy_get_exception to examine any of them.

tracy_get_exception

Gets the complete details of a specific exception file. Use this when you want to examine an older exception, not just the latest one.

tracy_get_exception("exception-2024-01-15-143022-abc123.html")

tracy_get_warnings

Shows recent PHP warnings and notices from Tracy's log. These often indicate problems that don't crash the application but should be fixed.

tracy_get_warnings(10)

Common warnings AI can help fix:

  • Undefined array key
  • Deprecated function calls
  • Type mismatch warnings

tracy_get_log

Reads entries from any Tracy log level. Tracy supports multiple log files: error.log, warning.log, info.log, and custom levels.

tracy_get_log("error", 20)

This reads the last 20 entries from the error log. Useful for seeing a history of issues, not just the most recent one.

Creating Custom Tools

You can extend MCP Inspector with your own tools. This is useful if you have application-specific data that AI should be able to query.

Create a class implementing the Toolkit marker interface and annotate its methods with #[McpTool]. Dependencies are injected the usual Nette way:

use Mcp\Capability\Attribute\McpTool;
use Nette\Database\Explorer;
use Nette\McpInspector\Toolkit;

class OrderToolkit implements Toolkit
{
	public function __construct(
		private Explorer $database,
	) {}

	/**
	 * Get pending orders count and total value.
	 */
	#[McpTool(name: 'orders_get_pending_summary')]
	public function getPendingSummary(): array
	{
		$result = $this->database->table('order')
			->where('status', 'pending')
			->select('COUNT(*) AS count, SUM(total) AS total')
			->fetch();

		return [
			'count' => $result->count,
			'total' => $result->total,
		];
	}
}

Register it as an ordinary service in your services.neon – MCP Inspector auto-discovers every service that implements Toolkit:

services:
	- App\Mcp\OrderToolkit

Now AI can call orders_get_pending_summary() to get real-time order statistics.

Configuration

MCP Inspector needs to know how to build your application's DI container. It looks for a file named mcp-bootstrap.php in your project root, which must return a closure that produces the container. For a standard Nette Web Project it's a one-liner:

<?php
require __DIR__ . '/vendor/autoload.php';
return fn() => App\Bootstrap::boot()->createContainer();

The closure is invoked on every request, so changes to your services.neon and other config files are reflected immediately. If a rebuild fails (e.g. a typo in your config), MCP Inspector keeps serving the last working container and adds a warning to the result.

If your Bootstrap takes constructor arguments (multi-tenant apps and similar), build it your own way inside the closure and return the container from your own boot method – just keep the new Configurator call inside the Bootstrap class so Nette's %appDir% autodetection keeps working:

<?php
require __DIR__ . '/vendor/autoload.php';
return fn() => (new App\Bootstrap($tenant))->bootContainer();

You can point to a different bootstrap file with --bootstrap, or to a different project root with --project:

php vendor/bin/mcp-inspector --project=/path/to/project --bootstrap=cli-bootstrap.php

Manual MCP Configuration

For AI tools other than Claude Code (which configures automatically via the plugin), add MCP Inspector to your tool's configuration:

For most MCP-compatible tools, create .mcp.json in your project root:

{
	"mcpServers": {
		"nette-inspector": {
			"command": "php",
			"args": ["vendor/bin/mcp-inspector"]
		}
	}
}

For Cursor, add to .cursor/mcp.json:

{
	"mcpServers": {
		"nette-inspector": {
			"command": "php",
			"args": ["vendor/bin/mcp-inspector"]
		}
	}
}

Consult your AI tool's documentation for the exact configuration location.

Security Considerations

MCP Inspector is designed for development environments. Here's what you should know:

Read-only by design – All tools only read data, never modify it.

Database protection – The db_explain_query tool accepts only a single SELECT query (an optional EXPLAIN prefix is stripped first). Everything else – INSERT, UPDATE, DELETE, SHOW, DESCRIBE as well as multi-statement input – is rejected.

Sensitive data masking – Configuration values containing words like “password”, “secret”, “token”, or “apikey” are automatically masked with ***MASKED***.

Do not expose in production – MCP Inspector should only run on development machines. It provides detailed information about your application internals that you don't want exposed publicly.