Files
Lesstime/src/Module/Directory/Infrastructure/Mcp/Tool/GetPrestataireTool.php
T
matthieu 99626b89da
Pull Request — Quality gate / Frontend (build) (pull_request) Successful in 41s
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 59s
feat(mcp) : outils MCP Directory pour prestataires, contacts, adresses et rapports
Ajoute 20 nouveaux outils MCP pour permettre à Claude (ou tout client MCP) de
remplir un dossier client / prospect / prestataire complet — onglets
Information, Contact, Adresse et Rapport — sans passer par l'UI.

Entités couvertes (CRUD complet, 5 outils chacune) :
- Prestataire : create / update / get / list / delete
- Contact : create / update / get / list / delete
- Address : create / update / get / list / delete
- CommercialReport : create / update / get / list / delete

Détails :
- Contact / Address / CommercialReport doivent être rattachés à exactement
  un parent parmi clientId, prospectId, prestataireId (validation côté tool).
- get-client, get-prospect et get-prestataire renvoient désormais un payload
  enrichi avec la liste de leurs contacts, adresses et rapports liés : un
  seul appel pour reconstruire l'onglet entier.
- Pour CommercialReport, le type (note / call / meeting / email) et la date
  occurredAt sont validés ; l'auteur est rempli automatiquement par le
  listener existant.
- Sécurité : ROLE_ADMIN aligné sur les autres outils MCP de Directory (pas
  de migration vers les permissions RBAC fines pour rester cohérent).

Plumbing :
- Repositories Contact / Address / CommercialReport : ajout de findBy() sur
  les interfaces (l'implémentation Doctrine l'a déjà via ServiceEntityRepository).
- Bindings interface -> implémentation Doctrine ajoutés dans services.yaml
  pour Prestataire / Contact / Address / CommercialReport.
- Sérialiseur partagé étendu : prestataire / contact / address /
  commercialReport / reportDocument.

Vérification : 86 outils MCP exposés au total (66 avant + 20 ajoutés), test
end-to-end via le transport HTTP (create-prestataire + create-contact +
create-address + create-commercial-report + get-prestataire renvoyant le
dossier complet). Suite PHPUnit verte.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 20:36:46 +02:00

58 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Module\Directory\Domain\Repository\AddressRepositoryInterface;
use App\Module\Directory\Domain\Repository\CommercialReportRepositoryInterface;
use App\Module\Directory\Domain\Repository\ContactRepositoryInterface;
use App\Module\Directory\Domain\Repository\PrestataireRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use function sprintf;
#[McpTool(name: 'get-prestataire', description: 'Get a prestataire by ID, with its linked contacts, addresses, and commercial reports.')]
class GetPrestataireTool
{
public function __construct(
private readonly PrestataireRepositoryInterface $prestataireRepository,
private readonly ContactRepositoryInterface $contactRepository,
private readonly AddressRepositoryInterface $addressRepository,
private readonly CommercialReportRepositoryInterface $reportRepository,
private readonly Security $security,
) {}
public function __invoke(int $id): string
{
if (!$this->security->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException('Access denied: ROLE_ADMIN required.');
}
$prestataire = $this->prestataireRepository->findById($id);
if (null === $prestataire) {
throw new InvalidArgumentException(sprintf('Prestataire with ID %d not found.', $id));
}
$payload = Serializer::prestataire($prestataire);
$payload['contacts'] = array_map(
fn ($c) => Serializer::contact($c),
$this->contactRepository->findBy(['prestataire' => $prestataire], ['lastName' => 'ASC'])
);
$payload['addresses'] = array_map(
fn ($a) => Serializer::address($a),
$this->addressRepository->findBy(['prestataire' => $prestataire], ['id' => 'ASC'])
);
$payload['reports'] = array_map(
fn ($r) => Serializer::commercialReport($r),
$this->reportRepository->findBy(['prestataire' => $prestataire], ['occurredAt' => 'DESC'])
);
return json_encode($payload);
}
}