.claude/skills/klytos-mcp-tools/SKILL.md
Guide for adding MCP (Model Context Protocol) tools to Klytos CMS — the PRIMARY interface for AI control. Use when registering new MCP tools, handling tool calls, extending the MCP API, understanding tool annotations, or building AI-controllable features. Everything added to Klytos must be configurable via MCP.
npx skillsauth add joseconti/klytos Klytos MCP ToolsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Everything added to Klytos MUST be configurable via MCP. MCP is the PRIMARY interface of this AI-First CMS. The admin panel is secondary. If a feature cannot be controlled by an AI via MCP, it is incomplete.
Use this reference whenever you need to:
Plugins register MCP tools using three hooks:
klytos_add_filter('mcp.tools_list', function (array $tools): array {
$tools[] = [
'name' => 'my_plugin_do_something',
'description' => 'Does something useful. Describe clearly what the tool does so the AI knows when to use it.',
'inputSchema' => [
'type' => 'object',
'properties' => [
'param1' => [
'type' => 'string',
'description' => 'First parameter — be descriptive.',
],
'param2' => [
'type' => 'integer',
'description' => 'Second parameter.',
],
'status' => [
'type' => 'string',
'enum' => ['active', 'inactive'],
'description' => 'Filter by status.',
],
],
'required' => ['param1'],
],
'annotations' => [
'title' => 'Do Something',
'readOnlyHint' => false,
'destructiveHint' => false,
'idempotentHint' => false,
'openWorldHint' => false,
],
];
return $tools;
});
klytos_add_filter('mcp.handle_tool', function (mixed $result, string $toolName, array $params): mixed {
if ($toolName !== 'my_plugin_do_something') {
return $result; // Not our tool — pass through
}
try {
// 1. Sanitize inputs
$param1 = klytos_sanitize_text($params['param1'] ?? '');
$param2 = klytos_sanitize_int($params['param2'] ?? 0);
// 2. Validate
if ($param1 === '') {
throw new \InvalidArgumentException('param1 is required');
}
// 3. Execute logic
$data = doSomethingUseful($param1, $param2);
// 4. Return success response
return [
'content' => [
['type' => 'text', 'text' => json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)],
],
'isError' => false,
];
} catch (\Exception $e) {
// 5. Return error response
return [
'content' => [
['type' => 'text', 'text' => 'Error: ' . $e->getMessage()],
],
'isError' => true,
];
}
}, 10);
{
"id": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"mcp_tools": ["my_plugin_do_something"]
}
For core tools, use the ToolRegistry directly:
// In core/mcp/tools/my-feature-tools.php
$registry->register(
'klytos_my_feature', // Tool name
'Does something in the core.', // Description
[ // Schema properties
'param1' => ['type' => 'string', 'description' => 'Parameter description'],
],
function (array $params, App $app): mixed { // Handler
$result = $app->getMyManager()->doSomething($params['param1']);
return ['success' => true, 'data' => $result];
},
[ // Annotations
'readOnlyHint' => false,
'destructiveHint' => false,
'idempotentHint' => true,
],
['param1'] // Required properties
);
| Annotation | Type | Description |
|---|---|---|
| readOnlyHint | bool | true = does NOT modify state (safe to call anytime) |
| destructiveHint | bool | true = may delete or irreversibly modify data |
| idempotentHint | bool | true = safe to call multiple times with same params |
| openWorldHint | bool | true = accepts arbitrary/unknown input parameters |
// List tools (read-only, safe)
['readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true]
// Create tool (modifies state, not idempotent)
['readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => false]
// Delete tool (destructive)
['readOnlyHint' => false, 'destructiveHint' => true, 'idempotentHint' => true]
// Update tool (modifies state, idempotent)
['readOnlyHint' => false, 'destructiveHint' => false, 'idempotentHint' => true]
All MCP tools MUST return this format:
// Success
[
'content' => [
['type' => 'text', 'text' => 'Human-readable result or JSON data'],
],
'isError' => false,
]
// Error
[
'content' => [
['type' => 'text', 'text' => 'Error: description of what went wrong'],
],
'isError' => true,
]
For structured data, return JSON in the text field:
return [
'content' => [
['type' => 'text', 'text' => json_encode([
'success' => true,
'items' => $items,
'total' => count($items),
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)],
],
'isError' => false,
];
| Hook | Type | Arguments | Description |
|---|---|---|---|
| mcp.tools_list | filter | array $tools | Register new tools |
| mcp.handle_tool | filter | mixed $result, string $toolName, array $params | Handle tool calls |
| mcp.tool_response | filter | array $response, string $toolName | Modify responses before sending |
| mcp.tool_called | action | string $toolName, array $params | Audit: tool was called |
klytos_create_page — Create new page/custom post type entryklytos_update_page — Update existing pageklytos_delete_page — Delete page by slugklytos_get_page — Get page by slugklytos_list_pages — List pages with filtersklytos_get_site_config — Get global configklytos_set_site_config — Update global configklytos_get_theme — Get theme configurationklytos_set_theme — Update full themeklytos_set_colors — Update color paletteklytos_set_fonts — Update fontsklytos_set_layout — Update layout settingsklytos_list_users — List usersklytos_create_user — Create userklytos_update_user — Update userklytos_reset_user_password — Reset passwordklytos_force_logout_user — Force logoutklytos_create_post_type — Create post typeklytos_update_post_type — Update post typeklytos_delete_post_type — Delete post typeklytos_get_post_type / klytos_list_post_typesklytos_add_taxonomy / klytos_update_taxonomy / klytos_delete_taxonomyklytos_add_term / klytos_update_term / klytos_delete_term / klytos_list_termsklytos_get_field_types — List 27 field typesklytos_add_custom_field / klytos_update_custom_field / klytos_remove_custom_fieldklytos_set_bulk_field_values — Set values on entriesklytos_get_menu / klytos_set_menuklytos_add_menu_item / klytos_remove_menu_itemklytos_create_page_template / klytos_get_page_template / klytos_list_page_templatesklytos_add_block_to_template / klytos_remove_block_from_templateklytos_create_block / klytos_update_block / klytos_get_block / klytos_list_blocks / klytos_delete_blockklytos_upload_asset / klytos_list_assets / klytos_delete_assetklytos_build_site — Build entire static siteklytos_build_page — Build single pageklytos_preview_page — Live previewklytos_get_build_statusklytos_schedule_single_action / klytos_schedule_recurring_actionklytos_cancel_scheduled_action / klytos_list_scheduled_actions / klytos_get_scheduler_statusklytos_create_webhook / klytos_list_webhooks / klytos_delete_webhookklytos_list_webhook_events / klytos_test_webhookklytos_get_consent_config / klytos_set_consent_config — Read/update consent configurationklytos_list_consent_declarations / klytos_add_consent_declaration / klytos_delete_consent_declaration — Manage plugin cookie/script declarationsklytos_get_consent_audit — Full audit report grouped by categoryklytos_list_versions / klytos_get_version / klytos_restore_version / klytos_diff_versionsklytos_list_plugins / klytos_activate_plugin / klytos_deactivate_pluginklytos_get_analytics / klytos_get_top_pagesklytos_list_tasks / klytos_get_task / klytos_create_task / klytos_update_task / klytos_complete_taskklytos_generate_image / klytos_list_ai_imagesklytos_ai_get_config / klytos_ai_list_providers / klytos_ai_get_usageklytos_list_guides / klytos_get_guide<?php
// plugins/analytics-export/init.php
declare(strict_types=1);
// 1. Register MCP tool
klytos_add_filter('mcp.tools_list', function (array $tools): array {
$tools[] = [
'name' => 'analytics_export_generate',
'description' => 'Generate an analytics export for a date range. Returns CSV data.',
'inputSchema' => [
'type' => 'object',
'properties' => [
'start_date' => ['type' => 'string', 'description' => 'Start date (YYYY-MM-DD)'],
'end_date' => ['type' => 'string', 'description' => 'End date (YYYY-MM-DD)'],
'format' => ['type' => 'string', 'enum' => ['csv', 'json'], 'description' => 'Export format'],
],
'required' => ['start_date', 'end_date'],
],
'annotations' => ['readOnlyHint' => true, 'title' => 'Export Analytics'],
];
return $tools;
});
// 2. Handle tool calls
klytos_add_filter('mcp.handle_tool', function (mixed $result, string $name, array $params): mixed {
if ($name !== 'analytics_export_generate') return $result;
$startDate = klytos_sanitize_text($params['start_date'] ?? '');
$endDate = klytos_sanitize_text($params['end_date'] ?? '');
$format = $params['format'] ?? 'json';
// Fetch analytics data
$analytics = klytos_app()->getAnalyticsManager();
$data = $analytics->getRange($startDate, $endDate);
if ($format === 'csv') {
$csv = "date,page,views\n";
foreach ($data as $row) {
$csv .= "{$row['date']},{$row['page']},{$row['views']}\n";
}
return ['content' => [['type' => 'text', 'text' => $csv]], 'isError' => false];
}
return [
'content' => [['type' => 'text', 'text' => json_encode($data, JSON_PRETTY_PRINT)]],
'isError' => false,
];
}, 10);
// 3. Also add admin page (secondary interface)
klytos_add_filter('admin.sidebar_items', function (array $items): array {
$items[] = [
'id' => 'analytics-export',
'title' => 'Export Analytics',
'url' => klytos_admin_url('plugins/analytics-export/admin/export.php'),
'icon' => 'fa-solid fa-file-export',
'position' => 61,
'section' => 'system',
'capability' => 'analytics.view',
];
return $items;
});
klytos-plugin.json under mcp_toolscore/mcp/tool-registry.phpcore/mcp/server.phpcore/mcp/json-rpc.phpcore/mcp/token-auth.phpcore/mcp/rate-limiter.phpcore/mcp/tools/ (21 files)development
Guide for working with dates, times, and timezones in Klytos CMS. Use when formatting dates, converting timezones, scheduling actions with timestamps, displaying local time, working with UTC storage, building timezone selectors, or using any klytos_date/klytos_gmdate/klytos_timezone functions.
tools
Guide for developing and extending the Klytos web terminal. Use when modifying terminal commands, adding terminal commands from plugins, fixing terminal bugs, extending the pseudo-terminal, working with TerminalExecutor class, registering custom permissions, adding custom category labels, or managing terminal UI and security.
development
--- name: klytos-site-builder description: Guide for building a complete website from scratch with Klytos CMS. Use when creating a new site, configuring a site after installation, setting up design/content/SEO/navigation, or when the user pastes the post-install prompt. Covers 9 phases: discovery, design reference, global config, theme, content structure, templates, content creation, additional features, and launch. --- # Klytos Site Builder ## Overview The Site Builder is a conversational AI
development
Use when creating or editing page content in Klytos CMS. Ensures every page has proper SEO structure, HTML semantics, meta tags, structured data, accessibility for maximum search engine visibility. Apply when writing page titles, descriptions, content, headings, images, internal links, JSON-LD schema, or following the SEO checklist before publishing pages.