diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index cb86435..a2f1f98 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -7,7 +7,10 @@
-
+
+
+
+
diff --git a/src/Abilities/Ability.php b/src/Abilities/Ability.php
index 095f73d..d24fb55 100644
--- a/src/Abilities/Ability.php
+++ b/src/Abilities/Ability.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Abilities;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* One capability of the MCP server, registered with the WordPress Abilities API.
*/
diff --git a/src/Abilities/AbilityRegistrar.php b/src/Abilities/AbilityRegistrar.php
index 0e84f0e..be1352e 100644
--- a/src/Abilities/AbilityRegistrar.php
+++ b/src/Abilities/AbilityRegistrar.php
@@ -11,6 +11,8 @@ use LIT\MCP\Server\RequestContext;
use Throwable;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Registers all abilities of available integrations with the Abilities API and
* wraps them with the role gate and neutral error handling.
diff --git a/src/Abilities/Annotations.php b/src/Abilities/Annotations.php
index c7b6dbe..0f4c812 100644
--- a/src/Abilities/Annotations.php
+++ b/src/Abilities/Annotations.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Abilities;
+defined('ABSPATH') || exit;
+
/**
* The MCP annotations of an ability (Ability::annotations()), in three presets. "readonly"
* drives the "nur lesen" group switch (ExposurePolicy::disabledByReadonly()) and, with
diff --git a/src/Abilities/Cursor.php b/src/Abilities/Cursor.php
index c98688b..7d984cb 100644
--- a/src/Abilities/Cursor.php
+++ b/src/Abilities/Cursor.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Abilities;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Opaque offset cursor for list tools (spec §8.1, §11.3).
*/
diff --git a/src/Abilities/Errors.php b/src/Abilities/Errors.php
index 3b6f6c2..a20df2e 100644
--- a/src/Abilities/Errors.php
+++ b/src/Abilities/Errors.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Abilities;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Factory for the error objects abilities return.
*
diff --git a/src/Abilities/ExposurePolicy.php b/src/Abilities/ExposurePolicy.php
index 8ce5614..07aa2f2 100644
--- a/src/Abilities/ExposurePolicy.php
+++ b/src/Abilities/ExposurePolicy.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Abilities;
+defined('ABSPATH') || exit;
+
/**
* Decides per ability whether it is a direct MCP tool, only reachable through the
* adapter's meta-tools, or disabled (spec §4.3). Ability::isDirect() is the default.
diff --git a/src/Abilities/FollowUp.php b/src/Abilities/FollowUp.php
index 039f79b..76bcb53 100644
--- a/src/Abilities/FollowUp.php
+++ b/src/Abilities/FollowUp.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Abilities;
use LIT\MCP\Log;
use Throwable;
+defined('ABSPATH') || exit;
+
/**
* Runs a step after a write has already succeeded (listeners, change log): a failure
* there must not turn the saved change into an error. It is logged and reported as warning.
diff --git a/src/Abilities/JsonMap.php b/src/Abilities/JsonMap.php
index 52ecef8..1378eb0 100644
--- a/src/Abilities/JsonMap.php
+++ b/src/Abilities/JsonMap.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Abilities;
use stdClass;
+defined('ABSPATH') || exit;
+
/**
* PHP encodes an empty array as JSON [] – for schema type "object" the client
* must see {}. WordPress' output validation accepts stdClass for objects.
diff --git a/src/Abilities/Rev.php b/src/Abilities/Rev.php
index 3a6521b..8ed6b14 100644
--- a/src/Abilities/Rev.php
+++ b/src/Abilities/Rev.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Abilities;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Short hash used as optimistic-lock handle ("rev", spec §5.3).
*/
diff --git a/src/Abilities/Rollback.php b/src/Abilities/Rollback.php
index 2a16166..6d6d4d1 100644
--- a/src/Abilities/Rollback.php
+++ b/src/Abilities/Rollback.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Abilities;
use Throwable;
+defined('ABSPATH') || exit;
+
/**
* Runs the undo steps of a failed write. Every step runs, even after an earlier one failed;
* a step fails by throwing. The caller turns the collected messages into the log detail and
diff --git a/src/Abilities/Text.php b/src/Abilities/Text.php
index afbdef2..f1ef944 100644
--- a/src/Abilities/Text.php
+++ b/src/Abilities/Text.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Abilities;
+defined('ABSPATH') || exit;
+
/**
* Small text helper shared by every summary that must stay bounded in size (outlines, node
* summaries, the rendered-page excerpt): extracts are a fixed-size preview, never an unbounded
diff --git a/src/Abilities/ToolResult.php b/src/Abilities/ToolResult.php
index 9dbaf00..ad5e899 100644
--- a/src/Abilities/ToolResult.php
+++ b/src/Abilities/ToolResult.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Abilities;
use InvalidArgumentException;
+defined('ABSPATH') || exit;
+
/**
* Uniform success result of every writing ability (spec §8.1).
* The adapter returns it as structuredContent plus JSON text.
diff --git a/src/Abilities/WriteFailed.php b/src/Abilities/WriteFailed.php
index 472acdc..6f59ce8 100644
--- a/src/Abilities/WriteFailed.php
+++ b/src/Abilities/WriteFailed.php
@@ -8,6 +8,8 @@ use RuntimeException;
use Throwable;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Thrown by write paths when saving failed after something may already have been
* written. getMessage() is the internal detail for the PHP error log; $reason is the
diff --git a/src/Access.php b/src/Access.php
index e77a0c3..41e72b0 100644
--- a/src/Access.php
+++ b/src/Access.php
@@ -6,6 +6,8 @@ namespace LIT\MCP;
use WP_User;
+defined('ABSPATH') || exit;
+
/**
* Role gate: only users whose role is allowed get the lit_mcp_use capability.
*
diff --git a/src/Admin/AccessTab.php b/src/Admin/AccessTab.php
index 0b98129..b205017 100644
--- a/src/Admin/AccessTab.php
+++ b/src/Admin/AccessTab.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Admin;
use LIT\MCP\Access;
+defined('ABSPATH') || exit;
+
/**
* Tab "Zugriff": roles allowed to use LIT MCP and the active OAuth connections
* with revocation (spec §8.4).
diff --git a/src/Admin/AdminNotices.php b/src/Admin/AdminNotices.php
index 905654f..c790f4c 100644
--- a/src/Admin/AdminNotices.php
+++ b/src/Admin/AdminNotices.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Admin;
+defined('ABSPATH') || exit;
+
/**
* Admin notices for administrators (Etappe-0 follow-up d). Uses only cached check
* results so no HTTP request runs on ordinary admin page loads.
diff --git a/src/Admin/AdminPostAction.php b/src/Admin/AdminPostAction.php
index 2708dc0..6d3358e 100644
--- a/src/Admin/AdminPostAction.php
+++ b/src/Admin/AdminPostAction.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Admin;
+defined('ABSPATH') || exit;
+
/**
* The frame of an admin-post.php handler of the settings page: only administrators
* (manage_options, else 403), and after the action a redirect back to the tab with a notice.
diff --git a/src/Admin/AdminTab.php b/src/Admin/AdminTab.php
index cdfd7a0..298026c 100644
--- a/src/Admin/AdminTab.php
+++ b/src/Admin/AdminTab.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Admin;
+defined('ABSPATH') || exit;
+
/**
* One tab of the settings page "Einstellungen → LIT MCP".
*/
diff --git a/src/Admin/ConnectionRepository.php b/src/Admin/ConnectionRepository.php
index 8cd39ea..c815cee 100644
--- a/src/Admin/ConnectionRepository.php
+++ b/src/Admin/ConnectionRepository.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Admin;
use WPMedia\MCP\OAuth\Auth\TokenEndpoint;
+defined('ABSPATH') || exit;
+
/**
* OAuth connections created by mcp-oauth (v1.1.2, TokenEndpoint): for every grant it
* creates one application password (name = client name, app_id = the CIMD client_id,
diff --git a/src/Admin/ConnectionStatus.php b/src/Admin/ConnectionStatus.php
index 08ba27d..a6e1918 100644
--- a/src/Admin/ConnectionStatus.php
+++ b/src/Admin/ConnectionStatus.php
@@ -9,6 +9,8 @@ use WP\MCP\Core\McpAdapter;
use WPMedia\MCP\OAuth\Auth\Discovery\HealthCheck;
use WPMedia\MCP\OAuth\Context as OAuthContext;
+defined('ABSPATH') || exit;
+
/**
* Connection checks for the settings page, admin notices and Site Health.
* Not final so notices and Site Health can be tested with a mock.
diff --git a/src/Admin/ConnectionTab.php b/src/Admin/ConnectionTab.php
index 1e30beb..76a8b6f 100644
--- a/src/Admin/ConnectionTab.php
+++ b/src/Admin/ConnectionTab.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Admin;
+defined('ABSPATH') || exit;
+
final class ConnectionTab implements AdminTab
{
public function __construct(private ConnectionStatus $status)
diff --git a/src/Admin/ConnectionUsage.php b/src/Admin/ConnectionUsage.php
index 351e1a8..a5904c0 100644
--- a/src/Admin/ConnectionUsage.php
+++ b/src/Admin/ConnectionUsage.php
@@ -10,6 +10,8 @@ use WP_REST_Request;
use WPMedia\MCP\OAuth\Auth\JWT;
use WPMedia\MCP\OAuth\Auth\SecretManager;
+defined('ABSPATH') || exit;
+
/**
* Records when an OAuth connection was last used, for "Zuletzt genutzt" in the tab "Zugriff".
*
diff --git a/src/Admin/LimitsTab.php b/src/Admin/LimitsTab.php
index 16183cc..4df5d73 100644
--- a/src/Admin/LimitsTab.php
+++ b/src/Admin/LimitsTab.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Admin;
use LIT\MCP\Limits;
+defined('ABSPATH') || exit;
+
/**
* Tab "Limits": upload/download size and log retention (spec §8.4). The snapshot count is
* kept as a hidden field until the design system feature that uses it exists.
diff --git a/src/Admin/LogListTable.php b/src/Admin/LogListTable.php
index 20f64a9..54cc36a 100644
--- a/src/Admin/LogListTable.php
+++ b/src/Admin/LogListTable.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Admin;
use LIT\MCP\ChangeLog\ChangeLog;
use WP_Post;
+defined('ABSPATH') || exit;
+
// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- method names are defined by WP_List_Table.
/**
diff --git a/src/Admin/LogObjects.php b/src/Admin/LogObjects.php
index 6e017ad..6eff676 100644
--- a/src/Admin/LogObjects.php
+++ b/src/Admin/LogObjects.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Admin;
use WP_Post;
use WP_Term;
+defined('ABSPATH') || exit;
+
/**
* Human names for the objects in the change log ("Seite: Kontakt" instead of "page 834"),
* linked to their edit screen where one exists and the current user may use it. prime()
diff --git a/src/Admin/LogTab.php b/src/Admin/LogTab.php
index b0eef8c..6bae64a 100644
--- a/src/Admin/LogTab.php
+++ b/src/Admin/LogTab.php
@@ -8,6 +8,8 @@ use LIT\MCP\ChangeLog\ChangeLog;
use LIT\MCP\Integrations\IntegrationRegistry;
use LIT\MCP\Limits;
+defined('ABSPATH') || exit;
+
/**
* Tab "Protokoll": filterable list of change log entries, links to revisions, and
* "Protokoll leeren" (spec §8.3). Page size and visible columns via WordPress'
diff --git a/src/Admin/SettingsPage.php b/src/Admin/SettingsPage.php
index c3aac12..b35d112 100644
--- a/src/Admin/SettingsPage.php
+++ b/src/Admin/SettingsPage.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Admin;
+defined('ABSPATH') || exit;
+
/**
* Settings page "Einstellungen → LIT MCP" with tabs (spec §8.4). Settings API, no JS framework.
*/
diff --git a/src/Admin/SiteHealth.php b/src/Admin/SiteHealth.php
index bb0e2f9..aed9fb0 100644
--- a/src/Admin/SiteHealth.php
+++ b/src/Admin/SiteHealth.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Admin;
+defined('ABSPATH') || exit;
+
/**
* Site Health test for our MCP endpoint (401 + WWW-Authenticate without a token).
* The discovery documents are covered by mcp-oauth's own Site Health test.
diff --git a/src/Admin/ToolsTab.php b/src/Admin/ToolsTab.php
index 7ed367c..2bb8f01 100644
--- a/src/Admin/ToolsTab.php
+++ b/src/Admin/ToolsTab.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Ability;
use LIT\MCP\Abilities\ExposurePolicy;
use LIT\MCP\Integrations\IntegrationRegistry;
+defined('ABSPATH') || exit;
+
/**
* Tab "Tools": direct/indirect/disabled exposure per ability (spec §8.4), grouped by the
* integration the ability comes from. Each group has its own mode (inherited by its tools)
diff --git a/src/ChangeLog/ChangeLog.php b/src/ChangeLog/ChangeLog.php
index 0ef0c0a..9e0f6d3 100644
--- a/src/ChangeLog/ChangeLog.php
+++ b/src/ChangeLog/ChangeLog.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\FollowUp;
use LIT\MCP\Log;
use LIT\MCP\Server\RequestContext;
+defined('ABSPATH') || exit;
+
/**
* Change log table {prefix}lit_mcp_log (spec §8.3). Stores references only,
* never content. Deliberately not final so abilities can be unit-tested with a mock.
diff --git a/src/ChangeLog/ChangeLogCleanup.php b/src/ChangeLog/ChangeLogCleanup.php
index 820e584..3216a0d 100644
--- a/src/ChangeLog/ChangeLogCleanup.php
+++ b/src/ChangeLog/ChangeLogCleanup.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\ChangeLog;
use LIT\MCP\Limits;
+defined('ABSPATH') || exit;
+
/**
* Daily WP-Cron job that removes log rows older than the configured retention.
*/
diff --git a/src/ChangeLog/ChangeLogInstaller.php b/src/ChangeLog/ChangeLogInstaller.php
index ea1b5fd..d32bde9 100644
--- a/src/ChangeLog/ChangeLogInstaller.php
+++ b/src/ChangeLog/ChangeLogInstaller.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\ChangeLog;
+defined('ABSPATH') || exit;
+
/**
* Creates/updates the change log table via dbDelta. Runs on activation and –
* because plugin updates never fire the activation hook – whenever the stored
diff --git a/src/Dependencies.php b/src/Dependencies.php
index 6524ea3..a1b43fb 100644
--- a/src/Dependencies.php
+++ b/src/Dependencies.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP;
+defined('ABSPATH') || exit;
+
/**
* Checks that the libraries WP-LIT-MCP builds on are loadable.
*/
diff --git a/src/Guides/GuideRepository.php b/src/Guides/GuideRepository.php
index 64b6561..ee8feba 100644
--- a/src/Guides/GuideRepository.php
+++ b/src/Guides/GuideRepository.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Guides;
+defined('ABSPATH') || exit;
+
/**
* Guide topics: markdown files from one directory (the default), extended or overridden
* by the site via the filter `lit_mcp_guides` (spec §9.2), which returns
diff --git a/src/Guides/InstructionsBuilder.php b/src/Guides/InstructionsBuilder.php
index adbf553..d7497bc 100644
--- a/src/Guides/InstructionsBuilder.php
+++ b/src/Guides/InstructionsBuilder.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\ExposurePolicy;
use LIT\MCP\Integrations\Integration;
use LIT\MCP\Integrations\IntegrationRegistry;
+defined('ABSPATH') || exit;
+
/**
* Builds the short server instructions every MCP client loads on connect.
* Keep this text short: it occupies context in every conversation.
diff --git a/src/Integrations/Core/CoreIntegration.php b/src/Integrations/Core/CoreIntegration.php
index 5c4c762..ce97bf0 100644
--- a/src/Integrations/Core/CoreIntegration.php
+++ b/src/Integrations/Core/CoreIntegration.php
@@ -8,6 +8,8 @@ use LIT\MCP\Access;
use LIT\MCP\Guides\GuideRepository;
use LIT\MCP\Integrations\Integration;
+defined('ABSPATH') || exit;
+
final class CoreIntegration implements Integration
{
public function __construct(private string $guidesDirectory)
diff --git a/src/Integrations/Core/EnvironmentProbe.php b/src/Integrations/Core/EnvironmentProbe.php
index 7e059b7..aca8d8e 100644
--- a/src/Integrations/Core/EnvironmentProbe.php
+++ b/src/Integrations/Core/EnvironmentProbe.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Core;
+defined('ABSPATH') || exit;
+
/**
* Detects the themes/plugins LIT MCP integrates with.
*/
diff --git a/src/Integrations/Core/GuideAbility.php b/src/Integrations/Core/GuideAbility.php
index 1375f52..8cd7800 100644
--- a/src/Integrations/Core/GuideAbility.php
+++ b/src/Integrations/Core/GuideAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Abilities\Errors;
use LIT\MCP\Guides\GuideRepository;
use WP_Error;
+defined('ABSPATH') || exit;
+
final class GuideAbility implements Ability
{
private const DEFAULT_TOPIC = 'overview';
diff --git a/src/Integrations/Core/SiteStatusAbility.php b/src/Integrations/Core/SiteStatusAbility.php
index 17adb7a..2313c7c 100644
--- a/src/Integrations/Core/SiteStatusAbility.php
+++ b/src/Integrations/Core/SiteStatusAbility.php
@@ -9,6 +9,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Access;
use WP_Error;
+defined('ABSPATH') || exit;
+
final class SiteStatusAbility implements Ability
{
public function __construct(private EnvironmentProbe $probe, private Access $access)
diff --git a/src/Integrations/Divi/BlockTree/AttrMap.php b/src/Integrations/Divi/BlockTree/AttrMap.php
index 9887d43..31c91aa 100644
--- a/src/Integrations/Divi/BlockTree/AttrMap.php
+++ b/src/Integrations/Divi/BlockTree/AttrMap.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\Divi\BlockTree;
use InvalidArgumentException;
use stdClass;
+defined('ABSPATH') || exit;
+
/**
* Divi 5 attributes addressed by dotted paths ("title.decoration.font.font"). The value at
* a path is a breakpoint map: {"desktop": {"value": …, "hover": …}, "phone": {"value": …}}.
diff --git a/src/Integrations/Divi/BlockTree/Block.php b/src/Integrations/Divi/BlockTree/Block.php
index 15a8824..89a1872 100644
--- a/src/Integrations/Divi/BlockTree/Block.php
+++ b/src/Integrations/Divi/BlockTree/Block.php
@@ -8,6 +8,8 @@ use InvalidArgumentException;
use LogicException;
use stdClass;
+defined('ABSPATH') || exit;
+
/**
* One block of the tree. A parsed block keeps its original opener/closer bytes; they are
* dropped only when the block itself changes (setAttrs(), a void block getting children),
diff --git a/src/Integrations/Divi/BlockTree/Container.php b/src/Integrations/Divi/BlockTree/Container.php
index 610e58b..05447ed 100644
--- a/src/Integrations/Divi/BlockTree/Container.php
+++ b/src/Integrations/Divi/BlockTree/Container.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\Divi\BlockTree;
use InvalidArgumentException;
use LogicException;
+defined('ABSPATH') || exit;
+
/**
* Ordered parts of a document or of a block's inner content: blocks and the raw text
* between them (whitespace, freeform HTML, Divi 4 shortcodes). Keeping every byte of that
diff --git a/src/Integrations/Divi/BlockTree/Document.php b/src/Integrations/Divi/BlockTree/Document.php
index 49849ac..e80cf5d 100644
--- a/src/Integrations/Divi/BlockTree/Document.php
+++ b/src/Integrations/Divi/BlockTree/Document.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\BlockTree;
+defined('ABSPATH') || exit;
+
/**
* The parsed post_content: top-level blocks and the text between them.
*/
diff --git a/src/Integrations/Divi/BlockTree/Json.php b/src/Integrations/Divi/BlockTree/Json.php
index e479df9..52b6a2f 100644
--- a/src/Integrations/Divi/BlockTree/Json.php
+++ b/src/Integrations/Divi/BlockTree/Json.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\Divi\BlockTree;
use JsonException;
use stdClass;
+defined('ABSPATH') || exit;
+
/**
* JSON of block attributes. PHP arrays cannot tell an empty JSON object from an empty list,
* nor an object with the keys "0", "1", … from a list. decodeObject() therefore keeps such
diff --git a/src/Integrations/Divi/BlockTree/MalformedMarkup.php b/src/Integrations/Divi/BlockTree/MalformedMarkup.php
index f15cc1b..c700f33 100644
--- a/src/Integrations/Divi/BlockTree/MalformedMarkup.php
+++ b/src/Integrations/Divi/BlockTree/MalformedMarkup.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\BlockTree;
use RuntimeException;
+defined('ABSPATH') || exit;
+
/**
* post_content is no balanced block markup (closer without opener, unclosed block, PCRE
* failure). The Divi tools then refuse to read or write the entry – nothing is guessed.
diff --git a/src/Integrations/Divi/BlockTree/NodeIndex.php b/src/Integrations/Divi/BlockTree/NodeIndex.php
index 31cda0f..4e44448 100644
--- a/src/Integrations/Divi/BlockTree/NodeIndex.php
+++ b/src/Integrations/Divi/BlockTree/NodeIndex.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\BlockTree;
+defined('ABSPATH') || exit;
+
/**
* Path IDs of a Document (spec §5.3): s0, s0.r1, s0.r1.c0.m2. One letter per role –
* s section, r row / row-inner, c column / column-inner, m module (incl. group and child
diff --git a/src/Integrations/Divi/BlockTree/NodeSummary.php b/src/Integrations/Divi/BlockTree/NodeSummary.php
index 95da6d8..c5d57a8 100644
--- a/src/Integrations/Divi/BlockTree/NodeSummary.php
+++ b/src/Integrations/Divi/BlockTree/NodeSummary.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\BlockTree;
use LIT\MCP\Abilities\Text;
+defined('ABSPATH') || exit;
+
/**
* Short human-readable facts about a node for the outline: admin label, first text,
* preset IDs, column layout. Pure PHP.
diff --git a/src/Integrations/Divi/BlockTree/Outline.php b/src/Integrations/Divi/BlockTree/Outline.php
index eaab7c7..a364371 100644
--- a/src/Integrations/Divi/BlockTree/Outline.php
+++ b/src/Integrations/Divi/BlockTree/Outline.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\BlockTree;
+defined('ABSPATH') || exit;
+
/**
* The page tree as rows and as compact text (lit-divi-outline, spec §5.3/§5.7; also the
* "outline" of write results). Preset IDs are shown with their names when known.
diff --git a/src/Integrations/Divi/BlockTree/Parser.php b/src/Integrations/Divi/BlockTree/Parser.php
index afb4d25..a4ea56b 100644
--- a/src/Integrations/Divi/BlockTree/Parser.php
+++ b/src/Integrations/Divi/BlockTree/Parser.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\BlockTree;
+defined('ABSPATH') || exit;
+
/**
* Parses block markup into a Document without WordPress (spec §4.4, §5.2). Uses the
* block-delimiter pattern of WP_Block_Parser, but records the exact bytes of every
diff --git a/src/Integrations/Divi/BlockTree/Serializer.php b/src/Integrations/Divi/BlockTree/Serializer.php
index f1493da..387f7d1 100644
--- a/src/Integrations/Divi/BlockTree/Serializer.php
+++ b/src/Integrations/Divi/BlockTree/Serializer.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\BlockTree;
+defined('ABSPATH') || exit;
+
/**
* Turns a Document back into block markup. Unchanged blocks reuse their original
* delimiters; changed or new blocks get delimiters generated exactly like WordPress'
diff --git a/src/Integrations/Divi/Compose/AttrWriter.php b/src/Integrations/Divi/Compose/AttrWriter.php
index 5125a8d..1978adc 100644
--- a/src/Integrations/Divi/Compose/AttrWriter.php
+++ b/src/Integrations/Divi/Compose/AttrWriter.php
@@ -8,6 +8,8 @@ use InvalidArgumentException;
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
use LIT\MCP\Integrations\Divi\Schema\ModuleCatalog;
+defined('ABSPATH') || exit;
+
/**
* Applies full-form changes (spec §5.4): attribute path => breakpoint map. Paths are checked
* against the catalog (invalid_attr_path with suggestions), placeholders resolved, strings
diff --git a/src/Integrations/Divi/Compose/ColumnWidths.php b/src/Integrations/Divi/Compose/ColumnWidths.php
index 87af38a..2418e5d 100644
--- a/src/Integrations/Divi/Compose/ColumnWidths.php
+++ b/src/Integrations/Divi/Compose/ColumnWidths.php
@@ -8,6 +8,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
use LIT\MCP\Integrations\Divi\BlockTree\Block;
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
+defined('ABSPATH') || exit;
+
/**
* Column widths of Divi rows (pure, static): the "columns" input of new rows
* ("1_3,2_3" → flexTypes, ruling S34) and the flexType checks on update (rulings S41, S43,
diff --git a/src/Integrations/Divi/Compose/Composer.php b/src/Integrations/Divi/Compose/Composer.php
index 138bd41..b222250 100644
--- a/src/Integrations/Divi/Compose/Composer.php
+++ b/src/Integrations/Divi/Compose/Composer.php
@@ -11,6 +11,8 @@ use LIT\MCP\Integrations\Divi\Design\DesignSystem;
use LIT\MCP\Integrations\Divi\Schema\ModuleCatalog;
use LIT\MCP\Integrations\Divi\Schema\ShortformMap;
+defined('ABSPATH') || exit;
+
/**
* Builds new Divi blocks from node descriptions (spec §5.4): short form, full form ("attrs")
* or both; sections with rows ("columns": "1_3,2_3") and modules; parent modules with
diff --git a/src/Integrations/Divi/Compose/ControlChars.php b/src/Integrations/Divi/Compose/ControlChars.php
index e2d4fcb..1342fec 100644
--- a/src/Integrations/Divi/Compose/ControlChars.php
+++ b/src/Integrations/Divi/Compose/ControlChars.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Compose;
+defined('ABSPATH') || exit;
+
/**
* Removes C0 control characters except tab, LF and CR, and DEL (rulings S32/S32a). Applied to
* RAW values only, before the marker check and the sanitizer: the WordPress sanitizers keep them
diff --git a/src/Integrations/Divi/Compose/DynamicContentRules.php b/src/Integrations/Divi/Compose/DynamicContentRules.php
index d19149b..3c78568 100644
--- a/src/Integrations/Divi/Compose/DynamicContentRules.php
+++ b/src/Integrations/Divi/Compose/DynamicContentRules.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\Divi\Compose;
use InvalidArgumentException;
use LIT\MCP\Integrations\Divi\Design\DesignSystem;
+defined('ABSPATH') || exit;
+
/**
* The allow list of content references ($variable({"type":"content",…})$) that VariableRef
* delegates to: which names exist and how each of their settings is cleaned. Pure PHP.
diff --git a/src/Integrations/Divi/Compose/HtmlContext.php b/src/Integrations/Divi/Compose/HtmlContext.php
index ca581bc..c093d8e 100644
--- a/src/Integrations/Divi/Compose/HtmlContext.php
+++ b/src/Integrations/Divi/Compose/HtmlContext.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Compose;
+defined('ABSPATH') || exit;
+
/**
* An independent second scan of an HTML fragment (ruling S45): a small state machine after the
* HTML tokenizer rules, written separately from the regex tokenizer HtmlTokens so a mistake in
diff --git a/src/Integrations/Divi/Compose/HtmlTokens.php b/src/Integrations/Divi/Compose/HtmlTokens.php
index 83a8700..18ff730 100644
--- a/src/Integrations/Divi/Compose/HtmlTokens.php
+++ b/src/Integrations/Divi/Compose/HtmlTokens.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Compose;
+defined('ABSPATH') || exit;
+
/**
* Ruling S45 tokenizer of lit/divi-replace-text (spec §5.7, rulings S8/S45): splits a string into
* tags (quote-aware – a ">" inside a quoted attribute value does not end the tag), comments,
diff --git a/src/Integrations/Divi/Compose/MediaResolver.php b/src/Integrations/Divi/Compose/MediaResolver.php
index d8cb9a5..e856678 100644
--- a/src/Integrations/Divi/Compose/MediaResolver.php
+++ b/src/Integrations/Divi/Compose/MediaResolver.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Compose;
+defined('ABSPATH') || exit;
+
/**
* Looks up media library images for short-form fields like image_id (spec §6.3: Divi image
* modules reference images by attachment ID plus URL). WpMediaResolver is the WordPress side.
diff --git a/src/Integrations/Divi/Compose/Placeholders.php b/src/Integrations/Divi/Compose/Placeholders.php
index 05a6c6a..34dec92 100644
--- a/src/Integrations/Divi/Compose/Placeholders.php
+++ b/src/Integrations/Divi/Compose/Placeholders.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\Divi\Compose;
use InvalidArgumentException;
use LIT\MCP\Integrations\Divi\Design\DesignSystem;
+defined('ABSPATH') || exit;
+
/**
* Translates the placeholders of spec §5.4 into Divi's $variable(…)$ syntax:
* {{color:primary||gcid-…}}, {{var:|gvid-…}}, {{font:heading|body}},
diff --git a/src/Integrations/Divi/Compose/ShortformWriter.php b/src/Integrations/Divi/Compose/ShortformWriter.php
index f7cb4b8..98ca3f4 100644
--- a/src/Integrations/Divi/Compose/ShortformWriter.php
+++ b/src/Integrations/Divi/Compose/ShortformWriter.php
@@ -8,6 +8,8 @@ use InvalidArgumentException;
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
use LIT\MCP\Integrations\Divi\Schema\ShortformMap;
+defined('ABSPATH') || exit;
+
/**
* Writes short-form fields (spec §5.4, ShortformMap) into Divi attributes: checks the value per
* kind, resolves placeholders (not for code) and sets it at ".desktop.value[.]";
diff --git a/src/Integrations/Divi/Compose/StoredForms.php b/src/Integrations/Divi/Compose/StoredForms.php
index 90cf6dc..404e5c1 100644
--- a/src/Integrations/Divi/Compose/StoredForms.php
+++ b/src/Integrations/Divi/Compose/StoredForms.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\Compose;
use LIT\MCP\Integrations\Divi\BlockTree\Serializer;
+defined('ABSPATH') || exit;
+
/**
* The forms a search text can take in stored block markup – the database prefilter of
* lit/divi-replace-text and the check for global modules it does not edit. Only a prefilter:
diff --git a/src/Integrations/Divi/Compose/StructureRules.php b/src/Integrations/Divi/Compose/StructureRules.php
index c2645e8..a7da185 100644
--- a/src/Integrations/Divi/Compose/StructureRules.php
+++ b/src/Integrations/Divi/Compose/StructureRules.php
@@ -8,6 +8,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
use LIT\MCP\Integrations\Divi\BlockTree\Block;
use LIT\MCP\Integrations\Divi\Schema\ModuleCatalog;
+defined('ABSPATH') || exit;
+
/**
* Which node may sit where (spec §5.4 "Struktur"): page → sections; regular section → rows;
* fullwidth section → fullwidth modules (catalog category "fullwidth-module"); column/group →
diff --git a/src/Integrations/Divi/Compose/TextReplacer.php b/src/Integrations/Divi/Compose/TextReplacer.php
index 129299e..6d2e0fd 100644
--- a/src/Integrations/Divi/Compose/TextReplacer.php
+++ b/src/Integrations/Divi/Compose/TextReplacer.php
@@ -8,6 +8,8 @@ use InvalidArgumentException;
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
use LIT\MCP\Integrations\Divi\BlockTree\NodeSummary;
+defined('ABSPATH') || exit;
+
/**
* Replaces visible text in the attributes of one block (lit/divi-replace-text, spec §5.7, D10):
* only in content (…innerContent) – plain values and the text keys of object values (text,
diff --git a/src/Integrations/Divi/Compose/TreeEditor.php b/src/Integrations/Divi/Compose/TreeEditor.php
index a9b1ea9..4da8a96 100644
--- a/src/Integrations/Divi/Compose/TreeEditor.php
+++ b/src/Integrations/Divi/Compose/TreeEditor.php
@@ -9,6 +9,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\Container;
use LIT\MCP\Integrations\Divi\BlockTree\Document;
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
+defined('ABSPATH') || exit;
+
/**
* Structural changes on a parsed page (spec §5.7): where to insert (parent / before / after,
* optional index), move, remove, duplicate – always checked against StructureRules. Works on
diff --git a/src/Integrations/Divi/Compose/ValueCleaner.php b/src/Integrations/Divi/Compose/ValueCleaner.php
index 9e4b9fa..d81d70f 100644
--- a/src/Integrations/Divi/Compose/ValueCleaner.php
+++ b/src/Integrations/Divi/Compose/ValueCleaner.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\Divi\Compose;
use InvalidArgumentException;
use LIT\MCP\Integrations\Divi\Schema\ModuleCatalog;
+defined('ABSPATH') || exit;
+
/**
* The single choke point through which every client string reaches Divi post_content. Divi
* saves bypass kses (D7), so this pipeline is the guarantee. Pure PHP.
diff --git a/src/Integrations/Divi/Compose/ValueKind.php b/src/Integrations/Divi/Compose/ValueKind.php
index bdca4a6..dce21e4 100644
--- a/src/Integrations/Divi/Compose/ValueKind.php
+++ b/src/Integrations/Divi/Compose/ValueKind.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Compose;
+defined('ABSPATH') || exit;
+
// The installed PHPCompatibility sniffs predate enums (PHP 8.1) and read their methods as plain functions.
// phpcs:disable PHPCompatibility.Variables.ForbiddenThisUseContexts.OutsideObjectContext
// phpcs:disable PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations.SelfOutsideClassScopeFound
diff --git a/src/Integrations/Divi/Compose/ValueSanitizer.php b/src/Integrations/Divi/Compose/ValueSanitizer.php
index 1dfe715..42877e9 100644
--- a/src/Integrations/Divi/Compose/ValueSanitizer.php
+++ b/src/Integrations/Divi/Compose/ValueSanitizer.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Compose;
+defined('ABSPATH') || exit;
+
/**
* Cleans values before they go into Divi attributes (spec §5.6/§10: wp_kses_post for rich
* text, sanitize_text_field for simple fields, esc_url_raw for URLs). Divi saves bypass kses
diff --git a/src/Integrations/Divi/Compose/VariableRef.php b/src/Integrations/Divi/Compose/VariableRef.php
index ac24806..1fe416c 100644
--- a/src/Integrations/Divi/Compose/VariableRef.php
+++ b/src/Integrations/Divi/Compose/VariableRef.php
@@ -10,6 +10,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\Json;
use LIT\MCP\Integrations\Divi\Design\DesignSystem;
use stdClass;
+defined('ABSPATH') || exit;
+
/**
* Divi's $variable({…})$ references (global colors, global variables, theme fonts, dynamic
* content). Divi saves bypass kses (D7), Divi resolves references anywhere in a string with
diff --git a/src/Integrations/Divi/Compose/Warnings.php b/src/Integrations/Divi/Compose/Warnings.php
index e182a96..6953489 100644
--- a/src/Integrations/Divi/Compose/Warnings.php
+++ b/src/Integrations/Divi/Compose/Warnings.php
@@ -11,6 +11,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\NodeSummary;
use LIT\MCP\Integrations\Divi\Design\DesignSystem;
use LIT\MCP\Integrations\Divi\Schema\ShortformMap;
+defined('ABSPATH') || exit;
+
/**
* Quality warnings of a Divi write (spec §5.5) – only about the nodes this call created or
* changed (and their children): fixed colors/fonts where a global one fits, images without
diff --git a/src/Integrations/Divi/Design/DesignSystem.php b/src/Integrations/Divi/Design/DesignSystem.php
index 65cde67..1a4de80 100644
--- a/src/Integrations/Divi/Design/DesignSystem.php
+++ b/src/Integrations/Divi/Design/DesignSystem.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\Design;
use InvalidArgumentException;
+defined('ABSPATH') || exit;
+
/**
* The site's Divi design system as read live from Divi (spec §2 principle 2, §5.7): global
* colors, global variables, theme fonts and sizes, module and group presets. Pure PHP –
diff --git a/src/Integrations/Divi/Design/DesignSystemReader.php b/src/Integrations/Divi/Design/DesignSystemReader.php
index f23dfa1..8465643 100644
--- a/src/Integrations/Divi/Design/DesignSystemReader.php
+++ b/src/Integrations/Divi/Design/DesignSystemReader.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\Divi\Design;
use ET\Builder\Packages\GlobalData\GlobalData;
use ET\Builder\Packages\GlobalData\GlobalPreset;
+defined('ABSPATH') || exit;
+
/**
* Reads the design system from Divi's own APIs once per request (spec §2 principle 2 – no
* copy is ever stored). Not final so abilities can be unit-tested with a mock.
diff --git a/src/Integrations/Divi/Design/DiviDesignSystemAbility.php b/src/Integrations/Divi/Design/DiviDesignSystemAbility.php
index 069315d..a85f7fe 100644
--- a/src/Integrations/Divi/Design/DiviDesignSystemAbility.php
+++ b/src/Integrations/Divi/Design/DiviDesignSystemAbility.php
@@ -9,6 +9,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Abilities\Errors;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-design-system: global colors, variables, theme fonts/sizes and presets with the
* placeholder to use for each (spec §5.4, §5.7). Read live from Divi; writing follows in
diff --git a/src/Integrations/Divi/DiviIntegration.php b/src/Integrations/Divi/DiviIntegration.php
index 616a338..f825fd6 100644
--- a/src/Integrations/Divi/DiviIntegration.php
+++ b/src/Integrations/Divi/DiviIntegration.php
@@ -27,6 +27,8 @@ use LIT\MCP\Integrations\Integration;
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
+defined('ABSPATH') || exit;
+
/**
* Divi 5 pages (spec §5, Etappe 2). Only available when the Divi 5 builder is loaded
* (spec §2 principle 4); Divi 4 is never edited (spec §3.4). The write abilities share one
diff --git a/src/Integrations/Divi/Pages/DiviChange.php b/src/Integrations/Divi/Pages/DiviChange.php
index 2312dd0..6619e41 100644
--- a/src/Integrations/Divi/Pages/DiviChange.php
+++ b/src/Integrations/Divi/Pages/DiviChange.php
@@ -8,6 +8,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\Block;
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
use LIT\MCP\Integrations\Divi\BlockTree\NodeSummary;
+defined('ABSPATH') || exit;
+
/**
* What a Divi write did to the tree: summary, changed nodes (for ToolResult::changed – IDs of
* surviving nodes are resolved after the change), touched nodes (for the quality warnings)
diff --git a/src/Integrations/Divi/Pages/DiviComposition.php b/src/Integrations/Divi/Pages/DiviComposition.php
index 78f9bc2..df4ea27 100644
--- a/src/Integrations/Divi/Pages/DiviComposition.php
+++ b/src/Integrations/Divi/Pages/DiviComposition.php
@@ -18,6 +18,8 @@ use LIT\MCP\Integrations\Divi\Compose\Warnings;
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
+defined('ABSPATH') || exit;
+
/**
* Wires the pure Compose classes with the live catalog, design system, Divi's dynamic content
* registry and the WordPress sanitizer/media lookup – once per request and entry. Ruling S31:
diff --git a/src/Integrations/Divi/Pages/DiviContentComposer.php b/src/Integrations/Divi/Pages/DiviContentComposer.php
index bc21801..e00d946 100644
--- a/src/Integrations/Divi/Pages/DiviContentComposer.php
+++ b/src/Integrations/Divi/Pages/DiviContentComposer.php
@@ -17,6 +17,8 @@ use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Divi short form for lit/content-create (spec §6.2): the sections become a Divi 5 layout in
* exactly one divi/placeholder – inserted by TreeEditor like the first section of an empty page
diff --git a/src/Integrations/Divi/Pages/DiviDeleteAbility.php b/src/Integrations/Divi/Pages/DiviDeleteAbility.php
index 0d20133..1b2a9be 100644
--- a/src/Integrations/Divi/Pages/DiviDeleteAbility.php
+++ b/src/Integrations/Divi/Pages/DiviDeleteAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\Block;
use LIT\MCP\Integrations\Divi\BlockTree\NodeSummary;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-delete: removes nodes with everything inside (spec §5.7, destructive). Needs
* confirm: true after asking the user; without it the answer lists what would be removed –
diff --git a/src/Integrations/Divi/Pages/DiviDuplicateNodeAbility.php b/src/Integrations/Divi/Pages/DiviDuplicateNodeAbility.php
index c038502..c39d8f4 100644
--- a/src/Integrations/Divi/Pages/DiviDuplicateNodeAbility.php
+++ b/src/Integrations/Divi/Pages/DiviDuplicateNodeAbility.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-duplicate-node: copies a node with everything inside right behind the original
* (spec §5.7). The copy's admin label gets " (Kopie)"; read-only nodes (global modules,
diff --git a/src/Integrations/Divi/Pages/DiviErrors.php b/src/Integrations/Divi/Pages/DiviErrors.php
index 4fd626f..070b412 100644
--- a/src/Integrations/Divi/Pages/DiviErrors.php
+++ b/src/Integrations/Divi/Pages/DiviErrors.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Errors;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/** The client errors the Divi tools share. */
final class DiviErrors
{
diff --git a/src/Integrations/Divi/Pages/DiviFlags.php b/src/Integrations/Divi/Pages/DiviFlags.php
index 2845f80..b38da3e 100644
--- a/src/Integrations/Divi/Pages/DiviFlags.php
+++ b/src/Integrations/Divi/Pages/DiviFlags.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\Pages;
use RuntimeException;
+defined('ABSPATH') || exit;
+
/**
* Marks an entry as a Divi 5 builder layout, like the Visual Builder's own save does
* (Divi 5.2.1 SyncToServerController.php:382-387: _et_pb_use_divi_5 = "on", legacy
diff --git a/src/Integrations/Divi/Pages/DiviInsertAbility.php b/src/Integrations/Divi/Pages/DiviInsertAbility.php
index 4f46363..26b8787 100644
--- a/src/Integrations/Divi/Pages/DiviInsertAbility.php
+++ b/src/Integrations/Divi/Pages/DiviInsertAbility.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Abilities\Errors;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-insert: inserts nodes in short and/or full form – modules, rows or whole sections –
* at parent / before / after (spec §5.7). All or nothing (ruling S39): the whole input is
diff --git a/src/Integrations/Divi/Pages/DiviMoveAbility.php b/src/Integrations/Divi/Pages/DiviMoveAbility.php
index fa4d056..c60de18 100644
--- a/src/Integrations/Divi/Pages/DiviMoveAbility.php
+++ b/src/Integrations/Divi/Pages/DiviMoveAbility.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Abilities\Errors;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-move: moves a node (with everything inside) to parent / before / after – also into
* another row or section, as long as the structure rules allow it (spec §5.7). Read-only
diff --git a/src/Integrations/Divi/Pages/DiviNodeGetAbility.php b/src/Integrations/Divi/Pages/DiviNodeGetAbility.php
index ade905a..425bff7 100644
--- a/src/Integrations/Divi/Pages/DiviNodeGetAbility.php
+++ b/src/Integrations/Divi/Pages/DiviNodeGetAbility.php
@@ -16,6 +16,8 @@ use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
use LIT\MCP\Integrations\Divi\Schema\ShortformMap;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-node-get: all attributes of one node in the full form (spec §5.4, §5.7) –
* attribute path => breakpoint map – plus the current short-form values.
diff --git a/src/Integrations/Divi/Pages/DiviOutlineAbility.php b/src/Integrations/Divi/Pages/DiviOutlineAbility.php
index ec0187d..7151b50 100644
--- a/src/Integrations/Divi/Pages/DiviOutlineAbility.php
+++ b/src/Integrations/Divi/Pages/DiviOutlineAbility.php
@@ -13,6 +13,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\Outline;
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-outline: the page tree with path IDs, types, admin labels, text excerpts and
* preset names plus tree_rev (spec §5.3, §5.7). Every Divi write needs this tree_rev.
diff --git a/src/Integrations/Divi/Pages/DiviPage.php b/src/Integrations/Divi/Pages/DiviPage.php
index 5c1d6cd..6c4a10a 100644
--- a/src/Integrations/Divi/Pages/DiviPage.php
+++ b/src/Integrations/Divi/Pages/DiviPage.php
@@ -9,6 +9,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\Document;
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* An entry loaded for the Divi tools: the post, its parsed tree, the path index and the
* tree_rev (hash of post_content – the optimistic lock of the Divi tools, ruling P16; the
diff --git a/src/Integrations/Divi/Pages/DiviPageLoader.php b/src/Integrations/Divi/Pages/DiviPageLoader.php
index f6738e4..20c2fce 100644
--- a/src/Integrations/Divi/Pages/DiviPageLoader.php
+++ b/src/Integrations/Divi/Pages/DiviPageLoader.php
@@ -13,6 +13,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use LIT\MCP\Log;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Loads an entry for the Divi tools: rights and status via PostGuard (spec §4.5), then the
* block tree. Divi 4 shortcode content and unbalanced markup are refused with a hint –
diff --git a/src/Integrations/Divi/Pages/DiviReplaceTextAbility.php b/src/Integrations/Divi/Pages/DiviReplaceTextAbility.php
index 838cd2a..88bf14e 100644
--- a/src/Integrations/Divi/Pages/DiviReplaceTextAbility.php
+++ b/src/Integrations/Divi/Pages/DiviReplaceTextAbility.php
@@ -19,6 +19,8 @@ use LIT\MCP\Log;
use Throwable;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-replace-text: replaces visible text across the Divi pages of one content type
* (spec §5.7, D10). dry_run (default true) only lists the hits with their tree_rev; the real run
diff --git a/src/Integrations/Divi/Pages/DiviSaver.php b/src/Integrations/Divi/Pages/DiviSaver.php
index 3665809..940af63 100644
--- a/src/Integrations/Divi/Pages/DiviSaver.php
+++ b/src/Integrations/Divi/Pages/DiviSaver.php
@@ -15,6 +15,8 @@ use Throwable;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Save pipeline of spec §5.6, steps 3–5: restore point and wp_update_post() with wp_slash() (the
* status stays), Divi 5 flags (DiviFlags), Divi's static CSS cache. A failure after saving is
diff --git a/src/Integrations/Divi/Pages/DiviSchema.php b/src/Integrations/Divi/Pages/DiviSchema.php
index 42e0394..8d4913e 100644
--- a/src/Integrations/Divi/Pages/DiviSchema.php
+++ b/src/Integrations/Divi/Pages/DiviSchema.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Pages;
+defined('ABSPATH') || exit;
+
/** Input schema properties the Divi write tools share. */
final class DiviSchema
{
diff --git a/src/Integrations/Divi/Pages/DiviTextSearch.php b/src/Integrations/Divi/Pages/DiviTextSearch.php
index f225c2f..b74586b 100644
--- a/src/Integrations/Divi/Pages/DiviTextSearch.php
+++ b/src/Integrations/Divi/Pages/DiviTextSearch.php
@@ -13,6 +13,8 @@ use LIT\MCP\Integrations\Divi\Compose\ValueCleaner;
use LIT\MCP\Integrations\WordPress\PostGuard;
use LIT\MCP\Integrations\WordPress\PostStatuses;
+defined('ABSPATH') || exit;
+
/**
* The search part of lit/divi-replace-text (D10): the SQL prefilter for candidate pages and
* the hits of one page, computed without changing it. The replacement is cleaned per place by
diff --git a/src/Integrations/Divi/Pages/DiviUpdateAbility.php b/src/Integrations/Divi/Pages/DiviUpdateAbility.php
index 9b2b872..5d968b1 100644
--- a/src/Integrations/Divi/Pages/DiviUpdateAbility.php
+++ b/src/Integrations/Divi/Pages/DiviUpdateAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Integrations\Divi\BlockTree\Block;
use LIT\MCP\Integrations\Divi\Compose\ColumnWidths;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-update: sets or removes values of existing nodes – short-form fields ("set"), full
* form ("attrs", null removes a path or breakpoint), preset and admin label (spec §5.7). Several
diff --git a/src/Integrations/Divi/Pages/DiviWriteAbility.php b/src/Integrations/Divi/Pages/DiviWriteAbility.php
index f33584f..5a90b13 100644
--- a/src/Integrations/Divi/Pages/DiviWriteAbility.php
+++ b/src/Integrations/Divi/Pages/DiviWriteAbility.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Ability;
use LIT\MCP\Abilities\ToolResult;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* The frame of the Divi write tools (spec §5.6): permission and execute both load the page
* through DiviWriter::page() (rights, Divi layout, tree_rev lock – execute never trusts state
diff --git a/src/Integrations/Divi/Pages/DiviWriter.php b/src/Integrations/Divi/Pages/DiviWriter.php
index b642e29..8cb015e 100644
--- a/src/Integrations/Divi/Pages/DiviWriter.php
+++ b/src/Integrations/Divi/Pages/DiviWriter.php
@@ -16,6 +16,8 @@ use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
use LIT\MCP\Integrations\WordPress\PostSaveFollowUp;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* The shared frame of every Divi write (spec §5.6): load with rights and the tree_rev lock
* (ruling P16; a mismatch is rev_mismatch and nothing is written), let the ability change the
diff --git a/src/Integrations/Divi/Pages/DynamicContentMap.php b/src/Integrations/Divi/Pages/DynamicContentMap.php
index c824443..10f0c6a 100644
--- a/src/Integrations/Divi/Pages/DynamicContentMap.php
+++ b/src/Integrations/Divi/Pages/DynamicContentMap.php
@@ -10,6 +10,8 @@ use LIT\MCP\Integrations\Divi\Compose\DynamicContentRules;
use LIT\MCP\Log;
use Throwable;
+defined('ABSPATH') || exit;
+
/**
* DynamicContentRules' dynamic content allow map (ruling S22) from Divi's live registry
* DynamicContentOptions::get_options($postId, 'edit') – the options the Visual Builder offers
diff --git a/src/Integrations/Divi/Pages/WpMediaResolver.php b/src/Integrations/Divi/Pages/WpMediaResolver.php
index a628693..7b4f4f0 100644
--- a/src/Integrations/Divi/Pages/WpMediaResolver.php
+++ b/src/Integrations/Divi/Pages/WpMediaResolver.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\Pages;
use LIT\MCP\Integrations\Divi\Compose\MediaResolver;
+defined('ABSPATH') || exit;
+
/**
* Media library images for short-form fields (image_id, portrait_id, image_ids): only images
* the current user may read. URL and alt text are cleaned by ShortformWriter like client input.
diff --git a/src/Integrations/Divi/Pages/WpValueSanitizer.php b/src/Integrations/Divi/Pages/WpValueSanitizer.php
index 648626d..9e6cb0a 100644
--- a/src/Integrations/Divi/Pages/WpValueSanitizer.php
+++ b/src/Integrations/Divi/Pages/WpValueSanitizer.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\Pages;
use LIT\MCP\Integrations\Divi\Compose\ValueSanitizer;
+defined('ABSPATH') || exit;
+
/**
* WordPress sanitizing of Divi values (spec §5.6/§10). Because DiviSaver bypasses kses for the
* page as a whole (kses would re-serialize every untouched block, D7), every value this plugin
diff --git a/src/Integrations/Divi/Schema/AttrPathIndex.php b/src/Integrations/Divi/Schema/AttrPathIndex.php
index a88620b..a030f34 100644
--- a/src/Integrations/Divi/Schema/AttrPathIndex.php
+++ b/src/Integrations/Divi/Schema/AttrPathIndex.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\Schema;
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
+defined('ABSPATH') || exit;
+
/**
* Known attribute paths of one module, derived from Divi's module metadata (settings of
* every attribute group, attrName references) and its default attributes (spec §5.4:
diff --git a/src/Integrations/Divi/Schema/DiviCatalogAbility.php b/src/Integrations/Divi/Schema/DiviCatalogAbility.php
index 9c0da80..fe71199 100644
--- a/src/Integrations/Divi/Schema/DiviCatalogAbility.php
+++ b/src/Integrations/Divi/Schema/DiviCatalogAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Abilities\Errors;
use LIT\MCP\Abilities\JsonMap;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/divi-catalog: the modules of this Divi installation with their short-form fields;
* with "module" the details of one module incl. all known attribute paths (spec §5.7).
diff --git a/src/Integrations/Divi/Schema/DiviModules.php b/src/Integrations/Divi/Schema/DiviModules.php
index 2386df2..a35f352 100644
--- a/src/Integrations/Divi/Schema/DiviModules.php
+++ b/src/Integrations/Divi/Schema/DiviModules.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\Schema;
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
+defined('ABSPATH') || exit;
+
/**
* Reads Divi's module metadata once per request (Divi 5 only). Not final so abilities can be
* unit-tested with a mock.
diff --git a/src/Integrations/Divi/Schema/ModuleCatalog.php b/src/Integrations/Divi/Schema/ModuleCatalog.php
index f4620b6..d54eabf 100644
--- a/src/Integrations/Divi/Schema/ModuleCatalog.php
+++ b/src/Integrations/Divi/Schema/ModuleCatalog.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Divi\Schema;
+defined('ABSPATH') || exit;
+
/**
* The modules this Divi installation knows (spec §5.7 lit-divi-catalog), built from
* ModuleRegistration::get_all_core_modules_metadata() – always live, never a copy.
diff --git a/src/Integrations/Divi/Schema/ShortformMap.php b/src/Integrations/Divi/Schema/ShortformMap.php
index d6bbace..a872350 100644
--- a/src/Integrations/Divi/Schema/ShortformMap.php
+++ b/src/Integrations/Divi/Schema/ShortformMap.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Divi\Schema;
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
+defined('ABSPATH') || exit;
+
/**
* Curated short form (spec §5.4) for the ~20 everyday modules: field => where Divi 5 keeps
* the value. Paths come from Divi's conversion outlines (…/module-library/src/components/
diff --git a/src/Integrations/Integration.php b/src/Integrations/Integration.php
index 932aa74..279a102 100644
--- a/src/Integrations/Integration.php
+++ b/src/Integrations/Integration.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations;
use LIT\MCP\Abilities\Ability;
+defined('ABSPATH') || exit;
+
/**
* A group of abilities that is only registered when its theme/plugin is active.
*/
diff --git a/src/Integrations/IntegrationRegistry.php b/src/Integrations/IntegrationRegistry.php
index 9df6be2..28f30cd 100644
--- a/src/Integrations/IntegrationRegistry.php
+++ b/src/Integrations/IntegrationRegistry.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations;
use LIT\MCP\Abilities\Ability;
+defined('ABSPATH') || exit;
+
final class IntegrationRegistry
{
/** @var list */
diff --git a/src/Integrations/Media/AdminIncludes.php b/src/Integrations/Media/AdminIncludes.php
index 50ccdc6..970269b 100644
--- a/src/Integrations/Media/AdminIncludes.php
+++ b/src/Integrations/Media/AdminIncludes.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Media;
+defined('ABSPATH') || exit;
+
/**
* Media helpers (download_url, wp_tempnam, media_handle_sideload, …) live in
* wp-admin/includes and are not loaded on REST requests.
diff --git a/src/Integrations/Media/ContentMediaReferences.php b/src/Integrations/Media/ContentMediaReferences.php
index f6556d5..c578208 100644
--- a/src/Integrations/Media/ContentMediaReferences.php
+++ b/src/Integrations/Media/ContentMediaReferences.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Media;
+defined('ABSPATH') || exit;
+
/**
* The pure part of MediaUsageFinder: whether a piece of stored content (post content or a
* block widget) references an attachment – by ID (wp-image-, [gallery ids], Divi 4
diff --git a/src/Integrations/Media/MediaDeleteAbility.php b/src/Integrations/Media/MediaDeleteAbility.php
index 579b727..d13add9 100644
--- a/src/Integrations/Media/MediaDeleteAbility.php
+++ b/src/Integrations/Media/MediaDeleteAbility.php
@@ -13,6 +13,8 @@ use LIT\MCP\ChangeLog\ChangeLog;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/media-delete: deletes one attachment after confirmation. WordPress has no media trash by
* default (MEDIA_TRASH false): wp_delete_attachment($id, false) then deletes the attachment and
diff --git a/src/Integrations/Media/MediaDownloadAbility.php b/src/Integrations/Media/MediaDownloadAbility.php
index 7b5875d..7feda6c 100644
--- a/src/Integrations/Media/MediaDownloadAbility.php
+++ b/src/Integrations/Media/MediaDownloadAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Abilities\Errors;
use LIT\MCP\Limits;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Delivers a media file (original or a named image size) as an MCP embedded resource
* (spec §4.3). Direct tool: like ImageContent (lit-media-preview), an embedded resource
diff --git a/src/Integrations/Media/MediaFiles.php b/src/Integrations/Media/MediaFiles.php
index ca5bdc1..754769e 100644
--- a/src/Integrations/Media/MediaFiles.php
+++ b/src/Integrations/Media/MediaFiles.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\Media;
+defined('ABSPATH') || exit;
+
/**
* Shared file-path safety check for lit-media-preview and lit-media-download
* (controller ruling: never read a file outside the uploads directory, even
diff --git a/src/Integrations/Media/MediaGetAbility.php b/src/Integrations/Media/MediaGetAbility.php
index add0e5b..75d28c4 100644
--- a/src/Integrations/Media/MediaGetAbility.php
+++ b/src/Integrations/Media/MediaGetAbility.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Ability;
use LIT\MCP\Abilities\Annotations;
use WP_Error;
+defined('ABSPATH') || exit;
+
final class MediaGetAbility implements Ability
{
public function __construct(private MediaPresenter $presenter, private MediaUsageFinder $finder)
diff --git a/src/Integrations/Media/MediaGuard.php b/src/Integrations/Media/MediaGuard.php
index e8c2788..a872649 100644
--- a/src/Integrations/Media/MediaGuard.php
+++ b/src/Integrations/Media/MediaGuard.php
@@ -9,6 +9,8 @@ use LIT\MCP\Integrations\WordPress\PostGuard;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Loads an attachment for abilities and checks the capability on that attachment
* (spec §4.5). Every error is ready to be returned from permission()/execute().
diff --git a/src/Integrations/Media/MediaImporter.php b/src/Integrations/Media/MediaImporter.php
index bff2f34..1ca8078 100644
--- a/src/Integrations/Media/MediaImporter.php
+++ b/src/Integrations/Media/MediaImporter.php
@@ -13,6 +13,8 @@ use Throwable;
use WP_Error;
use WpOrg\Requests\Exception as RequestsException;
+defined('ABSPATH') || exit;
+
/**
* Imports files into the media library (spec §6.3, §10).
*
diff --git a/src/Integrations/Media/MediaIntegration.php b/src/Integrations/Media/MediaIntegration.php
index 404cc98..db08afb 100644
--- a/src/Integrations/Media/MediaIntegration.php
+++ b/src/Integrations/Media/MediaIntegration.php
@@ -9,6 +9,8 @@ use LIT\MCP\Integrations\Integration;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use LIT\MCP\Limits;
+defined('ABSPATH') || exit;
+
/**
* Media library tools (spec §6.3). Always available. $log and $limits serve the write
* tools (upload, update, delete).
diff --git a/src/Integrations/Media/MediaMetaWriter.php b/src/Integrations/Media/MediaMetaWriter.php
index 562cb0a..3ebb497 100644
--- a/src/Integrations/Media/MediaMetaWriter.php
+++ b/src/Integrations/Media/MediaMetaWriter.php
@@ -8,6 +8,8 @@ use LIT\MCP\Integrations\WordPress\PostRow;
use RuntimeException;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Writes the editable metadata of an attachment (alt text, title, caption, description) and
* restores it from a snapshot taken before (lit/media-update rolls a batch back with it).
diff --git a/src/Integrations/Media/MediaPresenter.php b/src/Integrations/Media/MediaPresenter.php
index 92c3319..ba0f5b3 100644
--- a/src/Integrations/Media/MediaPresenter.php
+++ b/src/Integrations/Media/MediaPresenter.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\Media;
use LIT\MCP\Abilities\JsonMap;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Output format of an attachment. Not final so abilities can be tested with a mock.
*/
diff --git a/src/Integrations/Media/MediaPreviewAbility.php b/src/Integrations/Media/MediaPreviewAbility.php
index b9489f3..cc4268f 100644
--- a/src/Integrations/Media/MediaPreviewAbility.php
+++ b/src/Integrations/Media/MediaPreviewAbility.php
@@ -9,6 +9,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Abilities\Errors;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Renders a downscaled preview of an image attachment as an MCP ImageContent block
* (spec §4.3). Direct tool only: the mcp-adapter only turns `{type: 'image', …}` into
diff --git a/src/Integrations/Media/MediaSearchAbility.php b/src/Integrations/Media/MediaSearchAbility.php
index f9b5c24..9b7f7d8 100644
--- a/src/Integrations/Media/MediaSearchAbility.php
+++ b/src/Integrations/Media/MediaSearchAbility.php
@@ -12,6 +12,8 @@ use LIT\MCP\Integrations\WordPress\PostGuard;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Media library search (spec §6.3). Direct tool. `unused` only ever checks a small,
* bounded number of candidates per call via MediaUsageFinder::isUsed() (each call does one
diff --git a/src/Integrations/Media/MediaUpdateAbility.php b/src/Integrations/Media/MediaUpdateAbility.php
index 4c69a69..1821824 100644
--- a/src/Integrations/Media/MediaUpdateAbility.php
+++ b/src/Integrations/Media/MediaUpdateAbility.php
@@ -17,6 +17,8 @@ use Throwable;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/media-update: metadata of up to 50 attachments in one call, all or nothing.
* Every item is validated first (attachment, edit_post, lengths, optional `modified` lock);
diff --git a/src/Integrations/Media/MediaUploadAbility.php b/src/Integrations/Media/MediaUploadAbility.php
index 517a549..86a7f7c 100644
--- a/src/Integrations/Media/MediaUploadAbility.php
+++ b/src/Integrations/Media/MediaUploadAbility.php
@@ -9,6 +9,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Limits;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Uploads a Base64-encoded file into the media library (spec §6.3), up to the configured
* upload limit (at most Limits::INLINE_MAX_MB, the request carries the whole file).
diff --git a/src/Integrations/Media/MediaUploadFromUrlAbility.php b/src/Integrations/Media/MediaUploadFromUrlAbility.php
index 9c0fc2a..8fea506 100644
--- a/src/Integrations/Media/MediaUploadFromUrlAbility.php
+++ b/src/Integrations/Media/MediaUploadFromUrlAbility.php
@@ -8,6 +8,8 @@ use LIT\MCP\Abilities\Ability;
use LIT\MCP\Abilities\Annotations;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Imports a publicly reachable file into the media library (spec §6.3). Direct tool.
* Download, checks and cleanup: MediaImporter; permission and result: MediaUploads.
diff --git a/src/Integrations/Media/MediaUploads.php b/src/Integrations/Media/MediaUploads.php
index e3f3080..ca547b0 100644
--- a/src/Integrations/Media/MediaUploads.php
+++ b/src/Integrations/Media/MediaUploads.php
@@ -14,6 +14,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* What both upload abilities share (lit/media-upload-from-url, lit/media-upload): the
* permission check, running the import and building the result for the new attachment.
diff --git a/src/Integrations/Media/MediaUsageFinder.php b/src/Integrations/Media/MediaUsageFinder.php
index 8f3cfaf..421dd54 100644
--- a/src/Integrations/Media/MediaUsageFinder.php
+++ b/src/Integrations/Media/MediaUsageFinder.php
@@ -8,6 +8,8 @@ use Closure;
use LIT\MCP\Integrations\WordPress\PostStatuses;
use LIT\MCP\Log;
+defined('ABSPATH') || exit;
+
/**
* Finds where an attachment is used (spec §6.3). Deliberately errs on the side of "used":
* a false positive only asks for force: true, a false negative would break a page.
diff --git a/src/Integrations/Media/PublicAddress.php b/src/Integrations/Media/PublicAddress.php
index 9f119aa..b4173fe 100644
--- a/src/Integrations/Media/PublicAddress.php
+++ b/src/Integrations/Media/PublicAddress.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\Media;
use Closure;
+defined('ABSPATH') || exit;
+
/**
* The plugin's own check that a URL import only reaches public addresses (security audit M3), in
* addition to wp_http_validate_url(): older WordPress versions (the plugin supports 6.9) block
diff --git a/src/Integrations/Pods/PodsFieldSource.php b/src/Integrations/Pods/PodsFieldSource.php
index 2004174..24a346d 100644
--- a/src/Integrations/Pods/PodsFieldSource.php
+++ b/src/Integrations/Pods/PodsFieldSource.php
@@ -9,6 +9,8 @@ use LIT\MCP\Integrations\WordPress\Schema\FieldSource;
use RuntimeException;
use Throwable;
+defined('ABSPATH') || exit;
+
/**
* Pods field adapter (spec §6.1/§6.2): definitions from pods_api()->load_pod(),
* values read and written through the Pods API so relationships and caches stay
diff --git a/src/Integrations/WordPress/Content/ContentComposer.php b/src/Integrations/WordPress/Content/ContentComposer.php
index 8a346ef..ca6c435 100644
--- a/src/Integrations/WordPress/Content/ContentComposer.php
+++ b/src/Integrations/WordPress/Content/ContentComposer.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\WordPress\Content;
use Throwable;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Builds the content of a new entry for lit/content-create from a structured description
* (spec §6.2: "optional Divi-Inhalt in Kurzform"). Implemented by the Divi integration, so the
diff --git a/src/Integrations/WordPress/Content/ContentCreateAbility.php b/src/Integrations/WordPress/Content/ContentCreateAbility.php
index 68824dd..a2119ef 100644
--- a/src/Integrations/WordPress/Content/ContentCreateAbility.php
+++ b/src/Integrations/WordPress/Content/ContentCreateAbility.php
@@ -17,6 +17,8 @@ use Throwable;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/content-create: new entry, always a draft. All or nothing (spec §8.2): input is
* validated before the insert; if fields, terms or the featured image cannot be written
diff --git a/src/Integrations/WordPress/Content/ContentGetAbility.php b/src/Integrations/WordPress/Content/ContentGetAbility.php
index 8dc204f..245a801 100644
--- a/src/Integrations/WordPress/Content/ContentGetAbility.php
+++ b/src/Integrations/WordPress/Content/ContentGetAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Integrations\WordPress\PostGuard;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
+defined('ABSPATH') || exit;
+
final class ContentGetAbility implements Ability
{
public function __construct(private ContentSchema $schema, private PostPresenter $presenter)
diff --git a/src/Integrations/WordPress/Content/ContentQueryAbility.php b/src/Integrations/WordPress/Content/ContentQueryAbility.php
index d9c6cd9..21cd50b 100644
--- a/src/Integrations/WordPress/Content/ContentQueryAbility.php
+++ b/src/Integrations/WordPress/Content/ContentQueryAbility.php
@@ -14,6 +14,8 @@ use LIT\MCP\Integrations\WordPress\Schema\FieldDefinition;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
final class ContentQueryAbility implements Ability
{
private const STATUSES = ['publish', 'draft', 'pending', 'private', 'future'];
diff --git a/src/Integrations/WordPress/Content/ContentTypesAbility.php b/src/Integrations/WordPress/Content/ContentTypesAbility.php
index ad6b268..bf46cc4 100644
--- a/src/Integrations/WordPress/Content/ContentTypesAbility.php
+++ b/src/Integrations/WordPress/Content/ContentTypesAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Abilities\Errors;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
+defined('ABSPATH') || exit;
+
final class ContentTypesAbility implements Ability
{
public function __construct(private ContentSchema $schema)
diff --git a/src/Integrations/WordPress/Content/ContentUpdateAbility.php b/src/Integrations/WordPress/Content/ContentUpdateAbility.php
index 7bd0bc7..ae29404 100644
--- a/src/Integrations/WordPress/Content/ContentUpdateAbility.php
+++ b/src/Integrations/WordPress/Content/ContentUpdateAbility.php
@@ -22,6 +22,8 @@ use Throwable;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/content-update: changes an entry without touching its status. rev (from
* lit/content-get) is required so parallel edits are never overwritten (spec §2
diff --git a/src/Integrations/WordPress/Content/NewDraft.php b/src/Integrations/WordPress/Content/NewDraft.php
index 24ae8b6..3cf641e 100644
--- a/src/Integrations/WordPress/Content/NewDraft.php
+++ b/src/Integrations/WordPress/Content/NewDraft.php
@@ -12,6 +12,8 @@ use RuntimeException;
use Throwable;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* The transaction of lit/content-create: inserting the draft and every way back out of it.
* The three exits side by side:
diff --git a/src/Integrations/WordPress/Content/PostPresenter.php b/src/Integrations/WordPress/Content/PostPresenter.php
index 643cd48..366f6e5 100644
--- a/src/Integrations/WordPress/Content/PostPresenter.php
+++ b/src/Integrations/WordPress/Content/PostPresenter.php
@@ -11,6 +11,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use LIT\MCP\Integrations\WordPress\Schema\FieldDefinition;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Output format of an entry for the content tools. Not final so abilities can be
* unit-tested with a mock.
diff --git a/src/Integrations/WordPress/Content/PostWriter.php b/src/Integrations/WordPress/Content/PostWriter.php
index 7b8850b..3edbc5e 100644
--- a/src/Integrations/WordPress/Content/PostWriter.php
+++ b/src/Integrations/WordPress/Content/PostWriter.php
@@ -14,6 +14,8 @@ use Throwable;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Shared validation and write logic of lit/content-create and lit/content-update.
* prepare() validates everything before the first write (all or nothing, spec §8.2);
diff --git a/src/Integrations/WordPress/Menus/MenuAssignLocationAbility.php b/src/Integrations/WordPress/Menus/MenuAssignLocationAbility.php
index 1629e51..eceeb1d 100644
--- a/src/Integrations/WordPress/Menus/MenuAssignLocationAbility.php
+++ b/src/Integrations/WordPress/Menus/MenuAssignLocationAbility.php
@@ -12,6 +12,8 @@ use LIT\MCP\Abilities\ToolResult;
use LIT\MCP\ChangeLog\ChangeLog;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/menu-assign-location: assigns a menu to a theme location (menu_id 0 removes
* the assignment – the menu then disappears from the site, so removing an existing
diff --git a/src/Integrations/WordPress/Menus/MenuCreateAbility.php b/src/Integrations/WordPress/Menus/MenuCreateAbility.php
index 873a9db..02b5501 100644
--- a/src/Integrations/WordPress/Menus/MenuCreateAbility.php
+++ b/src/Integrations/WordPress/Menus/MenuCreateAbility.php
@@ -13,6 +13,8 @@ use LIT\MCP\Abilities\ToolResult;
use LIT\MCP\ChangeLog\ChangeLog;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/menu-create: creates an empty menu and optionally assigns it to a theme
* location. Menu items are added afterwards via lit/menu-set-items (Task 14).
diff --git a/src/Integrations/WordPress/Menus/MenuGetAbility.php b/src/Integrations/WordPress/Menus/MenuGetAbility.php
index ef7df51..f4e3fde 100644
--- a/src/Integrations/WordPress/Menus/MenuGetAbility.php
+++ b/src/Integrations/WordPress/Menus/MenuGetAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Abilities\Errors;
use LIT\MCP\Abilities\Rev;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/menu-get: a menu as a tree (P4 ruling: same node shape lit/menu-set-items,
* Task 14, accepts as input, so the result can be edited and sent back as-is).
diff --git a/src/Integrations/WordPress/Menus/MenuListAbility.php b/src/Integrations/WordPress/Menus/MenuListAbility.php
index 4cb51eb..03d7383 100644
--- a/src/Integrations/WordPress/Menus/MenuListAbility.php
+++ b/src/Integrations/WordPress/Menus/MenuListAbility.php
@@ -9,6 +9,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Abilities\Errors;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/menu-list: overview of all menus and the theme's menu locations, and which
* menu (if any) currently sits at each location.
diff --git a/src/Integrations/WordPress/Menus/MenuLocations.php b/src/Integrations/WordPress/Menus/MenuLocations.php
index 25e2577..0f22971 100644
--- a/src/Integrations/WordPress/Menus/MenuLocations.php
+++ b/src/Integrations/WordPress/Menus/MenuLocations.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\WordPress\Menus;
+defined('ABSPATH') || exit;
+
/**
* Theme menu locations (theme mod nav_menu_locations).
*/
diff --git a/src/Integrations/WordPress/Menus/MenuOperations.php b/src/Integrations/WordPress/Menus/MenuOperations.php
index 7021301..a9f1093 100644
--- a/src/Integrations/WordPress/Menus/MenuOperations.php
+++ b/src/Integrations/WordPress/Menus/MenuOperations.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\WordPress\Menus;
use LIT\MCP\Abilities\Errors;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Applies add/move/remove operations to the current menu tree and returns the
* desired tree for MenuWriter – so single operations and the declarative mode
diff --git a/src/Integrations/WordPress/Menus/MenuSetItemsAbility.php b/src/Integrations/WordPress/Menus/MenuSetItemsAbility.php
index 4a97e91..3db95a2 100644
--- a/src/Integrations/WordPress/Menus/MenuSetItemsAbility.php
+++ b/src/Integrations/WordPress/Menus/MenuSetItemsAbility.php
@@ -14,6 +14,8 @@ use LIT\MCP\Abilities\WriteFailed;
use LIT\MCP\ChangeLog\ChangeLog;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/menu-set-items: sets a menu's items, declaratively (items = whole target tree) or
* as add/move/remove operations. Both run through one path: operations are applied to
diff --git a/src/Integrations/WordPress/Menus/MenuTree.php b/src/Integrations/WordPress/Menus/MenuTree.php
index 2741ae4..e9df7dd 100644
--- a/src/Integrations/WordPress/Menus/MenuTree.php
+++ b/src/Integrations/WordPress/Menus/MenuTree.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\WordPress\Menus;
+defined('ABSPATH') || exit;
+
/**
* Turns the flat wp_get_nav_menu_items() list into a nested tree. The node shape
* (node()) is deliberately the same shape lit/menu-set-items (Task 14) accepts as
diff --git a/src/Integrations/WordPress/Menus/MenuWriter.php b/src/Integrations/WordPress/Menus/MenuWriter.php
index 427825d..f31107a 100644
--- a/src/Integrations/WordPress/Menus/MenuWriter.php
+++ b/src/Integrations/WordPress/Menus/MenuWriter.php
@@ -10,6 +10,8 @@ use Throwable;
use WP_Post;
use WP_Term;
+defined('ABSPATH') || exit;
+
/**
* Validates a desired menu tree against the current items and writes it.
*
diff --git a/src/Integrations/WordPress/PostGuard.php b/src/Integrations/WordPress/PostGuard.php
index ace98c1..cf88bf4 100644
--- a/src/Integrations/WordPress/PostGuard.php
+++ b/src/Integrations/WordPress/PostGuard.php
@@ -10,6 +10,8 @@ use RuntimeException;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Loads entries and post types for abilities, including the capability checks
* of spec §4.5. Every error is ready to be returned from permission()/execute().
diff --git a/src/Integrations/WordPress/PostRow.php b/src/Integrations/WordPress/PostRow.php
index 32808c7..0adfa23 100644
--- a/src/Integrations/WordPress/PostRow.php
+++ b/src/Integrations/WordPress/PostRow.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\WordPress;
use RuntimeException;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* Internal writes of post-row columns through wp_update_post() (slashed, WP_Error mode):
* rollbacks, clone rows, media metadata. Refusals become RuntimeExceptions with an internal
diff --git a/src/Integrations/WordPress/PostSaveFollowUp.php b/src/Integrations/WordPress/PostSaveFollowUp.php
index da2807c..d22aa10 100644
--- a/src/Integrations/WordPress/PostSaveFollowUp.php
+++ b/src/Integrations/WordPress/PostSaveFollowUp.php
@@ -10,6 +10,8 @@ use LIT\MCP\Abilities\ToolResult;
use LIT\MCP\ChangeLog\ChangeLog;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* What every post tool does once its write is saved: fire lit_mcp_after_save, re-read the
* post, write the change log and build the ToolResult with the new rev. From here on a
diff --git a/src/Integrations/WordPress/PostStatuses.php b/src/Integrations/WordPress/PostStatuses.php
index 6d456ed..fd6e5e5 100644
--- a/src/Integrations/WordPress/PostStatuses.php
+++ b/src/Integrations/WordPress/PostStatuses.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\WordPress;
+defined('ABSPATH') || exit;
+
/** Post statuses shared by the plugin's own SQL queries. */
final class PostStatuses
{
diff --git a/src/Integrations/WordPress/Render/PageRenderSummaryAbility.php b/src/Integrations/WordPress/Render/PageRenderSummaryAbility.php
index f4f8ab6..67be670 100644
--- a/src/Integrations/WordPress/Render/PageRenderSummaryAbility.php
+++ b/src/Integrations/WordPress/Render/PageRenderSummaryAbility.php
@@ -10,6 +10,8 @@ use LIT\MCP\Integrations\WordPress\PostGuard;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/page-render-summary: what a visitor sees in the content area – headings, texts, links,
* images with alt text and obvious problems (spec §5.7, §8.1). Works for every managed entry,
diff --git a/src/Integrations/WordPress/Render/PageRenderer.php b/src/Integrations/WordPress/Render/PageRenderer.php
index 5e87d26..c169d47 100644
--- a/src/Integrations/WordPress/Render/PageRenderer.php
+++ b/src/Integrations/WordPress/Render/PageRenderer.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\WordPress\Render;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Renders the content area of an entry in-process, like the front end does for the_content
* (Divi 5 renders its blocks there – verified in DDEV). Header, footer and Theme Builder
diff --git a/src/Integrations/WordPress/Render/RenderSummary.php b/src/Integrations/WordPress/Render/RenderSummary.php
index f8278be..f76d61f 100644
--- a/src/Integrations/WordPress/Render/RenderSummary.php
+++ b/src/Integrations/WordPress/Render/RenderSummary.php
@@ -10,6 +10,8 @@ use DOMNode;
use DOMXPath;
use LIT\MCP\Abilities\Text;
+defined('ABSPATH') || exit;
+
/**
* Structured excerpt of rendered HTML (spec §5.7 lit/page-render-summary): headings, text
* blocks, links, images with alt text and the obvious problems. Every extracted string is
diff --git a/src/Integrations/WordPress/RevisionPoint.php b/src/Integrations/WordPress/RevisionPoint.php
index 90504a5..6f33f76 100644
--- a/src/Integrations/WordPress/RevisionPoint.php
+++ b/src/Integrations/WordPress/RevisionPoint.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\WordPress;
+defined('ABSPATH') || exit;
+
/**
* Restore point before a change (spec §2 principle 7): WordPress stores the
* current state as a revision (only if it differs from the newest one) and the
diff --git a/src/Integrations/WordPress/Revisions/RevisionRestoreAbility.php b/src/Integrations/WordPress/Revisions/RevisionRestoreAbility.php
index 6545f3c..461d04f 100644
--- a/src/Integrations/WordPress/Revisions/RevisionRestoreAbility.php
+++ b/src/Integrations/WordPress/Revisions/RevisionRestoreAbility.php
@@ -17,6 +17,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/revision-restore: restores title, content and excerpt of an entry from one of
* its own revisions; the status is not touched. Because this overwrites the current
diff --git a/src/Integrations/WordPress/Revisions/RevisionsListAbility.php b/src/Integrations/WordPress/Revisions/RevisionsListAbility.php
index c1e705a..104b9c8 100644
--- a/src/Integrations/WordPress/Revisions/RevisionsListAbility.php
+++ b/src/Integrations/WordPress/Revisions/RevisionsListAbility.php
@@ -13,6 +13,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/revisions-list: revisions of an entry, newest first. Autosaves are included
* (marked autosave: true) rather than filtered out, so the client can decide. Each
diff --git a/src/Integrations/WordPress/Schema/ContentSchema.php b/src/Integrations/WordPress/Schema/ContentSchema.php
index d4331df..7a4621f 100644
--- a/src/Integrations/WordPress/Schema/ContentSchema.php
+++ b/src/Integrations/WordPress/Schema/ContentSchema.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\WordPress\Schema;
use LogicException;
+defined('ABSPATH') || exit;
+
/**
* Detects the content model of this installation (spec §6.1): post types with a
* UI, their taxonomies and their fields merged from all field sources.
diff --git a/src/Integrations/WordPress/Schema/FieldDefinition.php b/src/Integrations/WordPress/Schema/FieldDefinition.php
index 91aab4b..6dc1134 100644
--- a/src/Integrations/WordPress/Schema/FieldDefinition.php
+++ b/src/Integrations/WordPress/Schema/FieldDefinition.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\WordPress\Schema;
+defined('ABSPATH') || exit;
+
/**
* Description of one field of a post type, independent of where it comes from.
*/
diff --git a/src/Integrations/WordPress/Schema/FieldSource.php b/src/Integrations/WordPress/Schema/FieldSource.php
index 4dd4531..2fd8b95 100644
--- a/src/Integrations/WordPress/Schema/FieldSource.php
+++ b/src/Integrations/WordPress/Schema/FieldSource.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\WordPress\Schema;
use RuntimeException;
+defined('ABSPATH') || exit;
+
/**
* A provider of field definitions for post types that can also read and write
* the values of its own fields (Pods via the Pods API, everything else via meta).
diff --git a/src/Integrations/WordPress/Schema/FieldValidator.php b/src/Integrations/WordPress/Schema/FieldValidator.php
index 7bdea47..2030bc3 100644
--- a/src/Integrations/WordPress/Schema/FieldValidator.php
+++ b/src/Integrations/WordPress/Schema/FieldValidator.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\WordPress\Schema;
use DateTimeImmutable;
+defined('ABSPATH') || exit;
+
/**
* Checks field values against the detected schema before anything is written.
*/
diff --git a/src/Integrations/WordPress/Schema/MetaFieldSource.php b/src/Integrations/WordPress/Schema/MetaFieldSource.php
index 460f67d..4d40264 100644
--- a/src/Integrations/WordPress/Schema/MetaFieldSource.php
+++ b/src/Integrations/WordPress/Schema/MetaFieldSource.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\WordPress\Schema;
use RuntimeException;
+defined('ABSPATH') || exit;
+
/**
* Shared read/write via the post meta API. write() throws when WordPress did not
* store a value, so callers can roll back (all or nothing, spec §8.2).
diff --git a/src/Integrations/WordPress/Schema/RegisteredMetaSource.php b/src/Integrations/WordPress/Schema/RegisteredMetaSource.php
index 22d3a33..c3ea9b1 100644
--- a/src/Integrations/WordPress/Schema/RegisteredMetaSource.php
+++ b/src/Integrations/WordPress/Schema/RegisteredMetaSource.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\WordPress\Schema;
+defined('ABSPATH') || exit;
+
/**
* Fields registered with register_meta()/register_post_meta().
*/
diff --git a/src/Integrations/WordPress/Schema/SampledMetaSource.php b/src/Integrations/WordPress/Schema/SampledMetaSource.php
index 7f6fb4c..2ed8d3a 100644
--- a/src/Integrations/WordPress/Schema/SampledMetaSource.php
+++ b/src/Integrations/WordPress/Schema/SampledMetaSource.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Integrations\WordPress\Schema;
+defined('ABSPATH') || exit;
+
/**
* Meta keys actually used by the most recent posts of a type. Keys starting with
* "_" are internal and only shown when another source knows them.
diff --git a/src/Integrations/WordPress/Schema/TermAssigner.php b/src/Integrations/WordPress/Schema/TermAssigner.php
index b788c49..b3ff165 100644
--- a/src/Integrations/WordPress/Schema/TermAssigner.php
+++ b/src/Integrations/WordPress/Schema/TermAssigner.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\WordPress\Schema;
use RuntimeException;
use WP_Term;
+defined('ABSPATH') || exit;
+
/**
* Resolves term input ({taxonomy: [id | name, …]}) and replaces a post's terms.
* resolve() never writes, so a whole call can be validated first (all or nothing).
diff --git a/src/Integrations/WordPress/Settings/SettingsWhitelist.php b/src/Integrations/WordPress/Settings/SettingsWhitelist.php
index b806108..0d56a6b 100644
--- a/src/Integrations/WordPress/Settings/SettingsWhitelist.php
+++ b/src/Integrations/WordPress/Settings/SettingsWhitelist.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Integrations\WordPress\Settings;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* The WordPress options LIT MCP may read and write (spec §6.5), with validation.
*
diff --git a/src/Integrations/WordPress/Settings/WpSettingsGetAbility.php b/src/Integrations/WordPress/Settings/WpSettingsGetAbility.php
index 76b8e19..58a33be 100644
--- a/src/Integrations/WordPress/Settings/WpSettingsGetAbility.php
+++ b/src/Integrations/WordPress/Settings/WpSettingsGetAbility.php
@@ -9,6 +9,8 @@ use LIT\MCP\Abilities\Annotations;
use LIT\MCP\Abilities\Errors;
use WP_Error;
+defined('ABSPATH') || exit;
+
final class WpSettingsGetAbility implements Ability
{
public function __construct(private SettingsWhitelist $whitelist)
diff --git a/src/Integrations/WordPress/Settings/WpSettingsUpdateAbility.php b/src/Integrations/WordPress/Settings/WpSettingsUpdateAbility.php
index 4e8941a..7a2b01c 100644
--- a/src/Integrations/WordPress/Settings/WpSettingsUpdateAbility.php
+++ b/src/Integrations/WordPress/Settings/WpSettingsUpdateAbility.php
@@ -16,6 +16,8 @@ use RuntimeException;
use Throwable;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/wp-settings-update: writes whitelisted WordPress options, all or nothing.
*
diff --git a/src/Integrations/WordPress/Status/PostCloner.php b/src/Integrations/WordPress/Status/PostCloner.php
index c10fc08..9fc796c 100644
--- a/src/Integrations/WordPress/Status/PostCloner.php
+++ b/src/Integrations/WordPress/Status/PostCloner.php
@@ -13,6 +13,8 @@ use Throwable;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Copies entries (draft copy, trashed backup) and swaps a copy's content back into its
* original. Meta is copied byte-exact: the stored meta_value strings are read and
diff --git a/src/Integrations/WordPress/Status/PostDuplicateAbility.php b/src/Integrations/WordPress/Status/PostDuplicateAbility.php
index 15cbc2a..7ad5ea6 100644
--- a/src/Integrations/WordPress/Status/PostDuplicateAbility.php
+++ b/src/Integrations/WordPress/Status/PostDuplicateAbility.php
@@ -14,6 +14,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/post-duplicate: creates a draft copy of an entry (spec §6.2). The original –
* ID, URL, menu items, content – is not touched. A failure after the insert deletes
diff --git a/src/Integrations/WordPress/Status/PostPublishAbility.php b/src/Integrations/WordPress/Status/PostPublishAbility.php
index 398d100..bb2b9e0 100644
--- a/src/Integrations/WordPress/Status/PostPublishAbility.php
+++ b/src/Integrations/WordPress/Status/PostPublishAbility.php
@@ -16,6 +16,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/post-publish: publishes an entry immediately. A scheduled ("future") or
* future-dated entry is republished now instead of staying in the future (spec §6.2);
diff --git a/src/Integrations/WordPress/Status/PostReplaceWithCopyAbility.php b/src/Integrations/WordPress/Status/PostReplaceWithCopyAbility.php
index 8917ebb..a72995e 100644
--- a/src/Integrations/WordPress/Status/PostReplaceWithCopyAbility.php
+++ b/src/Integrations/WordPress/Status/PostReplaceWithCopyAbility.php
@@ -20,6 +20,8 @@ use Throwable;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/post-replace-with-copy: swaps a copy made by lit/post-duplicate into its original
* (spec §6.2). ID, URL, status and menu items of the original stay. rev of the original
diff --git a/src/Integrations/WordPress/Status/PostScheduleAbility.php b/src/Integrations/WordPress/Status/PostScheduleAbility.php
index 9e0d5b3..d915fd7 100644
--- a/src/Integrations/WordPress/Status/PostScheduleAbility.php
+++ b/src/Integrations/WordPress/Status/PostScheduleAbility.php
@@ -17,6 +17,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/post-schedule: schedules an entry for publication at a future point in time
* (site local time). An entry that is currently published stays live until then only
diff --git a/src/Integrations/WordPress/Status/PostTrashAbility.php b/src/Integrations/WordPress/Status/PostTrashAbility.php
index b7bace8..5d950f3 100644
--- a/src/Integrations/WordPress/Status/PostTrashAbility.php
+++ b/src/Integrations/WordPress/Status/PostTrashAbility.php
@@ -16,6 +16,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* lit/post-trash: moves an entry to the trash – never a permanent delete. Trashing the
* static front page, the posts page or an entry linked in a menu is allowed but named in
diff --git a/src/Integrations/WordPress/Status/PostUnpublishAbility.php b/src/Integrations/WordPress/Status/PostUnpublishAbility.php
index a7a795a..bef8f27 100644
--- a/src/Integrations/WordPress/Status/PostUnpublishAbility.php
+++ b/src/Integrations/WordPress/Status/PostUnpublishAbility.php
@@ -15,6 +15,8 @@ use LIT\MCP\Integrations\WordPress\PostGuard;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
+defined('ABSPATH') || exit;
+
/**
* lit/post-unpublish: withdraws a published, scheduled or private entry back to draft.
* An entry that is already not public (draft, pending, auto-draft) is a no-op.
diff --git a/src/Integrations/WordPress/Status/ReplaceFailed.php b/src/Integrations/WordPress/Status/ReplaceFailed.php
index 0a3a056..520b1b6 100644
--- a/src/Integrations/WordPress/Status/ReplaceFailed.php
+++ b/src/Integrations/WordPress/Status/ReplaceFailed.php
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\WordPress\Status;
use RuntimeException;
use Throwable;
+defined('ABSPATH') || exit;
+
/**
* Thrown by PostCloner::replace(). $parts lists the parts of the original replace()
* had started to write (post, meta, terms) – only those need to be restored.
diff --git a/src/Integrations/WordPress/Status/StatusWrite.php b/src/Integrations/WordPress/Status/StatusWrite.php
index 94f47a0..3e03bf4 100644
--- a/src/Integrations/WordPress/Status/StatusWrite.php
+++ b/src/Integrations/WordPress/Status/StatusWrite.php
@@ -9,6 +9,8 @@ use LIT\MCP\ChangeLog\ChangeLog;
use Throwable;
use WP_Post;
+defined('ABSPATH') || exit;
+
/**
* Runs the one WordPress call of a status tool (wp_update_post(), wp_trash_post()). If a
* hook throws inside it, the row may already be written – the entry's state is unknown,
diff --git a/src/Integrations/WordPress/WordPressIntegration.php b/src/Integrations/WordPress/WordPressIntegration.php
index 6fe11e0..c3268b6 100644
--- a/src/Integrations/WordPress/WordPressIntegration.php
+++ b/src/Integrations/WordPress/WordPressIntegration.php
@@ -39,6 +39,8 @@ use LIT\MCP\Integrations\WordPress\Status\PostScheduleAbility;
use LIT\MCP\Integrations\WordPress\Status\PostTrashAbility;
use LIT\MCP\Integrations\WordPress\Status\PostUnpublishAbility;
+defined('ABSPATH') || exit;
+
/**
* WordPress basics (spec §6): content, status, copies, revisions, menus, settings, and the
* rendered-content summary lit/page-render-summary (spec §5.7 – useful for every entry).
diff --git a/src/Lifecycle.php b/src/Lifecycle.php
index 7b296c5..f7cb907 100644
--- a/src/Lifecycle.php
+++ b/src/Lifecycle.php
@@ -10,6 +10,8 @@ use LIT\MCP\ChangeLog\ChangeLogCleanup;
use LIT\MCP\ChangeLog\ChangeLogInstaller;
use WPMedia\MCP\OAuth\Bootstrap as OAuthBootstrap;
+defined('ABSPATH') || exit;
+
/**
* Activation and deactivation hooks (registered in wp-lit-mcp.php). Uninstall
* lives in uninstall.php.
diff --git a/src/Limits.php b/src/Limits.php
index 99e2a32..65fcb6f 100644
--- a/src/Limits.php
+++ b/src/Limits.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP;
+defined('ABSPATH') || exit;
+
/**
* Admin-configurable limits (settings tab "Limits", spec §8.4).
*/
diff --git a/src/Log.php b/src/Log.php
index 9a79ed3..8f0dee5 100644
--- a/src/Log.php
+++ b/src/Log.php
@@ -6,6 +6,8 @@ namespace LIT\MCP;
use Throwable;
+defined('ABSPATH') || exit;
+
/**
* The plugin's one way into the PHP error log. Messages carry the "[wp-lit-mcp]" prefix; the
* log is for the site operator only and may contain details (paths, traces) that must never
diff --git a/src/Plugin.php b/src/Plugin.php
index e183a7c..daef929 100644
--- a/src/Plugin.php
+++ b/src/Plugin.php
@@ -36,6 +36,8 @@ use LIT\MCP\Server\RequestContext;
use LIT\MCP\Server\ServerRegistrar;
use LIT\MCP\Server\VisibilityFilter;
+defined('ABSPATH') || exit;
+
/**
* Wires WP-LIT-MCP into WordPress.
*/
diff --git a/src/Server/AuthorizeGate.php b/src/Server/AuthorizeGate.php
index fd6208e..c348cf6 100644
--- a/src/Server/AuthorizeGate.php
+++ b/src/Server/AuthorizeGate.php
@@ -6,6 +6,8 @@ namespace LIT\MCP\Server;
use LIT\MCP\Access;
+defined('ABSPATH') || exit;
+
/**
* Stops mcp-oauth's browser flow for logged-in users without lit_mcp_use (security audit L1).
* mcp-oauth only checks is_user_logged_in() and offers no filter, so this runs on
diff --git a/src/Server/DiscoveryCanonical.php b/src/Server/DiscoveryCanonical.php
index 13c9f0e..fa265bd 100644
--- a/src/Server/DiscoveryCanonical.php
+++ b/src/Server/DiscoveryCanonical.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP\Server;
+defined('ABSPATH') || exit;
+
/**
* Keeps WordPress' canonical redirect away from mcp-oauth's two discovery documents.
* With a pretty permalink structure ending in "/", WordPress 301-redirects
diff --git a/src/Server/RequestContext.php b/src/Server/RequestContext.php
index fc143ec..ef1b68f 100644
--- a/src/Server/RequestContext.php
+++ b/src/Server/RequestContext.php
@@ -9,6 +9,8 @@ use WP_REST_Request;
use WPMedia\MCP\OAuth\Auth\JWT;
use WPMedia\MCP\OAuth\Auth\SecretManager;
+defined('ABSPATH') || exit;
+
/**
* Tracks whether the current REST dispatch is serving our OAuth-protected MCP
* server route (`/mcp/mcp-oauth-server`) and which OAuth client made it.
diff --git a/src/Server/ServerRegistrar.php b/src/Server/ServerRegistrar.php
index 5df84a2..bff0a99 100644
--- a/src/Server/ServerRegistrar.php
+++ b/src/Server/ServerRegistrar.php
@@ -15,6 +15,8 @@ use WPMedia\MCP\OAuth\Context as OAuthContext;
use WPMedia\MCP\OAuth\Transport\OAuthHttpTransport;
use WPMedia\MCP\OAuth\Transport\ServerRegistrar as OAuthServerRegistrar;
+defined('ABSPATH') || exit;
+
/**
* Registers the OAuth-protected MCP server with our own tool list.
*
diff --git a/src/Server/VisibilityFilter.php b/src/Server/VisibilityFilter.php
index 6281c88..b860769 100644
--- a/src/Server/VisibilityFilter.php
+++ b/src/Server/VisibilityFilter.php
@@ -8,6 +8,8 @@ use LIT\MCP\Access;
use WP\MCP\Core\McpServer;
use WP\McpSchema\Common\Protocol\DTO\InitializeResult;
+defined('ABSPATH') || exit;
+
/**
* Users who may connect (mcp-oauth) but are not allowed to use LIT MCP get neither
* the tool list nor the site-specific instructions of our server. Execution is
diff --git a/src/Uninstaller.php b/src/Uninstaller.php
index 60b98d9..3cf62a6 100644
--- a/src/Uninstaller.php
+++ b/src/Uninstaller.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace LIT\MCP;
+defined('ABSPATH') || exit;
+
/**
* Removes WP-LIT-MCP's own data (uninstall.php, Task 12): options, the endpoint-check
* transient, the log-cleanup cron hook and the change log table – on every site of a
diff --git a/tests/Integration/divi-convert-fixture.php b/tests/Integration/divi-convert-fixture.php
index 02d8565..848e0f5 100644
--- a/tests/Integration/divi-convert-fixture.php
+++ b/tests/Integration/divi-convert-fixture.php
@@ -7,6 +7,8 @@
* Paths are relative to the plugin's tests/Fixtures/divi directory.
*/
+defined('WP_CLI') && WP_CLI || exit;
+
use ET\Builder\Packages\Conversion\Conversion;
$args = $args ?? [];
diff --git a/tests/Unit/DirectAccessGuardTest.php b/tests/Unit/DirectAccessGuardTest.php
new file mode 100644
index 0000000..2151a13
--- /dev/null
+++ b/tests/Unit/DirectAccessGuardTest.php
@@ -0,0 +1,48 @@
+