From cd82959a0e3911fc97028ba7c579d654634a8fd4 Mon Sep 17 00:00:00 2001 From: Snider Date: Wed, 4 Mar 2026 13:05:16 +0000 Subject: [PATCH] feat: absorb Front\Mcp frontage from php-framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the MCP frontage ServiceProvider (Core\Front\Mcp\Boot), McpContext DTO, McpToolHandler interface, and MCP portal blade layout from php-framework into this package. Namespaces unchanged — added PSR-4 mapping for Core\Front\Mcp\ and auto-discovery provider. Co-Authored-By: Virgil --- composer.json | 7 +- src/Front/Mcp/Boot.php | 50 ++++++++ src/Front/Mcp/Contracts/McpToolHandler.php | 48 ++++++++ src/Front/Mcp/McpContext.php | 133 +++++++++++++++++++++ src/Front/View/Blade/layouts/mcp.blade.php | 87 ++++++++++++++ 5 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 src/Front/Mcp/Boot.php create mode 100644 src/Front/Mcp/Contracts/McpToolHandler.php create mode 100644 src/Front/Mcp/McpContext.php create mode 100644 src/Front/View/Blade/layouts/mcp.blade.php diff --git a/composer.json b/composer.json index 0d14dee..1af1572 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "autoload": { "psr-4": { "Core\\Mcp\\": "src/Mcp/", - "Core\\Website\\Mcp\\": "src/Website/Mcp/" + "Core\\Website\\Mcp\\": "src/Website/Mcp/", + "Core\\Front\\Mcp\\": "src/Front/Mcp/" } }, "autoload-dev": { @@ -26,7 +27,9 @@ }, "extra": { "laravel": { - "providers": [] + "providers": [ + "Core\\Front\\Mcp\\Boot" + ] } }, "minimum-stability": "stable", diff --git a/src/Front/Mcp/Boot.php b/src/Front/Mcp/Boot.php new file mode 100644 index 0000000..c0726b4 --- /dev/null +++ b/src/Front/Mcp/Boot.php @@ -0,0 +1,50 @@ +group('mcp', [ + \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ]); + } + + public function register(): void + { + // + } + + public function boot(): void + { + // Fire McpRoutesRegistering event for lazy-loaded modules + LifecycleEventProvider::fireMcpRoutes(); + + // Fire McpToolsRegistering so modules can register tool handlers + LifecycleEventProvider::fireMcpTools(); + } +} diff --git a/src/Front/Mcp/Contracts/McpToolHandler.php b/src/Front/Mcp/Contracts/McpToolHandler.php new file mode 100644 index 0000000..e223f4b --- /dev/null +++ b/src/Front/Mcp/Contracts/McpToolHandler.php @@ -0,0 +1,48 @@ +sessionId; + } + + /** + * Set the current session ID. + */ + public function setSessionId(?string $sessionId): void + { + $this->sessionId = $sessionId; + } + + /** + * Get the current plan if one is active. + * + * @return object|null AgentPlan model instance when Agentic module installed + */ + public function getCurrentPlan(): ?object + { + return $this->currentPlan; + } + + /** + * Set the current plan. + * + * @param object|null $plan AgentPlan model instance + */ + public function setCurrentPlan(?object $plan): void + { + $this->currentPlan = $plan; + } + + /** + * Send an MCP notification to the client. + * + * Notifications are one-way messages that don't expect a response. + * Common notifications include progress updates, log messages, etc. + */ + public function sendNotification(string $method, array $params = []): void + { + if ($this->notificationCallback) { + ($this->notificationCallback)($method, $params); + } + } + + /** + * Log a message to the current session. + * + * Messages are recorded in the session log for handoff context + * and audit trail purposes. + */ + public function logToSession(string $message, string $type = 'info', array $data = []): void + { + if ($this->logCallback) { + ($this->logCallback)($message, $type, $data); + } + } + + /** + * Set the notification callback. + */ + public function setNotificationCallback(?Closure $callback): void + { + $this->notificationCallback = $callback; + } + + /** + * Set the log callback. + */ + public function setLogCallback(?Closure $callback): void + { + $this->logCallback = $callback; + } + + /** + * Check if a session is currently active. + */ + public function hasSession(): bool + { + return $this->sessionId !== null; + } + + /** + * Check if a plan is currently active. + */ + public function hasPlan(): bool + { + return $this->currentPlan !== null; + } +} diff --git a/src/Front/View/Blade/layouts/mcp.blade.php b/src/Front/View/Blade/layouts/mcp.blade.php new file mode 100644 index 0000000..04f0e9a --- /dev/null +++ b/src/Front/View/Blade/layouts/mcp.blade.php @@ -0,0 +1,87 @@ +@php + $appName = config('core.app.name', 'Core PHP'); + $appUrl = config('app.url', 'https://core.test'); + $privacyUrl = config('core.urls.privacy', '/privacy'); + $termsUrl = config('core.urls.terms', '/terms'); +@endphp + + + + + + + + {{ $title ?? 'MCP Portal' }} - {{ $appName }} + + + @vite(['resources/css/app.css', 'resources/js/app.js']) + @fluxAppearance + + + +
+
+
+ +
+ @php + $workspace = request()->attributes->get('mcp_workspace'); + @endphp + @if($workspace) + + Dashboard + + + API Keys + + + {{ $workspace->name }} + + @else + + Sign in + + @endif + + ← {{ $appName }} + +
+
+
+
+ + +
+ {{ $slot }} +
+ + + + + @fluxScripts + +