Docusaurus

This commit is contained in:
Pascal Birchler 2025-04-05 13:05:18 +02:00
parent 6534d863e2
commit ea7b71dfe3
No known key found for this signature in database
GPG key ID: 0DECE73DD74E8B2F
24 changed files with 18641 additions and 0 deletions

20
.gitignore vendored Normal file
View file

@ -0,0 +1,20 @@
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

41
README.md Normal file
View file

@ -0,0 +1,41 @@
# Website

This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.

### Installation

```
$ yarn
```

### Local Development

```
$ yarn start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

### Build

```
$ yarn build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

### Deployment

Using SSH:

```
$ USE_SSH=true yarn deploy
```

Not using SSH:

```
$ GIT_USER=<Your GitHub username> yarn deploy
```

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.

44
docs/index.md Normal file
View file

@ -0,0 +1,44 @@
---
sidebar_position: 1
---

# Introduction

This projected originally kicked off during the [CloudFest Hackathon 2025](https://hackathon.cloudfest.com/project/wp-cli-mcp-host/) to implement the [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) in the WordPress ecosystem, specifically integrating it with WP-CLI.

The core innovation is transforming WordPress into an MCP Server and WP-CLI into an MCP Host through a new package, enabling direct AI interactions with WordPress installations during development. This approach provides developers with powerful AI capabilities without requiring a live site or REST API endpoints.

**WordPress MCP Server Layer:**

1. Implementation of MCP Server interfaces in WordPress
2. Resource providers for posts, pages, media, and other WordPress content types
3. Tool definitions for common WordPress actions (content creation, media handling)
4. Context providers for WordPress configuration and site state

**WP-CLI MCP Host Package:**

1. MCP Host implementation within WP-CLI framework
2. New command namespace for AI operations
3. Integration with (local and remote) LLM providers
4. Transport layer for local WordPress communication

You can think of MCP as the "USB port for LLMs", a standard way for LLMs to interact with any third-party system using things like function calling.

While the Hackathon project focused on WP-CLI, the _MCP Server_ is usage-agnostic and can also be exposed via HTTP.

The _MCP Host_, gets information (such as list of available tools) from the server and passes it on to the LLM (e.g. Gemini).

## Contributors

Original CloudFest Hackathon Contributors:

- Pascal Birchler - [@swissspidy](https://github.com/swissspidy)
- Jan-Willem Oostendorp - [@janw-me](https://github.com/janw-me)
- Joost de Valk - [@jdevalk](https://github.com/jdevalk)
- Marco Chiesi - [@marcochiesi](https://github.com/marcochiesi)
- Matt Biscay - [@skyminds](https://github.com/skyminds)
- Moritz Bappert - [@moritzbappert](https://github.com/moritzbappert)
- James Hunt - [@thetwopct](https://github.com/thetwopct)
- Tome Pajkovski - [@tomepajk](https://github.com/tomepajk)
- David Mosterd - [@davidmosterd](https://github.com/davidmosterd)
- Milana Cap - [@zzap](https://github.com/zzap)

View file

@ -0,0 +1,7 @@
{
"label": "WordPress MCP Server",
"position": 3,
"link": {
"type": "generated-index"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,106 @@
# Reference

## `Server` class

The `Server` class is a core component of the MCP for WordPress implementation and is a small wrapper around the [MCP PHP SDK](https://github.com/logiscape/mcp-sdk-php).

This class provides:

- Tool registration (`register_tool()`)
- Resource registration (`register_resource()`)
- JSON-RPC request handling (`handle_message()`)

### Examples

Register a Tool

```PHP
$server->register_tool(
[
'name' => 'calculate_total',
'description' => 'Calculate the total amount'
'callable' => function( $params ) {
return $params['price'] * $params['quantity'];
},
'inputSchema' => [
'properties' => [
'price' => [ 'type' => 'integer' ],
'quantity' => [ 'type' => 'integer' ]
],
],
]
);
```


## `RouteInformation` class

The `RouteInformation` class encapsulates metadata about a WordPress REST API route. It provides methods to determine route characteristics, REST method type, and controller details.

This class is used to:

- Identify REST route types (`singular`/`list`, `GET`/`POST`/`DELETE`, etc.).
- Validate and process REST controller callbacks.
- Generate sanitized route names for MCP registration.

### Methods

| Name | Return Type | Description |
|----------------------------------------------------------|-------------|-------------------------------------------------------------|
| `RouteInformation::__construct($route, $method, $title)` | `void` | Initializes the class with a REST route, method, and title. |
| `RouteInformation::get_name()` | `string` | Get a tool name for the route. |
| `RouteInformation::get_description()` | `string` | Get a human-friendly description. |

## `RestApi` class

The `RestApi` class is responsible for mapping WordPress REST API endpoints into MCP tools. It does this by:

- Extracting route details from the REST API.
- Generating input schemas from REST arguments.
- Creating AI tools dynamically based on route metadata.

This enables seamless AI-driven interactions with the WordPress REST API.

### Methods

| Name | Return Type | Description |
|--------------------------------------------------------------------|-------------|-------------------------------------------------------|
| `RestApi::args_to_schema( $args )` | `array` | Converts REST API arguments into a structured schema. |
| `RestApi::sanitize_type( $type )` | `string` | Maps input types to standard schema types. |
| `RestApi::get_tools()` | `array` | Registers REST API endpoints as AI tools in MCP. |
| `RestApi::rest_callable( $inputs, $route, $method_name, $server )` | `array` | Executes a REST API call dynamically. |

## `MediaManager` class

The `MediaManager` class provides a static method to upload a media file to the WordPress Media Library. It:

- Copies a file into the WordPress uploads directory.
- Registers the file as a WordPress media attachment.
- Generates and updates attachment metadata.

This class is useful for automated media uploads within WP-CLI or AI-powered workflows.

### Methods

| Name | Return Type | Description |
|--------------------------------------------------------|-------------|------------------------------------------------------------------|
| `MediaManager::upload_to_media_library( $media_path )` | `int` | Uploads a media file to WordPress and returns its attachment ID. |

## `ImageTools` class

The `ImageTools` class provides AI-powered image generation functionality within WP-CLI.
It:

- Integrates AI-based image generation tools.
- Registers the tool in the system for easy access.
- Uses a client to fetch AI-generated images.

This class is used to dynamically generate images based on user prompts.

### Methods

| Name | Return Type | Description |
|---------------------------------------|-------------|----------------------------------------------|
| `ImageTools::__construct( $client )` | `void` | Initializes ImageTools with an AI client. |
| `ImageTools::get_tools()` | `array` | Returns a list of available AI tools. |
| `ImageTools::image_generation_tool()` | `Tool` | Creates an AI-powered image generation tool. |

View file

@ -0,0 +1,8 @@
{
"label": "WP-CLI",
"position": 2,
"link": {
"type": "generated-index",
"description": "WP-CLI Usage"
}
}

125
docs/wp-cli/commands.md Normal file
View file

@ -0,0 +1,125 @@
# Commands

This package implements the following commands:

### wp ai

AI prompt.

~~~
wp ai <prompt> [--skip-wordpress]
~~~

**OPTIONS**

```
<prompt>
AI prompt.

[--skip-wordpress]
Run command without loading WordPress. (Not implemented yet)
```

**EXAMPLES**

```
# Get data from WordPress
$ wp ai "What are the titles of my last three posts?"
- Hello world
- My awesome post
- Another post

# Interact with multiple MCP servers.
$ wp ai "Take file foo.txt and create a new blog post from it"
Success: Blog post created.
```


### wp mcp server list

Lists available MCP servers.

~~~
wp mcp server list [--format=<format>]
~~~

**OPTIONS**

```
[--format=<format>]
Render output in a particular format.
---
default: table
options:
- table
- csv
- json
- count
---
```

**EXAMPLES**

```
# Greet the world.
$ wp mcp server list
Success: Hello World!

# Greet the world.
$ wp ai "create 10 test posts about swiss recipes and include generated featured images"
Success: Hello World!
```


### wp mcp server add

Add a new MCP server to the list

~~~
wp mcp server add <name> <server>
~~~

**OPTIONS**

```
<name>
Name for referencing the server later

<server>
Server command or URL.
```

**EXAMPLES**

```
# Add server from URL.
$ wp mcp server add "server-github" "https://github.com/mcp"
Success: Server added.

# Add server with command to execute
$ wp mcp server add "server-filesystem" "npx -y @modelcontextprotocol/server-filesystem /my/allowed/folder/"
Success: Server added.
```

### wp mcp server remove

Remove a new MCP server from the list

~~~
wp mcp server remove <name>
~~~

**OPTIONS**

```
<name>
Name of the server to remove
```

**EXAMPLES**

```
# Remove server.
$ wp mcp server remove "server-filesystem"
Success: Server removed.
```

View file

@ -0,0 +1,15 @@
---
sidebar_position: 1
---

# Installation

Installing this package requires WP-CLI v2.11 or greater. Update to the latest stable release with `wp cli update`.

Tip: for better on support of the latest PHP versions, use the v2.12 nightly build with `wp cli update --nightly`.

To install the latest development version of this package, use the following command instead:

```bash
wp package install mcp-wp/ai-command:dev-main
```

View file

@ -0,0 +1,11 @@
# Prompts cookbook

## Content creation

```
wp ai "Create 10 posts about Pokemon, each post describing a generation 1 pokemon, with the title being the name of the pokemon and the category Pokemon"
```

```
wp ai "Get the last 5 posts and summarize them in 1 summary - then create a post with the title 'Summary of my last 5 posts' with that summary as content"
```

30
docs/wp-cli/reference.md Normal file
View file

@ -0,0 +1,30 @@
# Reference

## `AiCommand` class

The `AiCommand` class registers CLI command for WP-CLI. It is a WP-CLI command handler designed to integrate AI capabilities within WordPress. It connects AI-driven services with WP-CLI using the MCP (Multi-Client Processor) architecture, allowing AI models to:

- Access resources (e.g., WordPress posts, users, products).
- Call AI-powered tools (e.g., image generation, event lookup).
- Execute AI-generated functions dynamically.

### Methods

| Name | Return Type | Description |
|--------------------------------------------|-------------|---------------------------------------------------|
| `AiCommand::__invoke()` | `void` | Executes AI-driven WP-CLI commands. |
| `AiCommand::register_tools( $server )` | `void` | Registers AI-powered tools in MCP. |
| `AiCommand::register_resources( $server )` | `void` | Registers data resources (e.g., users, products). |

## `Client` class

The `Client` class is a core component of the MCP for WordPress implementation and is a small wrapper around the [MCP PHP SDK](https://github.com/logiscape/mcp-sdk-php).

It allows connecting to different MCP servers via local commands, PHP, or HTTP.

### Methods

| Name | Return Type | Description |
|-------------------------|-----------------|--------------------------------------------------------|
| `Client::__construct()` | | Constructor |
| `Client::connect()` | `ClientSession` | Connects to the server and returns a session instance. |

112
docusaurus.config.ts Normal file
View file

@ -0,0 +1,112 @@
import {themes as prismThemes} from 'prism-react-renderer';
import type {Config} from '@docusaurus/types';
import type * as Preset from '@docusaurus/preset-classic';

// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)

const config: Config = {
title: 'MCP for WordPress',
tagline: 'Enabling AI-Powered WordPress Development and Usage',
favicon: 'img/favicon.ico',

// Set the production url of your site here
url: 'https://mcp-wp.github.io',
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '/',

// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: 'mcp-wp', // Usually your GitHub org/user name.
projectName: 'mcp-wp.github.io', // Usually your repo name.

trailingSlash: false,

onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',

// Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you
// may want to replace "en" with "zh-Hans".
i18n: {
defaultLocale: 'en',
locales: ['en'],
},

presets: [
[
'classic',
{
docs: {
sidebarPath: './sidebars.ts',
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl:
'https://github.com/mcp-wp/mcp-wp.github.io/tree/main',
},
theme: {
customCss: './src/css/custom.css',
},
} satisfies Preset.Options,
],
],

themeConfig: {
// Replace with your project's social card
image: 'img/docusaurus-social-card.jpg',
navbar: {
title: 'MCP for WordPress',
logo: {
alt: 'MCP for WordPress',
src: 'img/logo.jpeg',
},
items: [
{
type: 'docSidebar',
sidebarId: 'docsSidebar',
position: 'left',
label: 'Docs',
},
{
href: 'https://github.com/mcp-wp',
label: 'GitHub',
position: 'right',
},
],
},
footer: {
style: 'dark',
links: [
{
title: 'Docs',
items: [
{
label: 'Docs',
to: '/docs',
},
],
},
{
title: 'More',
items: [
{
label: 'Blog',
to: 'https://pascalbirchler.com',
},
{
label: 'GitHub',
href: 'https://github.com/mcp-wp',
},
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} MCP for WordPress contributors.`,
},
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
},
} satisfies Preset.ThemeConfig,
};

export default config;

17922
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

47
package.json Normal file
View file

@ -0,0 +1,47 @@
{
"name": "mcp-wp",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/tsconfig": "3.7.0",
"@docusaurus/types": "3.7.0",
"typescript": "~5.6.2"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 3 chrome version",
"last 3 firefox version",
"last 5 safari version"
]
},
"engines": {
"node": ">=18.0"
}
}

33
sidebars.ts Normal file
View file

@ -0,0 +1,33 @@
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';

// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)

/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation

The sidebars can be generated from the filesystem, or explicitly defined here.

Create as many sidebars as you want.
*/
const sidebars: SidebarsConfig = {
// By default, Docusaurus generates a sidebar from the docs folder structure
docsSidebar: [{type: 'autogenerated', dirName: '.'}],

// But you can create a sidebar manually
/*
tutorialSidebar: [
'intro',
'hello',
{
type: 'category',
label: 'Tutorial',
items: ['tutorial-basics/create-a-document'],
},
],
*/
};

export default sidebars;

30
src/css/custom.css Normal file
View file

@ -0,0 +1,30 @@
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/

/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #3858e9;
--ifm-color-primary-dark: #3858e9;
--ifm-color-primary-darker: #213fd4;
--ifm-color-primary-darkest: #1d35b4;
--ifm-color-primary-light: #c7d1ff;
--ifm-color-primary-lighter: #eff2ff;
--ifm-color-primary-lightest: #ffffff;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
}

/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme='dark'] {
--ifm-color-primary: #979aa1;
--ifm-color-primary-dark: #979aa1;
--ifm-color-primary-darker: #656a71;
--ifm-color-primary-darkest: #40464d;
--ifm-color-primary-light: #d9d9d9;
--ifm-color-primary-lighter: #f6f6f6;
--ifm-color-primary-lightest: #ffffff;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
}

View file

@ -0,0 +1,30 @@
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/

.heroBanner {
padding: 4rem 0;
text-align: center;
position: relative;
overflow: hidden;
}

@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
}

.buttons {
display: flex;
align-items: center;
justify-content: center;
}

.main {
padding: 2rem;
display: flex;
align-items: center;
justify-content: center;
}

45
src/pages/index.tsx Normal file
View file

@ -0,0 +1,45 @@
import type {ReactNode} from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import Heading from '@theme/Heading';

import styles from './index.module.css';

function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<Heading as="h1" className="hero__title">
{siteConfig.title}
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs">
Learn more
</Link>
</div>
</div>
</header>
);
}

export default function Home(): ReactNode {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={`${siteConfig.title}`}
description="Bringing the Model Context Protocol to WordPress and WP-CLI">
<HomepageHeader />
<main className={styles.main}>
<p>
Enable AI-powered WordPress development by implementing a WordPress MCP server and leveraging it through <a href="https://wp-cli.org/">WP-CLI</a>.
</p>
</main>
</Layout>
);
}

View file

@ -0,0 +1,7 @@
---
title: Markdown page example
---

# Markdown page example

You don't need React to write simple standalone pages.

0
static/.nojekyll Normal file
View file

BIN
static/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

BIN
static/img/logo.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

8
tsconfig.json Normal file
View file

@ -0,0 +1,8 @@
{
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@docusaurus/tsconfig",
"compilerOptions": {
"baseUrl": "."
},
"exclude": [".docusaurus", "build"]
}