MCP Tools for Developers
How LaraDashboard MCP tools are registered, authorized, and extended by modules using McpFilterHook.
MCP Tools for Developers
LaraDashboard exposes admin capabilities to AI agents through MCP tools. Core ships foundational tools; modules register additional tools without modifying core code.
Architecture
AI Client (Cursor / Claude)
↓
POST /mcp
↓
LaraDashboardServer
↓
McpRegistryService ← McpFilterHook::TOOLS
↓
Tool classes (core + modules)
Core never imports module classes directly. Modules hook into App\Enums\Hooks\McpFilterHook.
Core tools (22)
Registered in app/Mcp/Tools/ and loaded by McpRegistryService:
| Tool | Ability (typical) | Permission |
|---|---|---|
get-daily-briefing |
mcp:briefing.read |
dashboard.view |
list-posts / get-post |
mcp:posts.read |
post.view |
create-post |
mcp:posts.write |
post.create |
update-post |
mcp:posts.update |
post.edit |
delete-post |
mcp:posts.delete |
post.delete |
list-terms / assign-post-terms |
mcp:terms.read |
term.view |
list-media |
mcp:media.read |
media.view |
upload-media / attach-featured-image |
mcp:media.write |
media.create |
generate-seo-meta |
mcp:posts.update |
post.edit |
list-email-templates / get-email-template |
mcp:email_templates.read |
email_template.view |
send-email |
mcp:email.send |
email_template.view |
clear-cache |
mcp:ops.cache |
settings.edit |
list-logs / get-log-tail |
mcp:ops.logs.read |
settings.edit |
get-site-health |
mcp:ops.health.read |
dashboard.view |
list-mcp-tools |
mcp:access |
(token base ability) |
list-modules |
mcp:modules.read |
module.view |
activate-module / deactivate-module |
mcp:modules.activate / deactivate |
module.activate / module.deactivate |
Module examples: CRM (16 tools), DocForge (4), CustomForm (2).
Available hooks
| Hook | Purpose |
|---|---|
McpFilterHook::TOOLS |
Register tool class names |
McpFilterHook::ABILITY_PERMISSION_MAP |
Map mcp:* abilities to Spatie permissions |
McpFilterHook::TOKEN_ABILITIES |
Final token ability list per user |
McpFilterHook::BRIEFING_PROVIDERS |
Daily briefing sections |
McpFilterHook::TOOL_DEFINITIONS |
Mutate settings UI metadata |
Register tools from a module
In your module bootstrap service (see CRM or DocForge for examples):
use App\Enums\Hooks\McpFilterHook;
use App\Support\Facades\Hook;
Hook::addFilter(McpFilterHook::TOOLS, [$this, 'registerMcpTools']);
Hook::addFilter(McpFilterHook::ABILITY_PERMISSION_MAP, [$this, 'registerMcpAbilities']);
public function registerMcpTools(array $tools): array
{
return array_merge($tools, [
\Modules\YourModule\Mcp\Tools\YourTool::class,
]);
}
public function registerMcpAbilities(array $map): array
{
return array_merge($map, [
'mcp:yourmodule.read' => 'yourmodule.view',
]);
}
Authoring a tool class
Place tools in modules/YourModule/app/Mcp/Tools/.
#[Name('your-tool')]
#[Description('What this tool does.')]
#[McpToolMeta(ability: 'mcp:yourmodule.read', permission: 'yourmodule.view', group: 'Your Module')]
class YourTool extends Tool
{
use InteractsWithMcpAuthorization;
public function shouldRegister(): bool
{
return Schema::hasTable('your_table');
}
public function handle(Request $request): Response
{
if ($response = $this->authorizeMcpAbility('mcp:yourmodule.read', 'yourmodule.view')) {
return $response;
}
// Validate, call a service, return JSON
return Response::json(['ok' => true]);
}
public function schema(JsonSchema $schema): array
{
return [
'id' => $schema->integer()->description('Record ID.')->required(),
];
}
}
Conventions
- Use kebab-case tool names (
list-contacts,search-docs). - Put business logic in services, not in the tool class.
- Use
shouldRegister()when the tool depends on optional tables. - Return structured JSON via
Response::json()or errors viaResponse::error(). - Reuse
InteractsWithMcpAuthorizationfor token + permission checks.
Token generation
McpTokenService builds tokens with:
- Base ability
mcp:access - Every
mcp:*ability whose mapped permission the user holds
Users generate tokens at Settings → MCP. Tokens are named laradashboard-mcp.
Server instructions
Update instructions in App\Mcp\Servers\LaraDashboardServer when you add major workflows so agents know which tools to chain.
Testing
Feature-test tools with:
LaraDashboardServer::actingAs($user, 'sanctum')
->tool(YourTool::class, ['id' => 1])
->assertOk();
Grant the user the mapped permission and create an MCP token via McpTokenService.