ModelTools.php•8.65 kB
<?php
declare(strict_types=1);
namespace OpenFGA\MCP\Tools;
use OpenFGA\ClientInterface;
use OpenFGA\Exceptions\SerializationException;
use OpenFGA\Models\AuthorizationModelInterface;
use OpenFGA\Responses\{CreateAuthorizationModelResponseInterface, GetAuthorizationModelResponseInterface, ListAuthorizationModelsResponseInterface};
use PhpMcp\Server\Attributes\{McpTool};
use Throwable;
use function assert;
final readonly class ModelTools extends AbstractTools
{
public function __construct(
private ClientInterface $client,
) {
}
/**
* Create a new authorization model using OpenFGA's DSL syntax.
*
* @param string $dsl DSL representing the authorization model to create
* @param string $store ID of the store to create the authorization model in
*
* @throws SerializationException
* @throws Throwable
*
* @return string a success message, or an error message
*/
#[McpTool(
name: 'create_model',
)]
public function createModel(
string $dsl,
string $store,
): string {
$error = $this->checkOfflineMode('Creating authorization models');
if (null !== $error) {
return $error;
}
$failure = null;
$success = '';
$authorizationModel = null;
$error = $this->checkWritePermission('create authorization models');
if (null !== $error) {
return $error;
}
$error = $this->checkRestrictedMode(storeId: $store);
if (null !== $error) {
return $error;
}
$this->client->dsl(dsl: $dsl)
->failure(static function (Throwable $e) use (&$failure): void {
$failure = '❌ Failed to create authorization model! Error: ' . $e->getMessage();
})
->success(static function (mixed $model) use (&$authorizationModel): void {
if ($model instanceof AuthorizationModelInterface) {
$authorizationModel = $model;
}
});
if (null !== $failure) {
return $failure;
}
if (! $authorizationModel instanceof AuthorizationModelInterface) {
return '❌ Failed to create authorization model!';
}
$this->client->createAuthorizationModel(store: $store, typeDefinitions: $authorizationModel->getTypeDefinitions(), conditions: $authorizationModel->getConditions())
->failure(static function (Throwable $e) use (&$failure): void {
$failure = '❌ Failed to create authorization model! Error: ' . $e->getMessage();
})
->success(static function (mixed $model) use (&$success): void {
assert($model instanceof CreateAuthorizationModelResponseInterface);
$success = '✅ Successfully created authorization model! Model ID: ' . $model->getModel();
});
return $failure ?? $success;
}
/**
* Get a specific authorization model from a particular store.
*
* @param string $store ID of the store to get the authorization model from
* @param string $model ID of the authorization model to get
*
* @throws Throwable
*
* @return string the authorization model, or an error message
*/
#[McpTool(name: 'get_model')]
public function getModel(
string $store,
string $model,
): string {
$error = $this->checkOfflineMode('Getting authorization model');
if (null !== $error) {
return $error;
}
$failure = null;
$success = '';
$error = $this->checkRestrictedMode(storeId: $store, modelId: $model);
if (null !== $error) {
return $error;
}
$this->client->getAuthorizationModel(store: $store, model: $model)
->failure(static function (Throwable $e) use (&$failure): void {
$failure = '❌ Failed to get authorization model! Error: ' . $e->getMessage();
})
->success(static function (mixed $model) use (&$success): void {
assert($model instanceof GetAuthorizationModelResponseInterface);
$authModel = $model->getModel();
if ($authModel instanceof AuthorizationModelInterface) {
$success = '✅ Found authorization model! Model ID: ' . $authModel->getId();
} else {
$success = '❌ Authorization model not found!';
}
});
return $failure ?? $success;
}
/**
* Get the DSL from a specific authorization model from a particular store.
*
* @param string $store ID of the store to get the authorization model from
* @param string $model ID of the authorization model to get
*
* @throws Throwable
*
* @return string the DSL representation of the authorization model, or an error message
*/
#[McpTool(name: 'get_model_dsl')]
public function getModelDsl(
string $store,
string $model,
): string {
$error = $this->checkOfflineMode('Getting authorization model DSL');
if (null !== $error) {
return $error;
}
$failure = null;
$success = '';
$error = $this->checkRestrictedMode(storeId: $store, modelId: $model);
if (null !== $error) {
return $error;
}
$this->client->getAuthorizationModel(store: $store, model: $model)
->failure(static function (Throwable $e) use (&$failure): void {
$failure = '❌ Failed to get authorization model! Error: ' . $e->getMessage();
})
->success(static function (mixed $model) use (&$success): void {
assert($model instanceof GetAuthorizationModelResponseInterface);
$authModel = $model->getModel();
$success = $authModel instanceof AuthorizationModelInterface ? $authModel->dsl() : '❌ Authorization model not found!';
});
return $failure ?? $success;
}
/**
* List authorization models in a store, sorted in descending order of creation.
*
* @param string $store ID of the store to list authorization models for
*
* @throws Throwable
*
* @return array<array{id: string}>|string A list of authorization models, or an error message
*/
#[McpTool(name: 'list_models')]
public function listModels(
string $store,
): string | array {
$error = $this->checkOfflineMode('Listing authorization models');
if (null !== $error) {
return $error;
}
$failure = null;
$success = [];
$error = $this->checkRestrictedMode(storeId: $store);
if (null !== $error) {
return $error;
}
$this->client->listAuthorizationModels(store: $store)
->failure(static function (Throwable $e) use (&$failure): void {
$failure = '❌ Failed to list authorization models! Error: ' . $e->getMessage();
})
->success(static function (mixed $models) use (&$success): void {
assert($models instanceof ListAuthorizationModelsResponseInterface);
foreach ($models->getModels() as $model) {
$success[] = [
'id' => $model->getId(),
];
}
});
return $failure ?? $success;
}
/**
* Verify a DSL representation of an authorization model.
*
* @param string $dsl DSL representation of the authorization model to verify
*
* @throws SerializationException
* @throws Throwable
*
* @return string a success message, or an error message
*/
#[McpTool(name: 'verify_model')]
public function verifyModel(
string $dsl,
): string {
$error = $this->checkOfflineMode('Verifying authorization model');
if (null !== $error) {
return $error;
}
$failure = null;
$success = '';
$this->client->dsl(dsl: $dsl)
->failure(static function (Throwable $e) use (&$failure): void {
$failure = '❌ Failed to verify authorization model! Error: ' . $e->getMessage();
})
->success(static function () use (&$success): void {
$success = '✅ Successfully verified! This DSL appears to represent a valid authorization model.';
});
return $failure ?? $success;
}
}