#!/usr/bin/env node
/**
* Proto-Blocks MCP Server
* The Ultimate MCP Server for guiding LLMs on creating Proto-Blocks
*
* This server provides comprehensive tools and resources for creating
* WordPress Gutenberg blocks using PHP templates with Proto-Blocks.
*/
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
// Import knowledge modules
import { getBasicsKnowledge } from './knowledge/basics.js';
import { getFieldsKnowledge, getFieldDetails } from './knowledge/fields.js';
import { getControlsKnowledge, getControlDetails } from './knowledge/controls.js';
import { getTemplatesKnowledge } from './knowledge/templates.js';
import { getStylingKnowledge } from './knowledge/styling.js';
import { getInteractivityKnowledge } from './knowledge/interactivity.js';
import { getExamplesKnowledge, getExampleByComplexity } from './knowledge/examples.js';
import { getTroubleshootingKnowledge, getTroubleshootingByCategory } from './knowledge/troubleshooting.js';
import { getBlockJsonSchema, generateBlockJson } from './knowledge/schema.js';
import { getQuickReference } from './knowledge/quick-reference.js';
import { getRepeatersKnowledge, getRepeaterDetails } from './knowledge/repeaters.js';
// Create server instance
const server = new Server(
{
name: 'proto-blocks-mcp',
version: '1.0.0',
},
{
capabilities: {
tools: {},
resources: {},
},
}
);
// Define all available tools
const TOOLS = [
{
name: 'proto_blocks_get_started',
description: `Get comprehensive introduction to Proto-Blocks. Returns everything needed to understand what Proto-Blocks is, how it works, requirements, installation, and the fundamental concepts. This is the FIRST tool to use when starting with Proto-Blocks.`,
inputSchema: {
type: 'object',
properties: {},
required: [],
},
},
{
name: 'proto_blocks_quick_reference',
description: `Get a quick reference card with the most commonly used patterns, field types, control types, and template syntax. Perfect for experienced users who need a quick refresher.`,
inputSchema: {
type: 'object',
properties: {},
required: [],
},
},
{
name: 'proto_blocks_field_types',
description: `Get detailed documentation for Proto-Blocks field types. Fields are the editable regions in your block templates (text, wysiwyg, image, link, repeater, innerblocks). Use fieldType parameter to get details for a specific field, or omit for complete field documentation.`,
inputSchema: {
type: 'object',
properties: {
fieldType: {
type: 'string',
description: 'Optional: Specific field type to get details for (text, wysiwyg, image, link, repeater, innerblocks)',
enum: ['text', 'wysiwyg', 'image', 'link', 'repeater', 'innerblocks'],
},
},
required: [],
},
},
{
name: 'proto_blocks_control_types',
description: `Get detailed documentation for Proto-Blocks control types. Controls appear in the WordPress block inspector panel sidebar (text, textarea, select, toggle, checkbox, range, number, color, color-palette, radio, image). Use controlType parameter to get details for a specific control.`,
inputSchema: {
type: 'object',
properties: {
controlType: {
type: 'string',
description: 'Optional: Specific control type to get details for',
enum: ['text', 'textarea', 'select', 'toggle', 'checkbox', 'range', 'number', 'color', 'color-palette', 'radio', 'image'],
},
},
required: [],
},
},
{
name: 'proto_blocks_templates',
description: `Get comprehensive documentation on creating PHP templates for Proto-Blocks. Covers template structure, available variables ($attributes, $content, $block), data-proto-* attributes, best practices, and common patterns.`,
inputSchema: {
type: 'object',
properties: {},
required: [],
},
},
{
name: 'proto_blocks_styling',
description: `Get documentation on styling Proto-Blocks. Covers three approaches: Vanilla CSS, Tailwind CSS inline utilities, and Tailwind with @apply. Includes theming, responsive design, and editor style considerations.`,
inputSchema: {
type: 'object',
properties: {
approach: {
type: 'string',
description: 'Optional: Specific styling approach to focus on',
enum: ['vanilla-css', 'tailwind-inline', 'tailwind-apply'],
},
},
required: [],
},
},
{
name: 'proto_blocks_interactivity',
description: `Get documentation on adding interactivity to Proto-Blocks. Covers plain JavaScript, ES Modules, and the WordPress Interactivity API. Includes state management patterns and event handling.`,
inputSchema: {
type: 'object',
properties: {
approach: {
type: 'string',
description: 'Optional: Specific interactivity approach',
enum: ['plain-js', 'es-modules', 'interactivity-api'],
},
},
required: [],
},
},
{
name: 'proto_blocks_examples',
description: `Get complete, working examples of Proto-Blocks at different complexity levels. Each example includes full block.json, template.php, and optional style.css/view.js files. Use complexity parameter to filter examples.`,
inputSchema: {
type: 'object',
properties: {
complexity: {
type: 'string',
description: 'Filter examples by complexity level',
enum: ['basic', 'intermediate', 'advanced', 'expert'],
},
},
required: [],
},
},
{
name: 'proto_blocks_troubleshooting',
description: `Get troubleshooting guidance for common Proto-Blocks issues. Covers block registration, template rendering, field binding, styling, interactivity, and performance issues. Use category parameter to filter by issue type.`,
inputSchema: {
type: 'object',
properties: {
category: {
type: 'string',
description: 'Optional: Filter troubleshooting by category',
enum: ['registration', 'templates', 'fields', 'controls', 'styling', 'interactivity', 'performance', 'editor'],
},
},
required: [],
},
},
{
name: 'proto_blocks_repeaters',
description: `Get comprehensive documentation on Proto-Blocks repeaters. Repeaters are an ADVANCED feature for creating dynamic lists and collections of items. Covers basic to complex implementations including nested repeaters, repeaters with Interactivity API, styling patterns, and performance optimization. Use topic parameter to get specific information.`,
inputSchema: {
type: 'object',
properties: {
topic: {
type: 'string',
description: 'Optional: Specific repeater topic to focus on',
enum: ['basics', 'nested', 'interactivity', 'patterns', 'troubleshooting'],
},
},
required: [],
},
},
{
name: 'proto_blocks_schema',
description: `Get the complete block.json schema for Proto-Blocks. Shows all available options, their types, defaults, and descriptions. Essential reference for configuring blocks correctly.`,
inputSchema: {
type: 'object',
properties: {},
required: [],
},
},
{
name: 'proto_blocks_generate',
description: `Generate a complete Proto-Blocks block based on requirements. Provide a description of the block you want to create and get back the full block.json, template.php, and style.css files ready to use.`,
inputSchema: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Block name (e.g., "my-card", "hero-section")',
},
title: {
type: 'string',
description: 'Human-readable block title',
},
description: {
type: 'string',
description: 'Detailed description of what the block should do and contain',
},
useTailwind: {
type: 'boolean',
description: 'Whether to use Tailwind CSS (default: false)',
},
useInteractivity: {
type: 'boolean',
description: 'Whether to use WordPress Interactivity API (default: false)',
},
},
required: ['name', 'title', 'description'],
},
},
];
// Handle list tools request
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools: TOOLS };
});
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'proto_blocks_get_started':
return {
content: [{ type: 'text', text: getBasicsKnowledge() }],
};
case 'proto_blocks_quick_reference':
return {
content: [{ type: 'text', text: getQuickReference() }],
};
case 'proto_blocks_field_types':
if (args?.fieldType) {
return {
content: [{ type: 'text', text: getFieldDetails(args.fieldType) }],
};
}
return {
content: [{ type: 'text', text: getFieldsKnowledge() }],
};
case 'proto_blocks_control_types':
if (args?.controlType) {
return {
content: [{ type: 'text', text: getControlDetails(args.controlType) }],
};
}
return {
content: [{ type: 'text', text: getControlsKnowledge() }],
};
case 'proto_blocks_templates':
return {
content: [{ type: 'text', text: getTemplatesKnowledge() }],
};
case 'proto_blocks_styling':
return {
content: [{ type: 'text', text: getStylingKnowledge(args?.approach) }],
};
case 'proto_blocks_interactivity':
return {
content: [{ type: 'text', text: getInteractivityKnowledge(args?.approach) }],
};
case 'proto_blocks_examples':
if (args?.complexity) {
return {
content: [{ type: 'text', text: getExampleByComplexity(args.complexity) }],
};
}
return {
content: [{ type: 'text', text: getExamplesKnowledge() }],
};
case 'proto_blocks_troubleshooting':
if (args?.category) {
return {
content: [{ type: 'text', text: getTroubleshootingByCategory(args.category) }],
};
}
return {
content: [{ type: 'text', text: getTroubleshootingKnowledge() }],
};
case 'proto_blocks_repeaters':
if (args?.topic) {
return {
content: [{ type: 'text', text: getRepeaterDetails(args.topic) }],
};
}
return {
content: [{ type: 'text', text: getRepeatersKnowledge() }],
};
case 'proto_blocks_schema':
return {
content: [{ type: 'text', text: getBlockJsonSchema() }],
};
case 'proto_blocks_generate':
if (!args?.name || !args?.title || !args?.description) {
return {
content: [{ type: 'text', text: 'Error: name, title, and description are required parameters.' }],
isError: true,
};
}
return {
content: [{ type: 'text', text: generateBlockJson(args) }],
};
default:
return {
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
isError: true,
};
}
} catch (error) {
return {
content: [{ type: 'text', text: `Error: ${error.message}` }],
isError: true,
};
}
});
// Define resources
const RESOURCES = [
{
uri: 'proto-blocks://documentation/complete',
name: 'Complete Proto-Blocks Documentation',
description: 'Full documentation for Proto-Blocks including all features, fields, controls, and examples',
mimeType: 'text/markdown',
},
{
uri: 'proto-blocks://examples/all',
name: 'All Proto-Blocks Examples',
description: 'Complete collection of Proto-Blocks examples from basic to expert level',
mimeType: 'text/markdown',
},
];
// Handle list resources request
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return { resources: RESOURCES };
});
// Handle read resource request
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;
if (uri === 'proto-blocks://documentation/complete') {
const fullDocs = [
getBasicsKnowledge(),
getFieldsKnowledge(),
getControlsKnowledge(),
getTemplatesKnowledge(),
getStylingKnowledge(),
getInteractivityKnowledge(),
getRepeatersKnowledge(),
getBlockJsonSchema(),
getTroubleshootingKnowledge(),
].join('\n\n---\n\n');
return {
contents: [
{
uri,
mimeType: 'text/markdown',
text: fullDocs,
},
],
};
}
if (uri === 'proto-blocks://examples/all') {
return {
contents: [
{
uri,
mimeType: 'text/markdown',
text: getExamplesKnowledge(),
},
],
};
}
throw new Error(`Unknown resource: ${uri}`);
});
// Start the server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Proto-Blocks MCP Server running on stdio');
}
main().catch((error) => {
console.error('Fatal error:', error);
process.exit(1);
});