freento / module-mcp-audit
MCP Audit Tools for Magento 2
Freento MCP Audit Tools for Magento 2
Add-on for Freento_Mcp that registers a set of audit and diagnostic MCP tools. The tools are designed for AI-driven store audits — collecting structured data about the filesystem, database, configuration, logs, indexers, cron, third-party modules, code quality and email delivery, all exposed over the standard MCP protocol provided by Freento_Mcp.
Features
- 16 ready-to-use audit tools registered into the parent module's
ToolRegistry - Single admin toggle to hide every audit tool everywhere (tools/list, tools/call, ACL UI)
- Log error grouping with smart message normalization (UUIDs, IDs, quoted values, emails)
- Two-step on-demand SQL query counter for any frontend URL (bypasses FPC)
- Sensitive
env.phpkeys (passwords, secrets, hosts, ports, etc.) automatically masked - Curated critical-settings check (deployment mode, 2FA, MySQL optimizer, Xdebug/APCu, key rotation, …)
Requirements
- Magento 2.4.x
- PHP 8.1+
freento/module-mcp^1.2(loaded as a module sequence dependency)magento/magento-coding-standard(declared as a composer dependency; required byrun_code_sniffer)
Installation
Via Composer
composer require freento/module-mcp-audit
php bin/magento module:enable Freento_McpAudit
php bin/magento setup:upgrade
php bin/magento cache:flush
Manual
Copy the module to app/code/Freento/McpAudit/ and run:
php bin/magento module:enable Freento_McpAudit
php bin/magento setup:upgrade
php bin/magento cache:flush
Configuration
Stores > Configuration > Freento > MCP > MCP Audit
| Field | Path | Description |
|---|---|---|
| Enable Audit Tools | freento_mcp/audit/enabled |
When disabled, all McpAudit tools are hidden everywhere — they are not exposed via tools/list, cannot be called, and do not appear in the ACL Rule tools list. |
The toggle is enforced at the ToolRegistry level via Plugin\ToolRegistryPlugin, which filters out every tool whose class lives under the Freento\McpAudit\ namespace when the module is disabled.
Available Tools
Database & Filesystem
| Tool | Description |
|---|---|
get_table_sizes |
Database table sizes (rows + MB) sorted by size, with optional LIKE pattern, min-size and limit filters. |
get_log_file_sizes |
Files in var/log and var/report sorted by size, with each file's inode change time (ctime). |
Logs & Errors
| Tool | Description |
|---|---|
get_log_errors |
Greps var/log/*.log for ERROR/CRITICAL entries, groups identical errors after normalizing UUIDs, IDs, quoted strings and emails. Filterable by date range (silently truncated to the first 31 days starting at from_date), sortable by count/first_seen/last_seen. Defaults: from_date/to_date = today, limit = 50 (max 200). |
Indexers & Cron
| Tool | Description |
|---|---|
get_indexer_statuses |
All indexers with status (valid/invalid/working), mode (schedule/save) and changelog backlog count. |
get_cron_config |
Cron groups configuration: schedule/lifetime/cleanup settings (XML defaults vs DB overrides), use_separate_process flag, and per-group job list with cron expressions. |
get_cron_schedule |
Cron schedule history (cron_schedule table) with filtering, sorting and aggregation, plus a derived execution_time field (finished_at - executed_at, rendered as a human-readable duration like 5m 30s). |
Configuration
| Tool | Description |
|---|---|
get_critical_settings |
Curated checks that are awkward to express via the generic config tools: deployment mode, admin URL, 2FA status, active cart rules without a coupon (always-on rules), MySQL optimizer_switch / optimizer_use_condition_selectivity, Xdebug + APCu state, search terms count, presence of an active admin user, and whether the encryption key has been rotated. |
get_config_data |
Fully resolved ScopeConfigInterface values (config.xml + core_config_data + env.php overrides). Accepts exact paths or path prefixes; supports default/websites/stores scopes and all_scopes: true for a full dump. |
get_php_ini_settings |
ini_get() lookup for an explicit list of php.ini directives. |
get_deployment_config |
Values from app/etc/env.php for an explicit paths list. Sensitive entries are silently omitted — match either a substring (password, passwd, secret, token, crypt, salt, private, credential, api_key, access_key, bearer, oauth, signature, hmac) or a full path segment (host, port, server, dbname, username, user, pwd, pass, key, auth, pem, cert). |
Modules & Code Quality
| Tool | Description |
|---|---|
get_third_party_modules |
Installed non-Magento and non-PayPal modules grouped by vendor, with composer name and install location (app/code vs vendor/). Optional include_latest_version queries the configured composer repositories for available stable upgrades. |
run_code_sniffer |
Runs vendor/bin/phpcs --standard=Magento2 against a module name (Vendor_Module), relative path, or absolute path. Output is parsed from JSON, filtered by severity, capped at 200 KB, and grouped per file. |
Catalog & Customer
| Tool | Description |
|---|---|
get_customer_groups |
customer_group rows with filtering and aggregation (entity-tool framework). |
get_eav_attributes |
eav_attribute rows with filtering by entity type, backend type, frontend input, native vs user-defined. |
Performance & Email
| Tool | Description |
|---|---|
count_sql_queries |
Counts SQL queries executed for an arbitrary storefront URL (the SqlCounterPlugin is registered in the frontend area only — admin/API requests are not counted). Two-step flow: action=start returns a counter ID and a visit URL containing ?_sql_counter=<id>; visiting that URL triggers the plugin (FPC bypassed by the unique query string); action=get returns the count. |
send_test_email |
Sends a test email through the configured customer-create-account template, using the store's transactional sender. Useful for verifying SMTP and trans_email/ident_general/*. |
Architecture
How tools are registered
etc/di.xml extends the parent module's Freento\Mcp\Model\ToolRegistry constructor's tools array argument, plus attaches ToolRegistryPlugin:
<type name="Freento\Mcp\Model\ToolRegistry">
<arguments>
<argument name="tools" xsi:type="array">
<item name="get_table_sizes" xsi:type="object">Freento\McpAudit\Model\Tool\GetTableSizes</item>
<!-- … 15 more entries … -->
</argument>
</arguments>
<plugin name="freento_mcp_audit_tool_registry"
type="Freento\McpAudit\Plugin\ToolRegistryPlugin"
sortOrder="100"/>
</type>
How the SQL counter works
Plugin\SqlCounterPlugin is wired (in etc/frontend/di.xml, frontend area only) as a before plugin on Magento\Framework\DB\LoggerInterface::logStats. When a storefront request includes the _sql_counter=<id> parameter:
- The plugin reads
var/tmp/sql_counter/<id>.pending(created bycount_sql_querieswithaction=start). - Every call to
LoggerInterface::logStatsincrements an in-memory counter. Any SQL whose text contains the literal substringsql_counteris skipped as a defensive guard against self-counting. - On plugin instance teardown (
__destruct, end of request lifecycle), the result is written tovar/tmp/sql_counter/<id>.resultand the pending file is deleted. - A subsequent
count_sql_queriescall withaction=getreturns the result and cleans up.
The _sql_counter parameter doubles as a cache-busting query string, so the counted response is guaranteed not to be served from FPC.
API Reference
All tools are invoked through the parent Freento_Mcp JSON-RPC endpoint (/freento_mcp/index/index). The audit module only adds tools — the request format, authentication, and transport are documented in the parent module README.
List audit tools
tools/list returns every registered tool; audit tools are the ones whose names appear in the table above.
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Call an audit tool
get_table_sizes — top 10 largest tables
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"get_table_sizes","arguments":{"limit":10}}
}'
get_log_errors — grouped errors for a date range
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"get_log_errors","arguments":{
"from_date":"2026-04-01","to_date":"2026-04-30",
"sort_by":"count","sort_dir":"desc","limit":20
}}
}'
get_config_data — read a subtree across all scopes
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":4,"method":"tools/call",
"params":{"name":"get_config_data","arguments":{
"paths":["dev/css","dev/js"],"all_scopes":true
}}
}'
get_deployment_config — values from app/etc/env.php
Sensitive segments (password, host, dbname, …) are silently omitted.
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":5,"method":"tools/call",
"params":{"name":"get_deployment_config","arguments":{
"paths":["session/save","cache"]
}}
}'
get_php_ini_settings
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":6,"method":"tools/call",
"params":{"name":"get_php_ini_settings","arguments":{
"keys":["memory_limit","max_execution_time",
"opcache.memory_consumption","opcache.validate_timestamps"]
}}
}'
count_sql_queries — two-step flow
# 1. Start: get a counter ID and a visit URL
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":7,"method":"tools/call",
"params":{"name":"count_sql_queries","arguments":{
"action":"start","url":"https://your-store.com/"
}}
}'
# 2. Visit the returned URL (browser or curl). The _sql_counter param bypasses FPC.
curl -s "https://your-store.com/?_sql_counter=<counter_id>" >/dev/null
# 3. Get the result
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":8,"method":"tools/call",
"params":{"name":"count_sql_queries","arguments":{
"action":"get","counter_id":"<counter_id>"
}}
}'
run_code_sniffer
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":9,"method":"tools/call",
"params":{"name":"run_code_sniffer","arguments":{
"path":"Freento_McpAudit","severity":"errors","limit":50
}}
}'
send_test_email
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":10,"method":"tools/call",
"params":{"name":"send_test_email","arguments":{
"email":"[email protected]","store_id":1
}}
}'
Entity-list tools (get_cron_schedule, get_customer_groups, get_eav_attributes)
These extend the parent module's entity-tool framework, so they accept the same filters / function / field / group_by / limit / sort_by / sort_dir parameters as the rest of Freento_Mcp (see parent README — Filters / Aggregation).
# Failed cron jobs in the last 7 days, grouped by job_code
curl -X POST https://your-store.com/freento_mcp/index/index \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"jsonrpc":"2.0","id":11,"method":"tools/call",
"params":{"name":"get_cron_schedule","arguments":{
"filters":{
"status":{"in":["error","missed"]},
"scheduled_at":{"gte":"2026-04-29"}
},
"function":"count","group_by":"job_code","limit":20
}}
}'
License
MIT
No changelog yet
The vendor hasn't published a changelog. Tagged releases appear in the Versions tab.
Requires 3
| Package | Constraint |
|---|---|
| freento/module-mcp | ^1.2 |
| magento/magento-coding-standard | * |
| php | ^8.1 |
Compatibility
Each Magento release line is installed on its supported PHP versions, then the module is built (DI compilation + static-content deploy) and its unit and integration suites are run. The matrix shows the lines and PHP versions the module is confirmed to install and run on. Code-quality results further down (phpstan, phpcs, …) are reported separately and never affect compatibility.
Code Quality
Advisory checks against the module's source. Static analysis runs once across the whole module; PHPStan re-runs per Magento + PHP version because resolvable symbols differ between releases. These NEVER affect the Compatibility badge. A phpcs finding can't make a module incompatible.
Static analysis
Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.
| Tool | Status | Findings | Summary |
|---|---|---|---|
| PHPCS | Fail | 27 | 2 errors, 25 warnings (ruleset: Magento2) |
| PHPMD | Warning | 28 | 28 rule violations (MissingImport:16, NPathComplexity:5, CyclomaticComplexity:4, EmptyCatchBlock:1, ExcessiveClassComplexity:1) |
| Cpd | Pass | 0 | |
| Composer validate | Info | 2 | valid; 2 advisory notes (composer validate --strict) |
Tests
Unit and integration suites, run for each applicable Magento and PHP version. A test failure speaks to the module's behaviour, not its compatibility with a Magento line, so it is reported here separately and never reddens the compatibility matrix.
Unit tests
| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | ||
| 2.4.8 | N/A | N/A | ||
| 2.4.9 | N/A | N/A |
Integration tests
| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | ||
| 2.4.8 | N/A | N/A | ||
| 2.4.9 | N/A | N/A |
Security
Security checks run directly against the module: an audit of its declared dependencies for known vulnerabilities (composer audit) and a scan of its source for malware and web-shell signatures. Each runs once. A malware detection fails the version outright.
More from Freento
View vendorMCP (Model Context Protocol) server for Magento 2 - All-in-one module
Dimensional Shipping module with REST API integration
Catches all emails sent from a Magento store and additionally logs them to the database.
Turn an existing module into recurring revenue.
If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.