Skip to content

Refactor Tools to improve consistency and readability #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions src/Mcp/Methods/CallToolWithExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,43 @@

namespace Laravel\Boost\Mcp\Methods;

use Generator;
use Illuminate\Support\ItemNotFoundException;
use Laravel\Boost\Mcp\ToolExecutor;
use Laravel\Mcp\Server\Contracts\Methods\Method;
use Laravel\Mcp\Server\ServerContext;
use Laravel\Mcp\Server\Tools\ToolResult;
use Laravel\Mcp\Server\Transport\JsonRpcNotification;
use Laravel\Mcp\Server\Transport\JsonRpcRequest;
use Laravel\Mcp\Server\Transport\JsonRpcResponse;
use Throwable;

class CallToolWithExecutor implements Method
{
/**
* Handle the JSON-RPC tool/call request with process isolation.
*
* @return JsonRpcResponse|Generator<JsonRpcNotification|JsonRpcResponse>
* @param JsonRpcRequest $request
* @param ServerContext $context
* @return JsonRpcResponse
*/
public function handle(JsonRpcRequest $request, ServerContext $context)
public function handle(JsonRpcRequest $request, ServerContext $context): JsonRpcResponse
{
try {
$tool = $context->tools()
->firstOrFail(fn ($tool) => $tool->name() === $request->params['name']);
} catch (ItemNotFoundException $e) {
$tool = $context->tools()->firstOrFail(fn ($tool) => $tool->name() === $request->params['name']);
} catch (ItemNotFoundException) {
return JsonRpcResponse::create(
$request->id,
ToolResult::error('Tool not found')
);
} catch (\Throwable $e) {
} catch (Throwable $e) {
return JsonRpcResponse::create(
$request->id,
ToolResult::error('Error finding tool: '.$e->getMessage())
);
}

try {
// Use ToolExecutor instead of calling tool directly
$executor = app(ToolExecutor::class);

// Safely get arguments
$arguments = [];
if (isset($request->params['arguments']) && is_array($request->params['arguments'])) {
$arguments = $request->params['arguments'];
Expand All @@ -52,7 +50,7 @@ public function handle(JsonRpcRequest $request, ServerContext $context)

return JsonRpcResponse::create($request->id, $result);

} catch (\Throwable $e) {
} catch (Throwable $e) {
return JsonRpcResponse::create(
$request->id,
ToolResult::error('Tool execution error: '.$e->getMessage())
Expand Down
5 changes: 2 additions & 3 deletions src/Mcp/Tools/BrowserLogs.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@

namespace Laravel\Boost\Mcp\Tools;

use Illuminate\Support\Facades\Log;
use Laravel\Boost\Concerns\ReadsLogs;
use Laravel\Mcp\Server\Tool;
use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
use Laravel\Mcp\Server\Tools\ToolInputSchema;
use Laravel\Mcp\Server\Tools\ToolResult;

#[IsReadOnly()]
#[IsReadOnly]
class BrowserLogs extends Tool
{
use ReadsLogs;
Expand Down Expand Up @@ -41,7 +40,7 @@ public function handle(array $arguments): ToolResult
return ToolResult::error('The "entries" argument must be greater than 0.');
}

// Locate the correct log file using shared helper.
// Locate the correct log file using the shared helper.
$logFile = storage_path('logs/browser.log');

if (! file_exists($logFile)) {
Expand Down
3 changes: 1 addition & 2 deletions src/Mcp/Tools/DatabaseConnections.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Laravel\Mcp\Server\Tools\ToolInputSchema;
use Laravel\Mcp\Server\Tools\ToolResult;

#[IsReadOnly()]
#[IsReadOnly]
class DatabaseConnections extends Tool
{
public function description(): string
Expand All @@ -19,7 +19,6 @@ public function description(): string

public function schema(ToolInputSchema $schema): ToolInputSchema
{
// No inputs required for this tool.
return $schema;
}

Expand Down
9 changes: 5 additions & 4 deletions src/Mcp/Tools/DatabaseQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
use Laravel\Mcp\Server\Tools\ToolInputSchema;
use Laravel\Mcp\Server\Tools\ToolResult;
use Throwable;

#[IsReadOnly()]
#[IsReadOnly]
class DatabaseQuery extends Tool
{
/**
Expand Down Expand Up @@ -56,9 +57,9 @@ public function handle(array $arguments): ToolResult
'EXPLAIN',
'DESCRIBE',
'DESC',
'WITH', // Common-table expressions, must be followed by SELECT
'WITH', // SELECT must follow Common-table expressions
'VALUES', // Returns literal values
'TABLE', // PostgreSQL shorthand for SELECT *
'TABLE', // PostgresSQL shorthand for SELECT *
];

$isReadOnly = in_array($firstWord, $allowList, true);
Expand All @@ -80,7 +81,7 @@ public function handle(array $arguments): ToolResult
return ToolResult::json(
DB::connection($connectionName)->select($query)
);
} catch (\Throwable $e) {
} catch (Throwable $e) {
return ToolResult::error('Query failed: '.$e->getMessage());
}
}
Expand Down
24 changes: 12 additions & 12 deletions src/Mcp/Tools/DatabaseSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Laravel\Boost\Mcp\Tools;

use Exception;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
Expand All @@ -14,7 +16,7 @@
use Laravel\Mcp\Server\Tools\ToolInputSchema;
use Laravel\Mcp\Server\Tools\ToolResult;

#[IsReadOnly()]
#[IsReadOnly]
class DatabaseSchema extends Tool
{
public function description(): string
Expand Down Expand Up @@ -42,7 +44,7 @@ public function handle(array $arguments): ToolResult
{
$connection = $arguments['database'] ?? config('database.default');
$filter = $arguments['filter'] ?? '';
$cacheKey = "boost:mcp:database-schema:{$connection}:{$filter}";
$cacheKey = "boost:mcp:database-schema:$connection:$filter";

$schema = Cache::remember($cacheKey, 20, function () use ($connection, $filter) {
return $this->getDatabaseStructure($connection, $filter);
Expand All @@ -53,13 +55,11 @@ public function handle(array $arguments): ToolResult

protected function getDatabaseStructure(?string $connection, string $filter = ''): array
{
$structure = [
return [
'engine' => DB::connection($connection)->getDriverName(),
'tables' => $this->getAllTablesStructure($connection, $filter),
'global' => $this->getGlobalStructure($connection),
];

return $structure;
}

protected function getAllTablesStructure(?string $connection, string $filter = ''): array
Expand Down Expand Up @@ -102,7 +102,7 @@ protected function getTableStructure(?string $connection, string $tableName): ar
'triggers' => $triggers,
'check_constraints' => $checkConstraints,
];
} catch (\Exception $e) {
} catch (Exception $e) {
Log::error('Failed to get table structure for: '.$tableName, [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
Expand Down Expand Up @@ -136,15 +136,15 @@ protected function getTableIndexes(?string $connection, string $tableName): arra

foreach ($indexes as $index) {
$indexDetails[$index['name']] = [
'columns' => $index['columns'],
'type' => $index['type'] ?? null,
'is_unique' => $index['unique'] ?? false,
'is_primary' => $index['primary'] ?? false,
'columns' => Arr::get($index, 'columns'),
'type' => Arr::get($index, 'type'),
'is_unique' => Arr::get($index, 'unique', false),
'is_primary' => Arr::get($index, 'primary', false),
];
}

return $indexDetails;
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -153,7 +153,7 @@ protected function getTableForeignKeys(?string $connection, string $tableName):
{
try {
return Schema::connection($connection)->getForeignKeys($tableName);
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand Down
11 changes: 6 additions & 5 deletions src/Mcp/Tools/DatabaseSchema/MySQLSchemaDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Laravel\Boost\Mcp\Tools\DatabaseSchema;

use Exception;
use Illuminate\Support\Facades\DB;

class MySQLSchemaDriver extends DatabaseSchemaDriver
Expand All @@ -16,7 +17,7 @@ public function getViews(): array
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = DATABASE()
');
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -25,7 +26,7 @@ public function getStoredProcedures(): array
{
try {
return DB::connection($this->connection)->select('SHOW PROCEDURE STATUS WHERE Db = DATABASE()');
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -34,7 +35,7 @@ public function getFunctions(): array
{
try {
return DB::connection($this->connection)->select('SHOW FUNCTION STATUS WHERE Db = DATABASE()');
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -47,7 +48,7 @@ public function getTriggers(?string $table = null): array
}

return DB::connection($this->connection)->select('SHOW TRIGGERS');
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -61,7 +62,7 @@ public function getCheckConstraints(string $table): array
WHERE CONSTRAINT_SCHEMA = DATABASE()
AND TABLE_NAME = ?
', [$table]);
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand Down
21 changes: 11 additions & 10 deletions src/Mcp/Tools/DatabaseSchema/PostgreSQLSchemaDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Laravel\Boost\Mcp\Tools\DatabaseSchema;

use Exception;
use Illuminate\Support\Facades\DB;

class PostgreSQLSchemaDriver extends DatabaseSchemaDriver
Expand All @@ -12,11 +13,11 @@ public function getViews(): array
{
try {
return DB::connection($this->connection)->select("
SELECT schemaname, viewname, definition
FROM pg_views
SELECT schemaname, viewname, definition
FROM pg_views
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
");
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -31,7 +32,7 @@ public function getStoredProcedures(): array
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
AND prokind = 'p'
");
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -46,7 +47,7 @@ public function getFunctions(): array
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
AND prokind = 'f'
");
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -66,7 +67,7 @@ public function getTriggers(?string $table = null): array
}

return DB::connection($this->connection)->select($sql);
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -76,11 +77,11 @@ public function getCheckConstraints(string $table): array
try {
return DB::connection($this->connection)->select("
SELECT conname, pg_get_constraintdef(oid) as definition
FROM pg_constraint
WHERE contype = 'c'
FROM pg_constraint
WHERE contype = 'c'
AND conrelid = ?::regclass
", [$table]);
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -93,7 +94,7 @@ public function getSequences(): array
FROM information_schema.sequences
WHERE sequence_schema = current_schema()
');
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/Mcp/Tools/DatabaseSchema/SQLiteSchemaDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Laravel\Boost\Mcp\Tools\DatabaseSchema;

use Exception;
use Illuminate\Support\Facades\DB;

class SQLiteSchemaDriver extends DatabaseSchemaDriver
Expand All @@ -12,11 +13,11 @@ public function getViews(): array
{
try {
return DB::connection($this->connection)->select("
SELECT name, sql
FROM sqlite_master
SELECT name, sql
FROM sqlite_master
WHERE type = 'view'
");
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand All @@ -42,7 +43,7 @@ public function getTriggers(?string $table = null): array
}

return DB::connection($this->connection)->select($sql);
} catch (\Exception $e) {
} catch (Exception) {
return [];
}
}
Expand Down
Loading
Loading