76 lines
4.3 KiB
PHP
76 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace App\Mcp\Tools;
|
|
|
|
use App\Actions\Permissions\PermissionService;
|
|
use App\Enums\Permission;
|
|
use App\Mcp\Support\KanbanGitMcp;
|
|
use App\Models\TicketStatus;
|
|
use App\Models\User;
|
|
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
|
use Illuminate\JsonSchema\Types\Type;
|
|
use Laravel\Mcp\Request;
|
|
use Laravel\Mcp\Response;
|
|
use Laravel\Mcp\ResponseFactory;
|
|
use Laravel\Mcp\Server\Attributes\Description;
|
|
use Laravel\Mcp\Server\Attributes\Name;
|
|
use Laravel\Mcp\Server\Tool;
|
|
use Laravel\Mcp\Server\Tools\Annotations\IsReadOnly;
|
|
|
|
#[Name('get_project_configuration')]
|
|
#[Description('Get compact current configuration for a visible project: ordered columns, statuses with IDs/slugs/column assignment and allowed target status IDs, types, priorities, custom field definitions, and permitted people IDs/names. Reads live effective configuration, without template snapshots or full user/project objects. People are paginated (default 25, maximum 100); use people_page for subsequent pages. Author changes require project admin permission, reported in permissions.')]
|
|
#[IsReadOnly]
|
|
class GetProjectConfiguration extends Tool
|
|
{
|
|
public function __construct(private readonly KanbanGitMcp $kanbanGitMcp, private readonly PermissionService $permissionService) {}
|
|
|
|
public function handle(Request $request): Response|ResponseFactory
|
|
{
|
|
$input = $request->validate([
|
|
'project_id' => ['required', 'integer'],
|
|
'people_page' => ['sometimes', 'integer', 'min:1'],
|
|
'people_per_page' => ['sometimes', 'integer', 'min:1', 'max:100'],
|
|
]);
|
|
$user = $this->kanbanGitMcp->user($request);
|
|
$project = $this->kanbanGitMcp->projectForRead($user, $input['project_id']);
|
|
$people = User::query()->visibleToProject($project)->orderBy('id')->paginate($input['people_per_page'] ?? 25, ['id', 'name'], 'people_page', $input['people_page'] ?? 1);
|
|
|
|
$columns = $project->boardColumns()->orderBy('id')->get(['id', 'name', 'position']);
|
|
$columnPositions = $columns->pluck('position', 'id');
|
|
$statuses = $project->ticketStatuses()->with('allowedTargetStatuses')->get()->sortBy(
|
|
fn (TicketStatus $status): array => [$columnPositions->get($status->board_column_id, 0), $status->position, $status->id],
|
|
)->values();
|
|
|
|
return Response::structured([
|
|
'data' => [
|
|
'project' => ['id' => $project->id, 'key' => $project->key, 'name' => $project->name],
|
|
'permissions' => [
|
|
'can_write' => $this->permissionService->allows($user, Permission::ProjectWrite, $project),
|
|
'can_change_author' => $this->permissionService->allows($user, Permission::ProjectAdmin, $project),
|
|
],
|
|
'board_columns' => $columns->toArray(),
|
|
'ticket_statuses' => $statuses->map(fn (TicketStatus $status): array => [
|
|
'id' => $status->id, 'name' => $status->name, 'slug' => $status->slug,
|
|
'position' => $status->position, 'board_column_id' => $status->board_column_id,
|
|
'allowed_target_status_ids' => $status->allowedTargetStatuses->pluck('id')->all(),
|
|
])->all(),
|
|
'ticket_types' => $project->ticketTypes()->orderBy('id')->get(['id', 'name', 'position', 'is_parent'])->toArray(),
|
|
'ticket_priorities' => $project->ticketPriorities()->orderBy('id')->get(['id', 'name', 'position'])->toArray(),
|
|
'ticket_field_definitions' => $project->ticketFieldDefinitions()->orderBy('id')->get(['id', 'label', 'field_type', 'position'])->toArray(),
|
|
'people' => $people->getCollection()->map(fn (User $person): array => ['id' => $person->id, 'name' => $person->name])->all(),
|
|
],
|
|
'meta' => ['people' => $this->kanbanGitMcp->paginationPayload($people)],
|
|
]);
|
|
}
|
|
|
|
/** @return array<string, Type> */
|
|
public function schema(JsonSchema $schema): array
|
|
{
|
|
return [
|
|
'project_id' => $schema->integer()->description('Visible project ID from list_projects.')->required(),
|
|
'people_page' => $schema->integer()->min(1)->description('People page number, defaults to 1.'),
|
|
'people_per_page' => $schema->integer()->min(1)->max(100)->description('People page size, defaults to 25; maximum 100.'),
|
|
];
|
|
}
|
|
}
|