Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24c53368a7 | ||
|
|
29b854fd44 |
No files matched your search
@@ -11,10 +11,16 @@ use App\Mcp\Resources\BestPractices;
|
||||
use App\Mcp\Resources\CodeSnippets;
|
||||
use App\Mcp\Resources\DatabaseQueries;
|
||||
use App\Mcp\Resources\FrameworkComparison;
|
||||
use App\Mcp\Tools\COX\Doorlock\Client\GetOxDoorlockClientFunction;
|
||||
use App\Mcp\Tools\COX\Doorlock\Server\GetOxDoorlockServerEvent;
|
||||
use App\Mcp\Tools\COX\Doorlock\Server\GetOxDoorlockServerFunction;
|
||||
use App\Mcp\Tools\COX\Fuel\Client\GetOxFuelClientFunction;
|
||||
use App\Mcp\Tools\COX\Fuel\Server\GetOxFuelServerFunction;
|
||||
use App\Mcp\Tools\COX\Inventory\Client\GetInventoryClientFunction;
|
||||
use App\Mcp\Tools\COX\Inventory\Server\GetInventoryServerFunction;
|
||||
use App\Mcp\Tools\COX\MySQL\GetCOXEventReference;
|
||||
use App\Mcp\Tools\COX\MySQL\GetCOXFunction;
|
||||
use App\Mcp\Tools\COX\Target\Client\GetOxTargetClientFunction;
|
||||
use App\Mcp\Tools\FiveM\Client\GetEventClientReference;
|
||||
use App\Mcp\Tools\FiveM\Client\GetNativeClientFunction;
|
||||
use App\Mcp\Tools\FiveM\GenerateManifest;
|
||||
@@ -26,6 +32,8 @@ use App\Mcp\Tools\QBCore\Client\GetQBCoreClientEventReference;
|
||||
use App\Mcp\Tools\QBCore\Client\GetQBCoreClientFunction;
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreConfig;
|
||||
use App\Mcp\Tools\QBCore\GetQBCorePlayers;
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreResourceList;
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreResourceReference;
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreSharedData;
|
||||
use App\Mcp\Tools\QBCore\Server\GetQBCoreServerEventReference;
|
||||
use App\Mcp\Tools\QBCore\Server\GetQBCoreServerFunction;
|
||||
@@ -66,10 +74,18 @@ class FiveMServer extends Server
|
||||
GetQBCoreSharedData::class,
|
||||
GetQBCoreConfig::class,
|
||||
GetQBCorePlayers::class,
|
||||
GetQBCoreResourceList::class,
|
||||
GetQBCoreResourceReference::class,
|
||||
GetCOXEventReference::class,
|
||||
GetCOXFunction::class,
|
||||
GetInventoryServerFunction::class,
|
||||
GetInventoryClientFunction::class,
|
||||
GetOxTargetClientFunction::class,
|
||||
GetOxFuelClientFunction::class,
|
||||
GetOxFuelServerFunction::class,
|
||||
GetOxDoorlockClientFunction::class,
|
||||
GetOxDoorlockServerFunction::class,
|
||||
GetOxDoorlockServerEvent::class,
|
||||
];
|
||||
|
||||
protected array $resources = [
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\COX\Doorlock\Client;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up ox_doorlock client functions by name. Returns function signature, parameters, return type, and usage examples for client-side door management.')]
|
||||
class GetOxDoorlockClientFunction extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$functionName = $request->get('function_name');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$function = $this->findFunction($functionName);
|
||||
|
||||
if (! $function) {
|
||||
return Response::text(sprintf("ox_doorlock client function '%s' not found. Check ox_doorlock documentation at https://coxdocs.dev/ox_doorlock", $functionName));
|
||||
}
|
||||
|
||||
$output = $this->formatFunctionInfo($function, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an ox_doorlock client function.
|
||||
*/
|
||||
protected function findFunction(string $name): ?array
|
||||
{
|
||||
$functions = [
|
||||
'pickClosestDoor' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Attempt to lockpick the closest door',
|
||||
'side' => 'client',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => 'exports.ox_doorlock:pickClosestDoor()',
|
||||
'js_example' => 'exports.ox_doorlock.pickClosestDoor();',
|
||||
],
|
||||
'useClosestDoor' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Toggle the lock state of the closest door',
|
||||
'side' => 'client',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => 'exports.ox_doorlock:useClosestDoor()',
|
||||
'js_example' => 'exports.ox_doorlock.useClosestDoor();',
|
||||
],
|
||||
'getClosestDoor' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Get data for the closest door',
|
||||
'side' => 'client',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'table|nil', 'description' => 'Door data or nil if no door nearby'],
|
||||
'lua_example' => "local door = exports.ox_doorlock:getClosestDoor()\nif door then\n print('Closest door ID: '..door.id)\n print('Door is locked: '..tostring(door.state == 1))\nend",
|
||||
'js_example' => "const door = exports.ox_doorlock.getClosestDoor();\nif (door) {\n console.log('Closest door ID: ' + door.id);\n console.log('Door is locked: ' + (door.state === 1));\n}",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($functions as $functionName => $functionData) {
|
||||
if (strtolower($functionName) === $nameLower) {
|
||||
return array_merge(['name' => $functionName], $functionData);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format function info.
|
||||
*/
|
||||
protected function formatFunctionInfo(array $function, string $language): string
|
||||
{
|
||||
return view('mcp.cox.cox-function', [
|
||||
'function' => $function,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'function_name' => $schema
|
||||
->string()
|
||||
->description('The name of the ox_doorlock client function to look up (e.g., "pickClosestDoor", "useClosestDoor", "getClosestDoor")')
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\COX\Doorlock\Server;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up ox_doorlock server events by name. Returns event signature, parameters, and usage examples for server-side door events.')]
|
||||
class GetOxDoorlockServerEvent extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$eventName = $request->get('event_name');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$event = $this->findEvent($eventName);
|
||||
|
||||
if (! $event) {
|
||||
return Response::text(sprintf("ox_doorlock server event '%s' not found. Check ox_doorlock documentation at https://coxdocs.dev/ox_doorlock", $eventName));
|
||||
}
|
||||
|
||||
$output = $this->formatEventInfo($event, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an ox_doorlock server event.
|
||||
*/
|
||||
protected function findEvent(string $name): ?array
|
||||
{
|
||||
$events = [
|
||||
'ox_doorlock:stateChanged' => [
|
||||
'type' => 'doorlock',
|
||||
'namespace' => 'Server',
|
||||
'description' => 'Triggered when a door lock state changes',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'doorId', 'type' => 'number', 'description' => 'The door ID'],
|
||||
['name' => 'state', 'type' => 'number', 'description' => 'New door state (0 = unlocked, 1 = locked)'],
|
||||
],
|
||||
'lua_example' => "AddEventHandler('ox_doorlock:stateChanged', function(doorId, state)\n local doorName = exports.ox_doorlock:getDoor(doorId)?.name or 'Unknown'\n local stateText = state == 1 and 'locked' or 'unlocked'\n print(('Door %s (ID: %s) is now %s'):format(doorName, doorId, stateText))\nend)",
|
||||
'js_example' => "on('ox_doorlock:stateChanged', (doorId, state) => {\n const door = exports.ox_doorlock.getDoor(doorId);\n const doorName = door?.name || 'Unknown';\n const stateText = state === 1 ? 'locked' : 'unlocked';\n console.log(`Door \${doorName} (ID: \${doorId}) is now \${stateText}`);\n});",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($events as $eventName => $eventData) {
|
||||
if (strtolower($eventName) === $nameLower) {
|
||||
return array_merge(['name' => $eventName], $eventData);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format event info.
|
||||
*/
|
||||
protected function formatEventInfo(array $event, string $language): string
|
||||
{
|
||||
return view('mcp.cox.cox-event-reference', [
|
||||
'event' => $event,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'event_name' => $schema
|
||||
->string()
|
||||
->description('The name of the ox_doorlock server event to look up (e.g., "ox_doorlock:stateChanged")')
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\COX\Doorlock\Server;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up ox_doorlock server functions by name. Returns function signature, parameters, return type, and usage examples for server-side door management.')]
|
||||
class GetOxDoorlockServerFunction extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$functionName = $request->get('function_name');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$function = $this->findFunction($functionName);
|
||||
|
||||
if (! $function) {
|
||||
return Response::text(sprintf("ox_doorlock server function '%s' not found. Check ox_doorlock documentation at https://coxdocs.dev/ox_doorlock", $functionName));
|
||||
}
|
||||
|
||||
$output = $this->formatFunctionInfo($function, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an ox_doorlock server function.
|
||||
*/
|
||||
protected function findFunction(string $name): ?array
|
||||
{
|
||||
$functions = [
|
||||
'getDoor' => [
|
||||
'namespace' => 'Server',
|
||||
'description' => 'Get door data by door ID',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'doorId', 'type' => 'number', 'description' => 'The door ID'],
|
||||
],
|
||||
'returns' => ['type' => 'table|nil', 'description' => 'Door data or nil if not found'],
|
||||
'lua_example' => "local door = exports.ox_doorlock:getDoor(1)\nif door then\n print('Door name: '..door.name)\n print('Door state: '..door.state)\nend",
|
||||
'js_example' => "const door = exports.ox_doorlock.getDoor(1);\nif (door) {\n console.log('Door name: ' + door.name);\n console.log('Door state: ' + door.state);\n}",
|
||||
],
|
||||
'getDoorFromName' => [
|
||||
'namespace' => 'Server',
|
||||
'description' => 'Get door data by door name',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'doorName', 'type' => 'string', 'description' => 'The door name'],
|
||||
],
|
||||
'returns' => ['type' => 'table|nil', 'description' => 'Door data or nil if not found'],
|
||||
'lua_example' => "local door = exports.ox_doorlock:getDoorFromName('mrpd_main')\nif door then\n print('Door ID: '..door.id)\n print('Door is locked: '..tostring(door.state == 1))\nend",
|
||||
'js_example' => "const door = exports.ox_doorlock.getDoorFromName('mrpd_main');\nif (door) {\n console.log('Door ID: ' + door.id);\n console.log('Door is locked: ' + (door.state === 1));\n}",
|
||||
],
|
||||
'editDoor' => [
|
||||
'namespace' => 'Server',
|
||||
'description' => 'Edit door properties by door ID',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'doorId', 'type' => 'number', 'description' => 'The door ID'],
|
||||
['name' => 'data', 'type' => 'table', 'description' => 'Table with properties to update (state, groups, etc.)'],
|
||||
['name' => 'playerId', 'type' => 'number|nil', 'description' => 'Optional player ID who triggered the edit'],
|
||||
],
|
||||
'returns' => ['type' => 'boolean', 'description' => 'True if door was successfully edited'],
|
||||
'lua_example' => "local success = exports.ox_doorlock:editDoor(1, {\n state = 0, -- Unlocked\n groups = {police = 0} -- Police can use\n})\nif success then\n print('Door edited successfully')\nend",
|
||||
'js_example' => "const success = exports.ox_doorlock.editDoor(1, {\n state: 0, // Unlocked\n groups: {police: 0} // Police can use\n});\nif (success) {\n console.log('Door edited successfully');\n}",
|
||||
],
|
||||
'setDoorState' => [
|
||||
'namespace' => 'Server',
|
||||
'description' => 'Set the lock state of a door',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'doorId', 'type' => 'number', 'description' => 'The door ID'],
|
||||
['name' => 'state', 'type' => 'number', 'description' => '0 = unlocked, 1 = locked'],
|
||||
['name' => 'playerId', 'type' => 'number|nil', 'description' => 'Optional player ID who triggered the state change'],
|
||||
],
|
||||
'returns' => ['type' => 'boolean', 'description' => 'True if state was successfully changed'],
|
||||
'lua_example' => "local success = exports.ox_doorlock:setDoorState(1, 1) -- Lock door ID 1\nif success then\n print('Door locked successfully')\nend",
|
||||
'js_example' => "const success = exports.ox_doorlock.setDoorState(1, 1); // Lock door ID 1\nif (success) {\n console.log('Door locked successfully');\n}",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($functions as $functionName => $functionData) {
|
||||
if (strtolower($functionName) === $nameLower) {
|
||||
return array_merge(['name' => $functionName], $functionData);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format function info.
|
||||
*/
|
||||
protected function formatFunctionInfo(array $function, string $language): string
|
||||
{
|
||||
return view('mcp.cox.cox-function', [
|
||||
'function' => $function,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'function_name' => $schema
|
||||
->string()
|
||||
->description('The name of the ox_doorlock server function to look up (e.g., "getDoor", "getDoorFromName", "editDoor", "setDoorState")')
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\COX\Fuel\Client;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up ox_fuel client functions by name. Returns function signature, parameters, return type, and usage examples for vehicle fuel management.')]
|
||||
class GetOxFuelClientFunction extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$functionName = $request->get('function_name');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$function = $this->findFunction($functionName);
|
||||
|
||||
if (! $function) {
|
||||
return Response::text(sprintf("ox_fuel client function '%s' not found. Check ox_fuel documentation at https://coxdocs.dev/ox_fuel", $functionName));
|
||||
}
|
||||
|
||||
$output = $this->formatFunctionInfo($function, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an ox_fuel client function.
|
||||
*/
|
||||
protected function findFunction(string $name): ?array
|
||||
{
|
||||
$functions = [
|
||||
'setMoneyCheck' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Set a custom function to check if a player has enough money to pay for fuel',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'callback', 'type' => 'function', 'description' => 'Function(amount: number) -> boolean that returns true if player can afford fuel'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => "exports.ox_fuel:setMoneyCheck(function(amount)\n local playerMoney = exports.framework:GetPlayerMoney()\n return playerMoney >= amount\nend)",
|
||||
'js_example' => "exports.ox_fuel.setMoneyCheck((amount) => {\n const playerMoney = exports.framework.GetPlayerMoney();\n return playerMoney >= amount;\n});",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($functions as $functionName => $functionData) {
|
||||
if (strtolower($functionName) === $nameLower) {
|
||||
return array_merge(['name' => $functionName], $functionData);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format function info.
|
||||
*/
|
||||
protected function formatFunctionInfo(array $function, string $language): string
|
||||
{
|
||||
return view('mcp.cox.cox-function', [
|
||||
'function' => $function,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'function_name' => $schema
|
||||
->string()
|
||||
->description('The name of the ox_fuel client function to look up (e.g., "setMoneyCheck")')
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\COX\Fuel\Server;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up ox_fuel server functions by name. Returns function signature, parameters, return type, and usage examples for server-side fuel management.')]
|
||||
class GetOxFuelServerFunction extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$functionName = $request->get('function_name');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$function = $this->findFunction($functionName);
|
||||
|
||||
if (! $function) {
|
||||
return Response::text(sprintf("ox_fuel server function '%s' not found. Check ox_fuel documentation at https://coxdocs.dev/ox_fuel", $functionName));
|
||||
}
|
||||
|
||||
$output = $this->formatFunctionInfo($function, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an ox_fuel server function.
|
||||
*/
|
||||
protected function findFunction(string $name): ?array
|
||||
{
|
||||
$functions = [
|
||||
'setPaymentMethod' => [
|
||||
'namespace' => 'Server',
|
||||
'description' => 'Set a custom payment method for fuel purchases',
|
||||
'side' => 'server',
|
||||
'parameters' => [
|
||||
['name' => 'callback', 'type' => 'function', 'description' => 'Function(source: number, amount: number) -> boolean that handles payment and returns true if successful'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => "exports.ox_fuel:setPaymentMethod(function(source, amount)\n local success = exports.framework:RemovePlayerMoney(source, amount)\n if success then\n print('Player '..source..' paid $'..amount..' for fuel')\n end\n return success\nend)",
|
||||
'js_example' => "exports.ox_fuel.setPaymentMethod((source, amount) => {\n const success = exports.framework.RemovePlayerMoney(source, amount);\n if (success) {\n console.log(`Player \${source} paid $\${amount} for fuel`);\n }\n return success;\n});",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($functions as $functionName => $functionData) {
|
||||
if (strtolower($functionName) === $nameLower) {
|
||||
return array_merge(['name' => $functionName], $functionData);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format function info.
|
||||
*/
|
||||
protected function formatFunctionInfo(array $function, string $language): string
|
||||
{
|
||||
return view('mcp.cox.cox-function', [
|
||||
'function' => $function,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'function_name' => $schema
|
||||
->string()
|
||||
->description('The name of the ox_fuel server function to look up (e.g., "setPaymentMethod")')
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\COX\Target\Client;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Look up ox_target client functions by name. Returns function signature, parameters, return type, and usage examples for targeting/third-eye interaction system.')]
|
||||
class GetOxTargetClientFunction extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$functionName = $request->get('function_name');
|
||||
$language = $request->get('language', 'lua');
|
||||
|
||||
$function = $this->findFunction($functionName);
|
||||
|
||||
if (! $function) {
|
||||
return Response::text(sprintf("ox_target client function '%s' not found. Check ox_target documentation at https://coxdocs.dev/ox_target", $functionName));
|
||||
}
|
||||
|
||||
$output = $this->formatFunctionInfo($function, $language);
|
||||
|
||||
return Response::text($output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an ox_target client function.
|
||||
*/
|
||||
protected function findFunction(string $name): ?array
|
||||
{
|
||||
$functions = [
|
||||
'disableTargeting' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Disables or enables the targeting system',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'disabled', 'type' => 'boolean', 'description' => 'true to disable, false to enable'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => 'exports.ox_target:disableTargeting(true) -- Disable targeting',
|
||||
'js_example' => 'exports.ox_target.disableTargeting(true); // Disable targeting',
|
||||
],
|
||||
'isActive' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Check if the targeting system is currently active',
|
||||
'side' => 'client',
|
||||
'parameters' => [],
|
||||
'returns' => ['type' => 'boolean', 'description' => 'true if targeting is active'],
|
||||
'lua_example' => "local active = exports.ox_target:isActive()\nif active then\n print('Targeting is active')\nend",
|
||||
'js_example' => "const active = exports.ox_target.isActive();\nif (active) {\n console.log('Targeting is active');\n}",
|
||||
],
|
||||
'addGlobalOption' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add a global target option that appears on all entities',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Target option configuration'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => "exports.ox_target:addGlobalOption({\n name = 'greet',\n icon = 'fas fa-hand-wave',\n label = 'Wave',\n onSelect = function()\n print('You waved!')\n end\n})",
|
||||
'js_example' => "exports.ox_target.addGlobalOption({\n name: 'greet',\n icon: 'fas fa-hand-wave',\n label: 'Wave',\n onSelect: () => {\n console.log('You waved!');\n }\n});",
|
||||
],
|
||||
'addGlobalPed' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add target options to all peds',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Option ID'],
|
||||
'lua_example' => "local id = exports.ox_target:addGlobalPed({\n {\n name = 'talk',\n icon = 'fas fa-comment',\n label = 'Talk',\n onSelect = function(data)\n print('Talking to ped: '..data.entity)\n end\n }\n})",
|
||||
'js_example' => "const id = exports.ox_target.addGlobalPed([\n {\n name: 'talk',\n icon: 'fas fa-comment',\n label: 'Talk',\n onSelect: (data) => {\n console.log('Talking to ped: ' + data.entity);\n }\n }\n]);",
|
||||
],
|
||||
'addGlobalVehicle' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add target options to all vehicles',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Option ID'],
|
||||
'lua_example' => "local id = exports.ox_target:addGlobalVehicle({\n {\n name = 'lockpick',\n icon = 'fas fa-lock',\n label = 'Lockpick Vehicle',\n canInteract = function(entity)\n return GetVehicleDoorLockStatus(entity) == 2\n end,\n onSelect = function(data)\n -- Lockpick logic\n end\n }\n})",
|
||||
'js_example' => "const id = exports.ox_target.addGlobalVehicle([\n {\n name: 'lockpick',\n icon: 'fas fa-lock',\n label: 'Lockpick Vehicle',\n canInteract: (entity) => {\n return GetVehicleDoorLockStatus(entity) === 2;\n },\n onSelect: (data) => {\n // Lockpick logic\n }\n }\n]);",
|
||||
],
|
||||
'addGlobalObject' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add target options to all objects',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Option ID'],
|
||||
'lua_example' => "local id = exports.ox_target:addGlobalObject({\n {\n name = 'examine',\n icon = 'fas fa-search',\n label = 'Examine',\n onSelect = function(data)\n print('Examining object')\n end\n }\n})",
|
||||
'js_example' => "const id = exports.ox_target.addGlobalObject([\n {\n name: 'examine',\n icon: 'fas fa-search',\n label: 'Examine',\n onSelect: (data) => {\n console.log('Examining object');\n }\n }\n]);",
|
||||
],
|
||||
'addGlobalPlayer' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add target options to all players',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Option ID'],
|
||||
'lua_example' => "local id = exports.ox_target:addGlobalPlayer({\n {\n name = 'givemoney',\n icon = 'fas fa-dollar-sign',\n label = 'Give Money',\n onSelect = function(data)\n -- Give money logic\n end\n }\n})",
|
||||
'js_example' => "const id = exports.ox_target.addGlobalPlayer([\n {\n name: 'givemoney',\n icon: 'fas fa-dollar-sign',\n label: 'Give Money',\n onSelect: (data) => {\n // Give money logic\n }\n }\n]);",
|
||||
],
|
||||
'addModel' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add target options to specific entity models',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'models', 'type' => 'string|table', 'description' => 'Model hash or array of model hashes'],
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Option ID'],
|
||||
'lua_example' => "local id = exports.ox_target:addModel('prop_atm_01', {\n {\n name = 'atm',\n icon = 'fas fa-credit-card',\n label = 'Use ATM',\n onSelect = function()\n -- Open ATM interface\n end\n }\n})",
|
||||
'js_example' => "const id = exports.ox_target.addModel('prop_atm_01', [\n {\n name: 'atm',\n icon: 'fas fa-credit-card',\n label: 'Use ATM',\n onSelect: () => {\n // Open ATM interface\n }\n }\n]);",
|
||||
],
|
||||
'addEntity' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add target options to a specific entity',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'entity', 'type' => 'number', 'description' => 'Entity handle'],
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => "local ped = PlayerPedId()\nexports.ox_target:addEntity(ped, {\n {\n name = 'selfie',\n icon = 'fas fa-camera',\n label = 'Take Selfie',\n onSelect = function()\n print('Taking selfie')\n end\n }\n})",
|
||||
'js_example' => "const ped = PlayerPedId();\nexports.ox_target.addEntity(ped, [\n {\n name: 'selfie',\n icon: 'fas fa-camera',\n label: 'Take Selfie',\n onSelect: () => {\n console.log('Taking selfie');\n }\n }\n]);",
|
||||
],
|
||||
'addLocalEntity' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add target options to a networked entity (client-side only)',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'netId', 'type' => 'number', 'description' => 'Network ID'],
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => "local netId = NetworkGetNetworkIdFromEntity(entity)\nexports.ox_target:addLocalEntity(netId, {\n {\n name = 'interact',\n icon = 'fas fa-hand',\n label = 'Interact',\n onSelect = function()\n print('Interacting')\n end\n }\n})",
|
||||
'js_example' => "const netId = NetworkGetNetworkIdFromEntity(entity);\nexports.ox_target.addLocalEntity(netId, [\n {\n name: 'interact',\n icon: 'fas fa-hand',\n label: 'Interact',\n onSelect: () => {\n console.log('Interacting');\n }\n }\n]);",
|
||||
],
|
||||
'addSphereZone' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add a sphere zone with target options',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'name', 'type' => 'string', 'description' => 'Unique zone name'],
|
||||
['name' => 'coords', 'type' => 'vector3', 'description' => 'Zone center coordinates'],
|
||||
['name' => 'radius', 'type' => 'number', 'description' => 'Zone radius'],
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
['name' => 'zoneOptions', 'type' => 'table', 'description' => 'Zone configuration'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Zone ID'],
|
||||
'lua_example' => "local id = exports.ox_target:addSphereZone('bank_atm', vector3(150.0, -1040.0, 29.5), 2.0, {\n {\n name = 'atm',\n icon = 'fas fa-credit-card',\n label = 'Use ATM',\n onSelect = function()\n print('Opening ATM')\n end\n }\n}, {})",
|
||||
'js_example' => "const id = exports.ox_target.addSphereZone('bank_atm', [150.0, -1040.0, 29.5], 2.0, [\n {\n name: 'atm',\n icon: 'fas fa-credit-card',\n label: 'Use ATM',\n onSelect: () => {\n console.log('Opening ATM');\n }\n }\n], {});",
|
||||
],
|
||||
'addBoxZone' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add a box zone with target options',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'name', 'type' => 'string', 'description' => 'Unique zone name'],
|
||||
['name' => 'coords', 'type' => 'vector3', 'description' => 'Zone center coordinates'],
|
||||
['name' => 'size', 'type' => 'vector3', 'description' => 'Zone size (length, width, height)'],
|
||||
['name' => 'rotation', 'type' => 'number', 'description' => 'Zone rotation'],
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
['name' => 'zoneOptions', 'type' => 'table', 'description' => 'Zone configuration'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Zone ID'],
|
||||
'lua_example' => "local id = exports.ox_target:addBoxZone('garage', vector3(215.0, -809.0, 30.7), vector3(5.0, 10.0, 3.0), 0, {\n {\n name = 'vehicles',\n icon = 'fas fa-car',\n label = 'Garage',\n onSelect = function()\n print('Opening garage')\n end\n }\n}, {})",
|
||||
'js_example' => "const id = exports.ox_target.addBoxZone('garage', [215.0, -809.0, 30.7], [5.0, 10.0, 3.0], 0, [\n {\n name: 'vehicles',\n icon: 'fas fa-car',\n label: 'Garage',\n onSelect: () => {\n console.log('Opening garage');\n }\n }\n], {});",
|
||||
],
|
||||
'addPolyZone' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Add a polygon zone with target options',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'name', 'type' => 'string', 'description' => 'Unique zone name'],
|
||||
['name' => 'points', 'type' => 'table', 'description' => 'Array of vector2 points'],
|
||||
['name' => 'options', 'type' => 'table', 'description' => 'Array of target options'],
|
||||
['name' => 'zoneOptions', 'type' => 'table', 'description' => 'Zone configuration'],
|
||||
],
|
||||
'returns' => ['type' => 'number', 'description' => 'Zone ID'],
|
||||
'lua_example' => "local id = exports.ox_target:addPolyZone('parking', {\n vector2(200.0, -800.0),\n vector2(220.0, -800.0),\n vector2(220.0, -820.0),\n vector2(200.0, -820.0)\n}, {\n {\n name = 'park',\n icon = 'fas fa-parking',\n label = 'Park Vehicle',\n onSelect = function()\n print('Parking vehicle')\n end\n }\n}, {})",
|
||||
'js_example' => "const id = exports.ox_target.addPolyZone('parking', [\n [200.0, -800.0],\n [220.0, -800.0],\n [220.0, -820.0],\n [200.0, -820.0]\n], [\n {\n name: 'park',\n icon: 'fas fa-parking',\n label: 'Park Vehicle',\n onSelect: () => {\n console.log('Parking vehicle');\n }\n }\n], {});",
|
||||
],
|
||||
'removeZone' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Remove a zone by ID',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'id', 'type' => 'number', 'description' => 'Zone ID to remove'],
|
||||
],
|
||||
'returns' => ['type' => 'void', 'description' => 'No return value'],
|
||||
'lua_example' => 'exports.ox_target:removeZone(zoneId)',
|
||||
'js_example' => 'exports.ox_target.removeZone(zoneId);',
|
||||
],
|
||||
'zoneExists' => [
|
||||
'namespace' => 'Client',
|
||||
'description' => 'Check if a zone exists by name',
|
||||
'side' => 'client',
|
||||
'parameters' => [
|
||||
['name' => 'name', 'type' => 'string', 'description' => 'Zone name'],
|
||||
],
|
||||
'returns' => ['type' => 'boolean', 'description' => 'true if zone exists'],
|
||||
'lua_example' => "local exists = exports.ox_target:zoneExists('bank_atm')\nif exists then\n print('Zone exists')\nend",
|
||||
'js_example' => "const exists = exports.ox_target.zoneExists('bank_atm');\nif (exists) {\n console.log('Zone exists');\n}",
|
||||
],
|
||||
];
|
||||
|
||||
$nameLower = strtolower($name);
|
||||
|
||||
foreach ($functions as $functionName => $functionData) {
|
||||
if (strtolower($functionName) === $nameLower) {
|
||||
return array_merge(['name' => $functionName], $functionData);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format function info.
|
||||
*/
|
||||
protected function formatFunctionInfo(array $function, string $language): string
|
||||
{
|
||||
return view('mcp.cox.cox-function', [
|
||||
'function' => $function,
|
||||
'language' => $language,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'function_name' => $schema
|
||||
->string()
|
||||
->description('The name of the ox_target client function to look up (e.g., "addSphereZone", "addGlobalVehicle", "addModel")')
|
||||
->required(),
|
||||
'language' => $schema
|
||||
->string()
|
||||
->enum(['lua', 'js'])
|
||||
->description('The scripting language for code examples')
|
||||
->default('lua'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,500 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\QBCore;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Get a complete list of all 58 documented QBCore resources with brief descriptions and categories.')]
|
||||
class GetQBCoreResourceList extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$category = $request->get('category');
|
||||
$resources = $this->getAllResources($category);
|
||||
|
||||
return Response::text($this->formatResourceList($resources));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all QBCore resources, optionally filtered by category.
|
||||
*/
|
||||
protected function getAllResources(?string $category = null): array
|
||||
{
|
||||
$allResources = [
|
||||
// Admin & Management
|
||||
'qb-adminmenu' => [
|
||||
'name' => 'qb-adminmenu',
|
||||
'title' => 'Admin Menu',
|
||||
'category' => 'Admin & Management',
|
||||
'description' => 'Admin panel for server management with player controls, moderation, warnings, and coordinate tools',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-adminmenu',
|
||||
],
|
||||
|
||||
// Jobs
|
||||
'qb-ambulancejob' => [
|
||||
'name' => 'qb-ambulancejob',
|
||||
'title' => 'Ambulance Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Medical job with hospital check-in, damage/bleeding system, and patient revival mechanics',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-ambulancejob',
|
||||
],
|
||||
'qb-busjob' => [
|
||||
'name' => 'qb-busjob',
|
||||
'title' => 'Bus Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Public transportation job for bus drivers with route and payment system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-busjob',
|
||||
],
|
||||
'qb-garbagejob' => [
|
||||
'name' => 'qb-garbagejob',
|
||||
'title' => 'Garbage Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Garbage collection job with pickup routes and payment system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-garbagejob',
|
||||
],
|
||||
'qb-hotdogjob' => [
|
||||
'name' => 'qb-hotdogjob',
|
||||
'title' => 'Hot Dog Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Hot dog stand vendor job with payment system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-hotdogjob',
|
||||
],
|
||||
'qb-mechanicjob' => [
|
||||
'name' => 'qb-mechanicjob',
|
||||
'title' => 'Mechanic Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Vehicle repair and customization job with parts system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-mechanicjob',
|
||||
],
|
||||
'qb-newsjob' => [
|
||||
'name' => 'qb-newsjob',
|
||||
'title' => 'News Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'News reporter job with interviews and broadcast system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-newsjob',
|
||||
],
|
||||
'qb-policejob' => [
|
||||
'name' => 'qb-policejob',
|
||||
'title' => 'Police Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Law enforcement job with dispatch, arrest, jailing, and evidence system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-policejob',
|
||||
],
|
||||
'qb-recyclejob' => [
|
||||
'name' => 'qb-recyclejob',
|
||||
'title' => 'Recycle Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Recycling center worker job with item pickup and crafting',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-recyclejob',
|
||||
],
|
||||
'qb-taxijob' => [
|
||||
'name' => 'qb-taxijob',
|
||||
'title' => 'Taxi Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Taxi driver job with passenger pickup and payment system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-taxijob',
|
||||
],
|
||||
'qb-towjob' => [
|
||||
'name' => 'qb-towjob',
|
||||
'title' => 'Tow Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Vehicle towing service with impound and payment system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-towjob',
|
||||
],
|
||||
'qb-truckerjob' => [
|
||||
'name' => 'qb-truckerjob',
|
||||
'title' => 'Trucker Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Long-haul trucking job with delivery routes and payment',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-truckerjob',
|
||||
],
|
||||
|
||||
// Crime & Robberies
|
||||
'qb-bankrobbery' => [
|
||||
'name' => 'qb-bankrobbery',
|
||||
'title' => 'Bank Robbery',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Heist job with thermal drill, hacking, and loot system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-bankrobbery',
|
||||
],
|
||||
'qb-drugs' => [
|
||||
'name' => 'qb-drugs',
|
||||
'title' => 'Drug Dealing',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Drug production and dealing system with supply and demand',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-drugs',
|
||||
],
|
||||
'qb-houserobbery' => [
|
||||
'name' => 'qb-houserobbery',
|
||||
'title' => 'House Robbery',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Residential burglary system with lockpicking and loot',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-houserobbery',
|
||||
],
|
||||
'qb-jewelry' => [
|
||||
'name' => 'qb-jewelry',
|
||||
'title' => 'Jewelry Store Robbery',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Jewelry store heist with thermite drill and loot system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-jewelry',
|
||||
],
|
||||
'qb-storerobbery' => [
|
||||
'name' => 'qb-storerobbery',
|
||||
'title' => 'Store Robbery',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Convenience store robbery with holdup mechanics',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-storerobbery',
|
||||
],
|
||||
'qb-truckrobbery' => [
|
||||
'name' => 'qb-truckrobbery',
|
||||
'title' => 'Truck Robbery',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Armored truck heist with combat and loot mechanics',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-truckrobbery',
|
||||
],
|
||||
'qb-weed' => [
|
||||
'name' => 'qb-weed',
|
||||
'title' => 'Weed Growing',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Marijuana cultivation and harvesting system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-weed',
|
||||
],
|
||||
'qb-vineyard' => [
|
||||
'name' => 'qb-vineyard',
|
||||
'title' => 'Vineyard',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Grape harvesting and wine production system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-vineyard',
|
||||
],
|
||||
|
||||
// Housing & Interiors
|
||||
'qb-apartments' => [
|
||||
'name' => 'qb-apartments',
|
||||
'title' => 'Apartments',
|
||||
'category' => 'Housing & Interiors',
|
||||
'description' => 'Player apartment rental and management system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-apartments',
|
||||
],
|
||||
'qb-houses' => [
|
||||
'name' => 'qb-houses',
|
||||
'title' => 'Houses',
|
||||
'category' => 'Housing & Interiors',
|
||||
'description' => 'Player house ownership with storage and customization',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-houses',
|
||||
],
|
||||
'qb-interior' => [
|
||||
'name' => 'qb-interior',
|
||||
'title' => 'Interior',
|
||||
'category' => 'Housing & Interiors',
|
||||
'description' => 'Interior world system for building custom rooms',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-interior',
|
||||
],
|
||||
|
||||
// Vehicles & Transportation
|
||||
'qb-garages' => [
|
||||
'name' => 'qb-garages',
|
||||
'title' => 'Garages',
|
||||
'category' => 'Vehicles & Transportation',
|
||||
'description' => 'Vehicle parking and retrieval system with multiple garages',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-garages',
|
||||
],
|
||||
'qb-vehiclekeys' => [
|
||||
'name' => 'qb-vehiclekeys',
|
||||
'title' => 'Vehicle Keys',
|
||||
'category' => 'Vehicles & Transportation',
|
||||
'description' => 'Vehicle ownership and key distribution system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-vehiclekeys',
|
||||
],
|
||||
'qb-vehiclesales' => [
|
||||
'name' => 'qb-vehiclesales',
|
||||
'title' => 'Vehicle Sales',
|
||||
'category' => 'Vehicles & Transportation',
|
||||
'description' => 'Vehicle dealership system for buying and trading vehicles',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-vehiclesales',
|
||||
],
|
||||
'qb-vehicleshop' => [
|
||||
'name' => 'qb-vehicleshop',
|
||||
'title' => 'Vehicle Shop',
|
||||
'category' => 'Vehicles & Transportation',
|
||||
'description' => 'Show room for purchasing new vehicles',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-vehicleshop',
|
||||
],
|
||||
'qb-fuel' => [
|
||||
'name' => 'qb-fuel',
|
||||
'title' => 'Fuel System',
|
||||
'category' => 'Vehicles & Transportation',
|
||||
'description' => 'Vehicle fueling system with gas stations',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-fuel',
|
||||
],
|
||||
|
||||
// Commerce & Markets
|
||||
'qb-banking' => [
|
||||
'name' => 'qb-banking',
|
||||
'title' => 'Banking',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'Bank account system with deposits, withdrawals, and transfers',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-banking',
|
||||
],
|
||||
'qb-cityhall' => [
|
||||
'name' => 'qb-cityhall',
|
||||
'title' => 'City Hall',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'Government records and ID system for players',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-cityhall',
|
||||
],
|
||||
'qb-clothing' => [
|
||||
'name' => 'qb-clothing',
|
||||
'title' => 'Clothing Shop',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'Clothing store system for outfit customization',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-clothing',
|
||||
],
|
||||
'qb-crypto' => [
|
||||
'name' => 'qb-crypto',
|
||||
'title' => 'Cryptocurrency',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'Cryptocurrency trading platform system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-crypto',
|
||||
],
|
||||
'qb-pawnshop' => [
|
||||
'name' => 'qb-pawnshop',
|
||||
'title' => 'Pawn Shop',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'Pawn shop for selling and buying items',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-pawnshop',
|
||||
],
|
||||
'qb-shops' => [
|
||||
'name' => 'qb-shops',
|
||||
'title' => 'Shops',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'General-purpose shop system for generic stores',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-shops',
|
||||
],
|
||||
|
||||
// Player Systems
|
||||
'qb-inventory' => [
|
||||
'name' => 'qb-inventory',
|
||||
'title' => 'Inventory',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Player item inventory management system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-inventory',
|
||||
],
|
||||
'qb-management' => [
|
||||
'name' => 'qb-management',
|
||||
'title' => 'Management',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Org/faction/job management system for player hierarchies',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-management',
|
||||
],
|
||||
'qb-multicharacter' => [
|
||||
'name' => 'qb-multicharacter',
|
||||
'title' => 'Multi-Character',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Multiple character selection and management on login',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-multicharacter',
|
||||
],
|
||||
'qb-phone' => [
|
||||
'name' => 'qb-phone',
|
||||
'title' => 'Phone',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'In-game phone system with apps, messages, and calls',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-phone',
|
||||
],
|
||||
'qb-prison' => [
|
||||
'name' => 'qb-prison',
|
||||
'title' => 'Prison',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Prison system for jailed players with tasks and release',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-prison',
|
||||
],
|
||||
'qb-spawn' => [
|
||||
'name' => 'qb-spawn',
|
||||
'title' => 'Spawn',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Initial spawn location selector for new players',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-spawn',
|
||||
],
|
||||
'qb-fitbit' => [
|
||||
'name' => 'qb-fitbit',
|
||||
'title' => 'Fitbit',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Health and fitness tracking wearable device',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-fitbit',
|
||||
],
|
||||
|
||||
// UI & Interface
|
||||
'qb-hud' => [
|
||||
'name' => 'qb-hud',
|
||||
'title' => 'HUD',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'Main heads-up display for player information',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-hud',
|
||||
],
|
||||
'qb-input' => [
|
||||
'name' => 'qb-input',
|
||||
'title' => 'Input',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'Generic input dialog system for NUI popups',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-input',
|
||||
],
|
||||
'qb-loading' => [
|
||||
'name' => 'qb-loading',
|
||||
'title' => 'Loading Screen',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'Animated loading screen on server startup',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-loading',
|
||||
],
|
||||
'qb-menu' => [
|
||||
'name' => 'qb-menu',
|
||||
'title' => 'Menu',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'Simple menu UI system for player interactions',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-menu',
|
||||
],
|
||||
'qb-radialmenu' => [
|
||||
'name' => 'qb-radialmenu',
|
||||
'title' => 'Radial Menu',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'Radial/circular menu interface for quick selections',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-radialmenu',
|
||||
],
|
||||
'qb-scoreboard' => [
|
||||
'name' => 'qb-scoreboard',
|
||||
'title' => 'Scoreboard',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'Server player list and information scoreboard',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-scoreboard',
|
||||
],
|
||||
'qb-target' => [
|
||||
'name' => 'qb-target',
|
||||
'title' => 'Target System',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'NPC and object targeting system for interactions',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-target',
|
||||
],
|
||||
|
||||
// Entertainment & Activities
|
||||
'qb-diving' => [
|
||||
'name' => 'qb-diving',
|
||||
'title' => 'Diving',
|
||||
'category' => 'Entertainment & Activities',
|
||||
'description' => 'Underwater treasure hunting activity',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-diving',
|
||||
],
|
||||
'qb-lapraces' => [
|
||||
'name' => 'qb-lapraces',
|
||||
'title' => 'Lap Races',
|
||||
'category' => 'Entertainment & Activities',
|
||||
'description' => 'Racing competition system with lap tracking',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-lapraces',
|
||||
],
|
||||
'qb-minigames' => [
|
||||
'name' => 'qb-minigames',
|
||||
'title' => 'Minigames',
|
||||
'category' => 'Entertainment & Activities',
|
||||
'description' => 'Collection of minigames for lockpicking, hacking, etc.',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-minigames',
|
||||
],
|
||||
'qb-radio' => [
|
||||
'name' => 'qb-radio',
|
||||
'title' => 'Radio',
|
||||
'category' => 'Entertainment & Activities',
|
||||
'description' => 'In-vehicle or ambient radio station system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-radio',
|
||||
],
|
||||
'qb-streetraces' => [
|
||||
'name' => 'qb-streetraces',
|
||||
'title' => 'Street Races',
|
||||
'category' => 'Entertainment & Activities',
|
||||
'description' => 'Street racing event system with records',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-streetraces',
|
||||
],
|
||||
|
||||
// Utilities & Miscellaneous
|
||||
'qb-doorlock' => [
|
||||
'name' => 'qb-doorlock',
|
||||
'title' => 'Door Lock',
|
||||
'category' => 'Utilities & Miscellaneous',
|
||||
'description' => 'Door locking system with access control',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-doorlock',
|
||||
],
|
||||
'qb-scrapyard' => [
|
||||
'name' => 'qb-scrapyard',
|
||||
'title' => 'Scrap Yard',
|
||||
'category' => 'Utilities & Miscellaneous',
|
||||
'description' => 'Vehicle scrapping system for parts and money',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-scrapyard',
|
||||
],
|
||||
'qb-smallresources' => [
|
||||
'name' => 'qb-smallresources',
|
||||
'title' => 'Small Resources',
|
||||
'category' => 'Utilities & Miscellaneous',
|
||||
'description' => 'Bundle of small utility resources for various features',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-smallresources',
|
||||
],
|
||||
'qb-weapons' => [
|
||||
'name' => 'qb-weapons',
|
||||
'title' => 'Weapons',
|
||||
'category' => 'Utilities & Miscellaneous',
|
||||
'description' => 'Weapon shop and ammo purchasing system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-weapons',
|
||||
],
|
||||
'qb-weathersync' => [
|
||||
'name' => 'qb-weathersync',
|
||||
'title' => 'Weather Sync',
|
||||
'category' => 'Utilities & Miscellaneous',
|
||||
'description' => 'Server-wide weather synchronization system',
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-weathersync',
|
||||
],
|
||||
];
|
||||
|
||||
if ($category) {
|
||||
return array_filter($allResources, fn ($r) => strtolower($r['category']) === strtolower($category));
|
||||
}
|
||||
|
||||
return $allResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the resource list.
|
||||
*/
|
||||
protected function formatResourceList(array $resources): string
|
||||
{
|
||||
return view('mcp.qbcore.qbcore-resource-list', [
|
||||
'resources' => $resources,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'category' => $schema
|
||||
->string()
|
||||
->description('Optional: Filter resources by category (Admin & Management, Jobs, Crime & Robberies, Housing & Interiors, Vehicles & Transportation, Commerce & Markets, Player Systems, UI & Interface, Entertainment & Activities, Utilities & Miscellaneous)')
|
||||
->enum([
|
||||
'Admin & Management',
|
||||
'Jobs',
|
||||
'Crime & Robberies',
|
||||
'Housing & Interiors',
|
||||
'Vehicles & Transportation',
|
||||
'Commerce & Markets',
|
||||
'Player Systems',
|
||||
'UI & Interface',
|
||||
'Entertainment & Activities',
|
||||
'Utilities & Miscellaneous',
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mcp\Tools\QBCore;
|
||||
|
||||
use Illuminate\Contracts\JsonSchema\JsonSchema;
|
||||
use Laravel\Mcp\Request;
|
||||
use Laravel\Mcp\Response;
|
||||
use Laravel\Mcp\Server\Attributes\Description;
|
||||
use Laravel\Mcp\Server\Tool;
|
||||
|
||||
#[Description('Get detailed documentation for a specific QBCore resource. Returns information about configuration, commands, events, callbacks, and usage examples.')]
|
||||
class GetQBCoreResourceReference extends Tool
|
||||
{
|
||||
/**
|
||||
* Handle the tool request.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$resourceName = $request->get('resource_name');
|
||||
|
||||
$resource = $this->findResource($resourceName);
|
||||
|
||||
if (! $resource) {
|
||||
return Response::text(sprintf("QBCore resource '%s' not found. Use GetQBCoreResourceList to see all available resources.", $resourceName));
|
||||
}
|
||||
|
||||
return Response::text($this->formatResourceReference($resource));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a QBCore resource by name.
|
||||
*/
|
||||
protected function findResource(string $name): ?array
|
||||
{
|
||||
$resources = [
|
||||
'qb-adminmenu' => [
|
||||
'name' => 'qb-adminmenu',
|
||||
'title' => 'Admin Menu',
|
||||
'category' => 'Admin & Management',
|
||||
'description' => 'Admin panel for server management and player moderation.',
|
||||
'features' => ['Player Management', 'Moderation', 'Coordinate Tools', 'Announcements', 'Reports', 'Warnings'],
|
||||
'commands' => [
|
||||
'/admin' => 'Opens the admin menu',
|
||||
'/blips' => 'Toggles player blips',
|
||||
'/names' => 'Toggles player names display',
|
||||
'/coords' => 'Shows your current coordinates',
|
||||
'/maxmods' => 'Sets vehicle to max mods',
|
||||
'/noclip' => 'Toggles noclip mode',
|
||||
'/admincar' => 'Adds current vehicle to garage',
|
||||
'/announce [message]' => 'Creates an announcement',
|
||||
'/report [message]' => 'Create a report to staff',
|
||||
'/reportr [message]' => 'Replies to a user report',
|
||||
'/reporttoggle' => 'Opt in/out of receiving player reports',
|
||||
'/staffchat [message]' => 'Sends a staff-only message',
|
||||
'/warn [id] [reason]' => 'Warn a player',
|
||||
'/checkwarns [id] [opt: number]' => 'View warnings for a player',
|
||||
'/delwarn [id] [number]' => 'Delete a warning from a player',
|
||||
'/givenuifocus [id] [hasFocus] [hasCursor]' => 'Sets nuifocus state for player',
|
||||
'/setmodel [model] [id]' => 'Changes the players ped model',
|
||||
'/setspeed [opt: speed]' => 'Sets players foot speed',
|
||||
'/kickall' => 'Kick all players from server',
|
||||
'/setammo [amount] [opt: weapon]' => 'Set weapon ammo',
|
||||
'/vector2' => 'Copies vector2 to clipboard',
|
||||
'/vector3' => 'Copies vector3 to clipboard',
|
||||
'/vector4' => 'Copies vector4 to clipboard',
|
||||
'/heading' => 'Copies heading to clipboard',
|
||||
],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-adminmenu',
|
||||
],
|
||||
|
||||
'qb-ambulancejob' => [
|
||||
'name' => 'qb-ambulancejob',
|
||||
'title' => 'Ambulance Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Medical job with hospital check-in system, damage/bleeding mechanics, and patient revival.',
|
||||
'features' => ['Hospital Check-in System', 'Damage Tracking', 'Bleeding System', 'Patient Revival', 'Job Shop', 'Vehicle Spawner'],
|
||||
'commands' => [
|
||||
'/911e [message]' => 'Sends a message to EMS',
|
||||
'/status' => 'Check the status of the nearest player',
|
||||
'/heal' => 'Heals the nearest player',
|
||||
'/revivep' => 'Revives the nearest player',
|
||||
'/revive' => 'Revive yourself',
|
||||
'/setpain [opt: id]' => 'Sets the pain level',
|
||||
'/kill [opt: id]' => 'Kills the player',
|
||||
'/aheal [opt: id]' => 'Heals a player',
|
||||
],
|
||||
'items' => [
|
||||
'ifaks' => 'Relieves player stress and heals them by +10',
|
||||
'bandage' => 'Heals player by +10 and has 50% chance of removing 1 level of bleeding',
|
||||
'firstaid' => 'Completely heals closest player as long as they are in last-stand',
|
||||
'painkillers' => 'Stops bleeding temporarily but wears off over time',
|
||||
],
|
||||
'events' => [
|
||||
'hospital:server:SetDeathStatus' => 'Modify the players isdead metadata',
|
||||
'hospital:server:SetLaststandStatus' => 'Modify the players inlaststand metadata',
|
||||
'hospital:server:ambulanceAlert' => 'Send a notification to all EMTs',
|
||||
'hospital:server:RevivePlayer' => 'Revive a player for free or a fee',
|
||||
],
|
||||
'callbacks' => [
|
||||
'hospital:GetDoctors' => 'Returns the number of players online with the ambulance job',
|
||||
],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-ambulancejob',
|
||||
],
|
||||
|
||||
'qb-banking' => [
|
||||
'name' => 'qb-banking',
|
||||
'title' => 'Banking',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'Bank account system with deposits, withdrawals, and transfers between players.',
|
||||
'features' => ['Account Management', 'Money Transfer', 'Transaction History', 'ATM Withdrawals'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-banking',
|
||||
],
|
||||
|
||||
'qb-inventory' => [
|
||||
'name' => 'qb-inventory',
|
||||
'title' => 'Inventory',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Player item inventory management system with weight-based limits.',
|
||||
'features' => ['Item Management', 'Weight Limits', 'Inventory UI', 'Drop Items', 'Trade Items'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-inventory',
|
||||
],
|
||||
|
||||
'qb-phone' => [
|
||||
'name' => 'qb-phone',
|
||||
'title' => 'Phone',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'In-game phone system with apps, messages, calls, and notifications.',
|
||||
'features' => ['Messaging', 'Phone Calls', 'Apps System', 'Contacts', 'Photos', 'Radio'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-phone',
|
||||
],
|
||||
|
||||
'qb-policejob' => [
|
||||
'name' => 'qb-policejob',
|
||||
'title' => 'Police Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Law enforcement job with dispatch, arrest, jailing, and evidence system.',
|
||||
'features' => ['Dispatch System', 'Arrests', 'Jail Management', 'Evidence Collection', 'Vehicle Impound'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-policejob',
|
||||
],
|
||||
|
||||
'qb-garages' => [
|
||||
'name' => 'qb-garages',
|
||||
'title' => 'Garages',
|
||||
'category' => 'Vehicles & Transportation',
|
||||
'description' => 'Vehicle parking and retrieval system with multiple garage locations.',
|
||||
'features' => ['Multiple Garages', 'Vehicle Storage', 'Quick Parking', 'Vehicle Retrieval'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-garages',
|
||||
],
|
||||
|
||||
'qb-shops' => [
|
||||
'name' => 'qb-shops',
|
||||
'title' => 'Shops',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'General-purpose shop system for creating generic stores.',
|
||||
'features' => ['Shop Creation', 'Item Pricing', 'Purchase System', 'Multiple Locations'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-shops',
|
||||
],
|
||||
|
||||
'qb-target' => [
|
||||
'name' => 'qb-target',
|
||||
'title' => 'Target System',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'NPC and object targeting system for player interactions.',
|
||||
'features' => ['Click Targeting', 'NPC Interaction', 'Object Targeting', 'Distance Based'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-target',
|
||||
],
|
||||
|
||||
'qb-hud' => [
|
||||
'name' => 'qb-hud',
|
||||
'title' => 'HUD',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'Main heads-up display showing player information and status.',
|
||||
'features' => ['Health Display', 'Armor Display', 'Hunger/Thirst', 'Stress Level', 'Mini Map'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-hud',
|
||||
],
|
||||
|
||||
'qb-doorlock' => [
|
||||
'name' => 'qb-doorlock',
|
||||
'title' => 'Door Lock',
|
||||
'category' => 'Utilities & Miscellaneous',
|
||||
'description' => 'Door locking system with access control and permissions.',
|
||||
'features' => ['Door Locking', 'Access Control', 'Job Locks', 'Gang Locks'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-doorlock',
|
||||
],
|
||||
|
||||
'qb-mechanicjob' => [
|
||||
'name' => 'qb-mechanicjob',
|
||||
'title' => 'Mechanic Job',
|
||||
'category' => 'Jobs',
|
||||
'description' => 'Vehicle repair and customization job with parts system.',
|
||||
'features' => ['Vehicle Repair', 'Vehicle Customization', 'Parts Management', 'Customer Jobs'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-mechanicjob',
|
||||
],
|
||||
|
||||
'qb-housing' => [
|
||||
'name' => 'qb-houses',
|
||||
'title' => 'Houses',
|
||||
'category' => 'Housing & Interiors',
|
||||
'description' => 'Player house ownership with storage and customization.',
|
||||
'features' => ['House Purchase', 'House Storage', 'Furniture Customization', 'Multi-Garage'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-houses',
|
||||
],
|
||||
|
||||
'qb-prison' => [
|
||||
'name' => 'qb-prison',
|
||||
'title' => 'Prison',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Prison system for jailed players with tasks and release.',
|
||||
'features' => ['Jailing System', 'Prison Jobs', 'Release System', 'Time Tracking'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-prison',
|
||||
],
|
||||
|
||||
'qb-bankrobbery' => [
|
||||
'name' => 'qb-bankrobbery',
|
||||
'title' => 'Bank Robbery',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Heist job with thermal drill, hacking, and loot system.',
|
||||
'features' => ['Thermal Drill', 'Hacking Minigame', 'Loot System', 'Police Alerts'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-bankrobbery',
|
||||
],
|
||||
|
||||
'qb-drugs' => [
|
||||
'name' => 'qb-drugs',
|
||||
'title' => 'Drug Dealing',
|
||||
'category' => 'Crime & Robberies',
|
||||
'description' => 'Drug production and dealing system with supply and demand.',
|
||||
'features' => ['Drug Production', 'Dealing Mechanics', 'Supply/Demand', 'Dealer Routes'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-drugs',
|
||||
],
|
||||
|
||||
'qb-fuel' => [
|
||||
'name' => 'qb-fuel',
|
||||
'title' => 'Fuel System',
|
||||
'category' => 'Vehicles & Transportation',
|
||||
'description' => 'Vehicle fueling system with gas stations.',
|
||||
'features' => ['Gas Stations', 'Fuel Usage', 'Cost Calculation', 'Player Jobs'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-fuel',
|
||||
],
|
||||
|
||||
'qb-multicharacter' => [
|
||||
'name' => 'qb-multicharacter',
|
||||
'title' => 'Multi-Character',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Multiple character selection and management on login.',
|
||||
'features' => ['Character Creation', 'Character Selection', 'Character Deletion'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-multicharacter',
|
||||
],
|
||||
|
||||
'qb-clothing' => [
|
||||
'name' => 'qb-clothing',
|
||||
'title' => 'Clothing Shop',
|
||||
'category' => 'Commerce & Markets',
|
||||
'description' => 'Clothing store system for outfit customization.',
|
||||
'features' => ['Outfit Customization', 'Clothing Purchase', 'Clothing Categories'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-clothing',
|
||||
],
|
||||
|
||||
'qb-vehicleshop' => [
|
||||
'name' => 'qb-vehicleshop',
|
||||
'title' => 'Vehicle Shop',
|
||||
'category' => 'Vehicles & Transportation',
|
||||
'description' => 'Show room for purchasing new vehicles.',
|
||||
'features' => ['Vehicle Showcase', 'Vehicle Purchase', 'Test Drive'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-vehicleshop',
|
||||
],
|
||||
|
||||
'qb-input' => [
|
||||
'name' => 'qb-input',
|
||||
'title' => 'Input',
|
||||
'category' => 'UI & Interface',
|
||||
'description' => 'Generic input dialog system for NUI popups.',
|
||||
'features' => ['Text Input', 'Number Input', 'Validation', 'Custom Styling'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-input',
|
||||
],
|
||||
|
||||
'qb-manage' => [
|
||||
'name' => 'qb-management',
|
||||
'title' => 'Management',
|
||||
'category' => 'Player Systems',
|
||||
'description' => 'Org/faction/job management for player hierarchies.',
|
||||
'features' => ['Rank Management', 'Member Management', 'Permission Control'],
|
||||
'url' => 'https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-management',
|
||||
],
|
||||
];
|
||||
|
||||
// Normalize the resource name for matching
|
||||
$normalized = strtolower(str_replace(['_', ' '], '-', $name));
|
||||
// Remove any prefix variations and ensure qb- prefix
|
||||
$normalized = preg_replace('/^(qbcore[-_]?)?/i', '', $normalized);
|
||||
$normalized = 'qb-'.ltrim($normalized, 'qb-');
|
||||
|
||||
foreach ($resources as $resource) {
|
||||
if (strtolower($resource['name']) === $normalized) {
|
||||
return $resource;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the resource reference.
|
||||
*/
|
||||
protected function formatResourceReference(array $resource): string
|
||||
{
|
||||
return view('mcp.qbcore.qbcore-resource-reference', [
|
||||
'resource' => $resource,
|
||||
])->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool's input schema.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\JsonSchema\JsonSchema>
|
||||
*/
|
||||
public function schema(JsonSchema $schema): array
|
||||
{
|
||||
return [
|
||||
'resource_name' => $schema
|
||||
->string()
|
||||
->description('The name of the QBCore resource to look up (e.g., qb-ambulancejob, qb-adminmenu, qb-inventory)')
|
||||
->required(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
## QBCore Resources Directory
|
||||
|
||||
Complete list of all {{ count($resources) }} official QBCore resources. Use `GetQBCoreResourceReference` to get detailed information about specific resources.
|
||||
|
||||
@php
|
||||
$grouped = collect($resources)->groupBy('category');
|
||||
@endphp
|
||||
|
||||
@foreach($grouped as $category => $categoryResources)
|
||||
### {{ $category }}
|
||||
|
||||
| Resource | Description | Documentation |
|
||||
|----------|-------------|-----------------|
|
||||
@foreach($categoryResources as $resource)
|
||||
| **{{ $resource['title'] }}** (`{{ $resource['name'] }}`) | {{ $resource['description'] }} | [View Docs]({{ $resource['url'] }}) |
|
||||
@endforeach
|
||||
|
||||
@endforeach
|
||||
|
||||
### Quick Links
|
||||
- [QBCore Framework GitHub](https://github.com/qbcore-framework)
|
||||
- [QBCore Documentation](https://docs.qbcore.org)
|
||||
- [QBCore Discord Community](https://discord.gg/qbcore)
|
||||
|
||||
**Total Resources:** {{ count($resources) }}
|
||||
@@ -0,0 +1,64 @@
|
||||
## {{ $resource['title'] }} (`{{ $resource['name'] }}`)
|
||||
|
||||
**Category:** {!! $resource['category'] !!}
|
||||
|
||||
{{ $resource['description'] }}
|
||||
|
||||
### Overview
|
||||
|
||||
{{ $resource['description'] }}
|
||||
|
||||
@if(isset($resource['features']) && !empty($resource['features']))
|
||||
#### Key Features
|
||||
@foreach($resource['features'] as $feature)
|
||||
- {{ $feature }}
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@if(isset($resource['commands']) && !empty($resource['commands']))
|
||||
### Commands
|
||||
|
||||
@foreach($resource['commands'] as $command => $description)
|
||||
#### `{{ $command }}`
|
||||
{{ $description }}
|
||||
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@if(isset($resource['events']) && !empty($resource['events']))
|
||||
### Events
|
||||
|
||||
@foreach($resource['events'] as $event => $description)
|
||||
#### `{{ $event }}`
|
||||
{{ $description }}
|
||||
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@if(isset($resource['callbacks']) && !empty($resource['callbacks']))
|
||||
### Callbacks
|
||||
|
||||
@foreach($resource['callbacks'] as $callback => $description)
|
||||
#### `{{ $callback }}`
|
||||
{{ $description }}
|
||||
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
@if(isset($resource['items']) && !empty($resource['items']))
|
||||
### Items
|
||||
|
||||
| Item | Description |
|
||||
|------|-------------|
|
||||
@foreach($resource['items'] as $item => $description)
|
||||
| `{{ $item }}` | {{ $description }} |
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
### Documentation
|
||||
- [Resource Documentation]({{ $resource['url'] }})
|
||||
- [QBCore Framework](https://docs.qbcore.org)
|
||||
- [GitHub Repository](https://github.com/qbcore-framework)
|
||||
|
||||
**Learn More:**
|
||||
To get detailed configuration options and advanced usage, visit the [full documentation]({{ $resource['url'] }}) for this resource.
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\COX\Doorlock\Client\GetOxDoorlockClientFunction;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
it('get ox_doorlock client function returns response with content', function () {
|
||||
$tool = new GetOxDoorlockClientFunction;
|
||||
$request = new Request(['function_name' => 'getClosestDoor']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_doorlock client function handles unknown function', function () {
|
||||
$tool = new GetOxDoorlockClientFunction;
|
||||
$request = new Request(['function_name' => 'NonExistentFunction123']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('not found');
|
||||
});
|
||||
|
||||
it('get ox_doorlock client function works with pickClosestDoor', function () {
|
||||
$tool = new GetOxDoorlockClientFunction;
|
||||
$request = new Request(['function_name' => 'pickClosestDoor']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_doorlock client function works with useClosestDoor', function () {
|
||||
$tool = new GetOxDoorlockClientFunction;
|
||||
$request = new Request(['function_name' => 'useClosestDoor']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_doorlock client function supports javascript examples', function () {
|
||||
$tool = new GetOxDoorlockClientFunction;
|
||||
$request = new Request(['function_name' => 'getClosestDoor', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\COX\Doorlock\Server\GetOxDoorlockServerEvent;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
it('get ox_doorlock server event returns response with content', function () {
|
||||
$tool = new GetOxDoorlockServerEvent;
|
||||
$request = new Request(['event_name' => 'ox_doorlock:stateChanged']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_doorlock server event handles unknown event', function () {
|
||||
$tool = new GetOxDoorlockServerEvent;
|
||||
$request = new Request(['event_name' => 'NonExistentEvent123']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('not found');
|
||||
});
|
||||
|
||||
it('get ox_doorlock server event supports javascript examples', function () {
|
||||
$tool = new GetOxDoorlockServerEvent;
|
||||
$request = new Request(['event_name' => 'ox_doorlock:stateChanged', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\COX\Doorlock\Server\GetOxDoorlockServerFunction;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
it('get ox_doorlock server function returns response with content', function () {
|
||||
$tool = new GetOxDoorlockServerFunction;
|
||||
$request = new Request(['function_name' => 'getDoor']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_doorlock server function handles unknown function', function () {
|
||||
$tool = new GetOxDoorlockServerFunction;
|
||||
$request = new Request(['function_name' => 'NonExistentFunction123']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('not found');
|
||||
});
|
||||
|
||||
it('get ox_doorlock server function works with getDoorFromName', function () {
|
||||
$tool = new GetOxDoorlockServerFunction;
|
||||
$request = new Request(['function_name' => 'getDoorFromName']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_doorlock server function works with editDoor', function () {
|
||||
$tool = new GetOxDoorlockServerFunction;
|
||||
$request = new Request(['function_name' => 'editDoor']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_doorlock server function works with setDoorState', function () {
|
||||
$tool = new GetOxDoorlockServerFunction;
|
||||
$request = new Request(['function_name' => 'setDoorState']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_doorlock server function supports javascript examples', function () {
|
||||
$tool = new GetOxDoorlockServerFunction;
|
||||
$request = new Request(['function_name' => 'getDoor', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\COX\Fuel\Client\GetOxFuelClientFunction;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
it('get ox_fuel client function returns response with content', function () {
|
||||
$tool = new GetOxFuelClientFunction;
|
||||
$request = new Request(['function_name' => 'setMoneyCheck']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_fuel client function handles unknown function', function () {
|
||||
$tool = new GetOxFuelClientFunction;
|
||||
$request = new Request(['function_name' => 'NonExistentFunction123']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('not found');
|
||||
});
|
||||
|
||||
it('get ox_fuel client function supports javascript examples', function () {
|
||||
$tool = new GetOxFuelClientFunction;
|
||||
$request = new Request(['function_name' => 'setMoneyCheck', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\COX\Fuel\Server\GetOxFuelServerFunction;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
it('get ox_fuel server function returns response with content', function () {
|
||||
$tool = new GetOxFuelServerFunction;
|
||||
$request = new Request(['function_name' => 'setPaymentMethod']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_fuel server function handles unknown function', function () {
|
||||
$tool = new GetOxFuelServerFunction;
|
||||
$request = new Request(['function_name' => 'NonExistentFunction123']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('not found');
|
||||
});
|
||||
|
||||
it('get ox_fuel server function supports javascript examples', function () {
|
||||
$tool = new GetOxFuelServerFunction;
|
||||
$request = new Request(['function_name' => 'setPaymentMethod', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\COX\Target\Client\GetOxTargetClientFunction;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
it('get ox_target client function returns response with content', function () {
|
||||
$tool = new GetOxTargetClientFunction;
|
||||
$request = new Request(['function_name' => 'addSphereZone']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_target client function handles unknown function', function () {
|
||||
$tool = new GetOxTargetClientFunction;
|
||||
$request = new Request(['function_name' => 'NonExistentFunction123']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('not found');
|
||||
});
|
||||
|
||||
it('get ox_target client function works with addGlobalVehicle', function () {
|
||||
$tool = new GetOxTargetClientFunction;
|
||||
$request = new Request(['function_name' => 'addGlobalVehicle']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_target client function works with addModel', function () {
|
||||
$tool = new GetOxTargetClientFunction;
|
||||
$request = new Request(['function_name' => 'addModel']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_target client function works with addBoxZone', function () {
|
||||
$tool = new GetOxTargetClientFunction;
|
||||
$request = new Request(['function_name' => 'addBoxZone']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_target client function works with addPolyZone', function () {
|
||||
$tool = new GetOxTargetClientFunction;
|
||||
$request = new Request(['function_name' => 'addPolyZone']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_target client function works with isActive', function () {
|
||||
$tool = new GetOxTargetClientFunction;
|
||||
$request = new Request(['function_name' => 'isActive']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
|
||||
it('get ox_target client function supports javascript examples', function () {
|
||||
$tool = new GetOxTargetClientFunction;
|
||||
$request = new Request(['function_name' => 'addEntity', 'language' => 'js']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
|
||||
expect($response)->not()->toBeNull();
|
||||
expect($response->content())->not()->toBeNull();
|
||||
});
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreResourceList;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
test('GetQBCoreResourceList returns all resources', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request([]);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('QBCore Resources Directory');
|
||||
expect($content)->toContain('qb-ambulancejob');
|
||||
expect($content)->toContain('qb-adminmenu');
|
||||
expect($content)->toContain('qb-policejob');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceList contains all 58 resources', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request([]);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
// Count resource names in the response
|
||||
$resources = [
|
||||
'qb-adminmenu', 'qb-ambulancejob', 'qb-apartments', 'qb-banking', 'qb-bankrobbery',
|
||||
'qb-busjob', 'qb-cityhall', 'qb-clothing', 'qb-crypto', 'qb-diving',
|
||||
'qb-doorlock', 'qb-drugs', 'qb-fitbit', 'qb-fuel', 'qb-garages',
|
||||
'qb-garbagejob', 'qb-hotdogjob', 'qb-houserobbery', 'qb-houses', 'qb-hud',
|
||||
'qb-input', 'qb-interior', 'qb-inventory', 'qb-jewelry', 'qb-lapraces',
|
||||
'qb-loading', 'qb-management', 'qb-mechanicjob', 'qb-menu', 'qb-minigames',
|
||||
'qb-multicharacter', 'qb-newsjob', 'qb-pawnshop', 'qb-phone', 'qb-policejob',
|
||||
'qb-prison', 'qb-radialmenu', 'qb-radio', 'qb-recyclejob', 'qb-scoreboard',
|
||||
'qb-scrapyard', 'qb-shops', 'qb-smallresources', 'qb-spawn', 'qb-storerobbery',
|
||||
'qb-streetraces', 'qb-taxijob', 'qb-towjob', 'qb-target', 'qb-truckerjob',
|
||||
'qb-truckrobbery', 'qb-vehiclekeys', 'qb-vehiclesales', 'qb-vehicleshop', 'qb-vineyard',
|
||||
'qb-weapons', 'qb-weathersync', 'qb-weed',
|
||||
];
|
||||
|
||||
foreach ($resources as $resource) {
|
||||
expect($content)->toContain($resource);
|
||||
}
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceList filters by category - Jobs', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request(['category' => 'Jobs']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
// Should contain job resources
|
||||
expect($content)->toContain('qb-ambulancejob');
|
||||
expect($content)->toContain('qb-policejob');
|
||||
expect($content)->toContain('qb-mechanicjob');
|
||||
|
||||
// Should not contain non-job resources
|
||||
expect($content)->not->toContain('## Admin & Management');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceList filters by category - Crime & Robberies', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request(['category' => 'Crime & Robberies']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('qb-bankrobbery');
|
||||
expect($content)->toContain('qb-drugs');
|
||||
expect($content)->toContain('qb-weed');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceList filters by category - Admin & Management', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request(['category' => 'Admin & Management']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('qb-adminmenu');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceList filters by category - UI & Interface', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request(['category' => 'UI & Interface']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('qb-hud');
|
||||
expect($content)->toContain('qb-menu');
|
||||
expect($content)->toContain('qb-target');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceList filters by category - Housing & Interiors', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request(['category' => 'Housing & Interiors']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('qb-apartments');
|
||||
expect($content)->toContain('qb-houses');
|
||||
expect($content)->toContain('qb-interior');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceList contains documentation links', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request([]);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('https://docs.qbcore.org/qbcore-documentation/qbcore-resources/');
|
||||
expect($content)->toContain('View Docs');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceList has grouped categories', function () {
|
||||
$tool = new GetQBCoreResourceList;
|
||||
$request = new Request([]);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('### Admin');
|
||||
expect($content)->toContain('### Jobs');
|
||||
expect($content)->toContain('### Crime');
|
||||
expect($content)->toContain('### Housing');
|
||||
expect($content)->toContain('### Vehicles');
|
||||
});
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
use App\Mcp\Tools\QBCore\GetQBCoreResourceReference;
|
||||
use Laravel\Mcp\Request;
|
||||
|
||||
test('GetQBCoreResourceReference returns ambulance job details', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-ambulancejob']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('Ambulance Job');
|
||||
expect($content)->toContain('Hospital Check-in System');
|
||||
expect($content)->toContain('/heal');
|
||||
expect($content)->toContain('ifaks');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference returns admin menu details', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-adminmenu']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('Admin Menu');
|
||||
expect($content)->toContain('/admin');
|
||||
expect($content)->toContain('/blips');
|
||||
expect($content)->toContain('Player Management');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference returns hud details', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-hud']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('HUD');
|
||||
expect($content)->toContain('Health Display');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference returns inventory details', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-inventory']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('Inventory');
|
||||
expect($content)->toContain('Player Systems');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference returns phone details', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-phone']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('Phone');
|
||||
expect($content)->toContain('Messaging');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference returns police job details', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-policejob']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('Police Job');
|
||||
expect($content)->toContain('Dispatch System');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference includes documentation URL', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-adminmenu']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('https://docs.qbcore.org/qbcore-documentation/qbcore-resources/qb-adminmenu');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference not found returns helpful message', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-nonexistent']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('not found');
|
||||
expect($content)->toContain('GetQBCoreResourceList');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference handles case variations', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'QBCore-Ambulancejob']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('Ambulance Job');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference returns garages details', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-garages']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('Garages');
|
||||
expect($content)->toContain('Transportation');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference returns shops details', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-shops']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('Shops');
|
||||
expect($content)->toContain('Commerce');
|
||||
});
|
||||
|
||||
test('GetQBCoreResourceReference includes categories', function () {
|
||||
$tool = new GetQBCoreResourceReference;
|
||||
$request = new Request(['resource_name' => 'qb-target']);
|
||||
|
||||
$response = $tool->handle($request);
|
||||
$content = (string) $response->content();
|
||||
|
||||
expect($content)->toContain('UI & Interface');
|
||||
expect($content)->toContain('Target System');
|
||||
});
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user