From 4e6be108859b07729e052ec2f4b925c8d2861792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vi=CC=81ctor=20Falco=CC=81n?= Date: Fri, 17 Jul 2026 15:42:18 +0200 Subject: [PATCH] fix(mcp): satisfy larastan (level 5) - Correct schema() @return to array (the JsonSchema builder returns Type objects, not the JsonSchema contract; the abstract Tool::schema uses mixed). - Narrow the MCP user to App\Models\User via instanceof before gating. - Fix the $tools property covariance annotation. - Exempt app/Mcp from public.method.unused (framework entry points invoked by laravel/mcp via reflection), matching how controllers/jobs/policies are treated. --- app/Mcp/Servers/WhisperMoneyServer.php | 3 ++- app/Mcp/Tools/GetCashflow.php | 2 +- app/Mcp/Tools/GetNetWorth.php | 2 +- app/Mcp/Tools/ListAccounts.php | 2 +- app/Mcp/Tools/ListCategories.php | 2 +- app/Mcp/Tools/McpTool.php | 2 +- app/Mcp/Tools/SearchTransactions.php | 2 +- app/Mcp/Tools/SpendingByCategory.php | 2 +- phpstan.neon | 6 ++++++ 9 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/Mcp/Servers/WhisperMoneyServer.php b/app/Mcp/Servers/WhisperMoneyServer.php index df711723..42f0ae59 100644 --- a/app/Mcp/Servers/WhisperMoneyServer.php +++ b/app/Mcp/Servers/WhisperMoneyServer.php @@ -13,6 +13,7 @@ use Laravel\Mcp\Server; use Laravel\Mcp\Server\Attributes\Instructions; use Laravel\Mcp\Server\Attributes\Name; use Laravel\Mcp\Server\Attributes\Version; +use Laravel\Mcp\Server\Tool; #[Name('Whisper Money')] #[Version('1.0.0')] @@ -30,7 +31,7 @@ analysing spending, cashflow and net worth. MARKDOWN)] class WhisperMoneyServer extends Server { - /** @var array */ + /** @var array> */ protected array $tools = [ SearchTransactions::class, SpendingByCategory::class, diff --git a/app/Mcp/Tools/GetCashflow.php b/app/Mcp/Tools/GetCashflow.php index 7e4c13a1..ac618762 100644 --- a/app/Mcp/Tools/GetCashflow.php +++ b/app/Mcp/Tools/GetCashflow.php @@ -15,7 +15,7 @@ use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly; class GetCashflow extends McpTool { /** - * @return array + * @return array */ public function schema(JsonSchema $schema): array { diff --git a/app/Mcp/Tools/GetNetWorth.php b/app/Mcp/Tools/GetNetWorth.php index 4de93b9e..bb866ec3 100644 --- a/app/Mcp/Tools/GetNetWorth.php +++ b/app/Mcp/Tools/GetNetWorth.php @@ -15,7 +15,7 @@ use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly; class GetNetWorth extends McpTool { /** - * @return array + * @return array */ public function schema(JsonSchema $schema): array { diff --git a/app/Mcp/Tools/ListAccounts.php b/app/Mcp/Tools/ListAccounts.php index eafe1e2a..c8f155a1 100644 --- a/app/Mcp/Tools/ListAccounts.php +++ b/app/Mcp/Tools/ListAccounts.php @@ -15,7 +15,7 @@ use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly; class ListAccounts extends McpTool { /** - * @return array + * @return array */ public function schema(JsonSchema $schema): array { diff --git a/app/Mcp/Tools/ListCategories.php b/app/Mcp/Tools/ListCategories.php index 0850506d..d26bfa68 100644 --- a/app/Mcp/Tools/ListCategories.php +++ b/app/Mcp/Tools/ListCategories.php @@ -15,7 +15,7 @@ use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly; class ListCategories extends McpTool { /** - * @return array + * @return array */ public function schema(JsonSchema $schema): array { diff --git a/app/Mcp/Tools/McpTool.php b/app/Mcp/Tools/McpTool.php index b2f5b67d..925cb8ef 100644 --- a/app/Mcp/Tools/McpTool.php +++ b/app/Mcp/Tools/McpTool.php @@ -31,7 +31,7 @@ abstract class McpTool extends Tool { $user = $request->user(); - if ($user === null) { + if (! $user instanceof User) { return Response::error('Authentication required.'); } diff --git a/app/Mcp/Tools/SearchTransactions.php b/app/Mcp/Tools/SearchTransactions.php index 6d3e0b22..000f2c04 100644 --- a/app/Mcp/Tools/SearchTransactions.php +++ b/app/Mcp/Tools/SearchTransactions.php @@ -15,7 +15,7 @@ use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly; class SearchTransactions extends McpTool { /** - * @return array + * @return array */ public function schema(JsonSchema $schema): array { diff --git a/app/Mcp/Tools/SpendingByCategory.php b/app/Mcp/Tools/SpendingByCategory.php index 344d64cc..22da0ec3 100644 --- a/app/Mcp/Tools/SpendingByCategory.php +++ b/app/Mcp/Tools/SpendingByCategory.php @@ -16,7 +16,7 @@ use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly; class SpendingByCategory extends McpTool { /** - * @return array + * @return array */ public function schema(JsonSchema $schema): array { diff --git a/phpstan.neon b/phpstan.neon index c745a4ee..b1fd3a12 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -23,6 +23,12 @@ parameters: path: app/Http/Controllers/* - identifier: public.method.unused path: app/Http/Controllers/**/* + # MCP servers and tools are entry points invoked by laravel/mcp via + # reflection, not called from PHP code. + - identifier: public.method.unused + path: app/Mcp/* + - identifier: public.method.unused + path: app/Mcp/**/* - identifier: public.method.unused path: app/Http/Middleware/* - identifier: public.property.unused