From 75198793e28da6b972fed59f3be1d91e7f0d88cb Mon Sep 17 00:00:00 2001 From: Lemuel Date: Fri, 2 Oct 2026 15:38:29 +0200 Subject: [PATCH] docs: document package installation and MCP client usage --- CHANGELOG.md | 11 ++ README.md | 66 +++++---- changelog.xml | 12 ++ docs/CLIENT-CONNECTIONS.md | 292 +++++++++++++++++++++++++++++++++++++ docs/GETTING-STARTED.md | 197 +++++++++++++++++++++++++ 5 files changed, 549 insertions(+), 29 deletions(-) create mode 100644 docs/CLIENT-CONNECTIONS.md create mode 100644 docs/GETTING-STARTED.md diff --git a/CHANGELOG.md b/CHANGELOG.md index efed9c3..f08084b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [[[NEXT_VERSION]]] + +### Addition + +- Add package-first Joomla setup, administrator-area, token/ACL, tool, confirmed-write, JCB and recovery guidance, with linked AI and direct-client connection instructions. + +### Change + +- Lead the README with the actively maintained fourth MCP build, stable package installation, repository roles and user documentation links. + ## 1.0.6 ### Fix @@ -122,3 +132,4 @@ - External client and remote stdio ownership separated into mcp_client. Development baseline entries describe existing source, not previously published releases. Published immutable tags establish release availability. + diff --git a/README.md b/README.md index 9ec88a2..b52f805 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,66 @@ # JoomEngine MCP for Joomla -An installable PHP MCP server for Joomla 6.1–6.x, with database-defined tools, resources, prompts and actions, a native administrator application, Joomla API authentication and a shared local console runtime. Version 0.1.1 adds installed Joomla Component Builder discovery, confirmed background jobs and retained compiler artifacts. The current verification boundary is recorded in [implementation status](docs/IMPLEMENTATION.md). +The actively maintained PHP successor to the original [Joomla MCP TypeScript proof of concept](https://github.com/joomengine/joomla-mcp). This is the project's **fourth MCP build/iteration**, with expanded functionality, native Joomla administration, database-defined capabilities and Joomla Component Builder (JCB) integration. Its stable package is distributed alongside JCB and designed to work with it. “Fourth build” describes the project's evolution; release tags use their own version numbers. -**Component:** `com_joomengine_mcp` -**Namespace:** `VDM\Component\JoomEngineMcp` -**Console plugin:** `plg_console_joomengine_mcp` in [`joomengine/mcp_plugin`](https://github.com/joomengine/mcp_plugin) -**External PHP client:** `joomengine/mcp-client` in [`joomengine/mcp_client`](https://github.com/joomengine/mcp_client) +**Start with the [stable MCP package](https://github.com/joomengine/mcp_package/tags).** Install its ZIP on your Joomla site to get the component, HTTP webservices plugin and local console plugin together. Then use the independent [MCP client](https://github.com/joomengine/mcp_client) to connect an AI host or call tools directly. -## Repository boundary +## Start here -This repository owns the installable component: catalogue, administrator MVC/forms, HTTP endpoint controllers, Joomla token/ACL integration, shared API/native execution, durable state and jobs. Its locked production dependencies are committed under `admin/vendor`; Composer is a maintainer tool, never an installation step. External MCP connection code, remote stdio bridging, client documentation and client releases belong exclusively to `mcp_client`. +| Task | Guide | +| --- | --- | +| Install on an existing Joomla site; enable plugins; configure URL, token and permissions | [Getting started](docs/GETTING-STARTED.md) | +| Connect Claude, ChatGPT or another compatible AI host; use Docker or the PHP client without an AI | [Client connections](docs/CLIENT-CONNECTIONS.md) | +| Understand administrator areas and manage the catalogue | [Administrator areas](docs/GETTING-STARTED.md#use-the-administrator-areas) | +| Read tools, plan confirmed writes and inspect jobs | [First read](docs/GETTING-STARTED.md#connect-and-make-a-first-read), [write flow](docs/GETTING-STARTED.md#plan-and-confirm-writes), [jobs](docs/GETTING-STARTED.md#enable-jcb-operations-and-background-jobs) | +| Set up JCB capabilities or use the local Joomla console | [JCB setup](docs/GETTING-STARTED.md#enable-jcb-operations-and-background-jobs), [console use](docs/GETTING-STARTED.md#use-the-local-joomla-console-without-an-ai) | +| Check an installation or connection problem | [Troubleshooting](docs/GETTING-STARTED.md#troubleshooting) | -The component's outbound Joomla API transport is implemented in `admin/src/Http`. See [client separation and handoff](docs/CLIENT-HANDOFF.md). +Support requires **Joomla 6.1–6.x**, **PHP 8.3 or later**, and the PHP extensions listed in [composer.json](composer.json). Production dependencies and installation data are already included; no Composer, Node.js or build step is required on the Joomla server. -## Download and install +## How the repositories fit together -Download this repository using **Code → Download ZIP**, or download a release tag's source ZIP, and upload it in Joomla's extension installer. The source tree already contains its production PHP dependencies and installation data. No build, Composer run or repacking is required. The supported host is Joomla 6.1–6.x with PHP 8.3 or later and the extensions listed in `composer.json`. +| Repository | Role | +| --- | --- | +| [mcp_package](https://github.com/joomengine/mcp_package) | Recommended installable bundle of the three Joomla extensions below; refreshed by release builds | +| **mcp_component** (this repository) | `com_joomengine_mcp`: server, catalogue, administrator application, authentication/ACL, actions, durable plans/jobs and artifacts | +| [mcp_webservices](https://github.com/joomengine/mcp_webservices) | `plg_webservices_joomengine_mcp`: registers the authenticated HTTP endpoint | +| [mcp_plugin](https://github.com/joomengine/mcp_plugin) | `plg_console_joomengine_mcp`: direct local Joomla console commands and stdio | +| [mcp_client](https://github.com/joomengine/mcp_client) | External PHP SDK and remote stdio bridge for AI hosts and direct tool calls | +| [joomla-mcp](https://github.com/joomengine/joomla-mcp) | Original TypeScript proof of concept; new users should follow the package and guides above | -Configure the canonical site API URL and Joomla permissions under **Components → JoomEngine MCP → Options**. The authenticated MCP endpoint is `/api/index.php/v1/joomengine-mcp`, relative to the Joomla installation. HTTP route registration comes from the separate [webservices plugin](https://github.com/joomengine/mcp_webservices); local console commands come from the [console plugin](https://github.com/joomengine/mcp_plugin). Install the [combined package](https://github.com/joomengine/mcp_package) to get all three extensions together. +JCB is a separate installation. The MCP package contains its own component and plugins; the client runs on the workstation or bridge host. Remote HTTP clients do not require server shell access. -For native JCB background jobs, provide a PHP CLI executable compatible with the installed Joomla version, with `pcntl_fork`, `posix_setsid` and `proc_open` available. Select its absolute path in the component's **PHP CLI binary** setting when it differs from the automatically detected PHP executable. The web-server account must be able to launch it and write the private artifact directory outside the served Joomla tree. Worker prerequisites are checked before a write is claimed. The golden-image Dockerfile demonstrates the required CLI extension setup; ordinary Joomla API operations remain available without that job runtime. +Configure **Canonical Joomla API URL** under **Components → JoomEngine MCP → Options** with the site's HTTPS URL ending in `/api/index.php`. The authenticated MCP endpoint adds `/v1/joomengine-mcp`, preserving any Joomla subdirectory. Supply the site base URL and a native Joomla API token to `mcp_client`. See [getting started](docs/GETTING-STARTED.md) for the complete setup. -Remote AI applications can use the independent client's [Docker Compose launcher](https://github.com/joomengine/mcp_client/blob/feature/standalone-php-client/docs/DOCKER.md). Supply the HTTPS Joomla installation URL and native API token; the client discovers capabilities from this component. The console plugin is required for direct local Joomla MCP commands, while the remote client connects to the component's authenticated HTTP endpoint. +## Capabilities and authority -The combined package is built exclusively by [OctoJPack](https://github.com/octoleo/octojpack), using the fixed `.octojpack` configuration and each extension's latest tag, and published to [mcp_package](https://github.com/joomengine/mcp_package). The component version determines the package version. Run the manual **Release** workflow to freeze the changelogs, tag the component, update its own feed and hash its tagged ZIP with OctoShoom, then publish the package. The package tag automatically starts its separate feed and OctoShoom workflow in `mcp_package`. [Release instructions](docs/RELEASE.md) list the required secrets and both workflow runs. +Published database records define providers, schemas, actions, bindings, tools, resources, prompts and targets. Reviewed PHP handlers execute them; database definitions are not executable dispatch code. The administrator application manages these definitions and exposes execution, grant, audit, job and artifact metadata through **Operations**. -## Required capabilities +HTTP uses Joomla's authenticated API user and intersects component permissions, viewing-access levels, row assets and target-resource ACL. Remote stdio through the external client retains that identity. Direct local Joomla console execution is a separate trusted server track; remote requests cannot select it. Confirmed remote writes require explicit grants, reviewed plans, confirmation, idempotency and read-back. See [security](SECURITY.md). -HTTP uses Joomla's authenticated API user and intersects component permissions, viewing-access levels, row assets and target-resource ACL. Local console execution is a separate trusted-server track; remote requests cannot opt into it. Published database records define schemas, actions, bindings, tools, resources and prompts, while reviewed injected PHP handlers execute them. Database definitions are not executable dispatch code. - -JCB remains a required integration alongside Joomla core. Install and enable JCB and its native command plugin, then synchronize actual installed contracts through the administrator Operations screen or local console: +Joomla core remains usable without JCB. For JCB capabilities, install and enable JCB and its native registration plugins, then refresh definitions using **Operations → Refresh JCB definitions** or: ```bash php cli/joomla.php joomla:mcp:jcb-sync ``` -Synchronization inspects JCB-owned API routes and registered command input definitions, then persists schemas, actions, bindings and targets. It preserves administrator customization and refuses unsupported contracts instead of silently omitting them. An absent API distribution produces no invented endpoints. Ordinary MCP discovery reads the stored catalogue and does not modify it. Repeat synchronization after changing JCB or its route/command plugins. +Synchronization inspects actual installed JCB API routes and registered command definitions, persists schemas/actions/bindings/targets, preserves administrator customization and refuses unsupported contracts. It creates no invented endpoints when an API distribution is absent. Ordinary discovery reads the stored catalogue; repeat refresh after changing JCB or its registration plugins. Disabling or uninstalling a required registration plugin hides the affected operations from discovery and execution. -Synchronized definitions record their actual registration-plugin dependencies. Disabling or uninstalling that plugin hides its operations from discovery and direct execution without requiring a catalogue rewrite. Permission requests accept only currently authorized executable scopes, including installed provider scopes such as `jcb.execute`. +JCB package `get`, `init`, `pull`, `push`, `reset` and compilation are effectful operations. Plans freeze inputs, options and relevant definition/configuration fingerprints. Native background execution uses isolated PHP workers and durable principal-owned jobs; compiler archives become bounded, hash-verified artifact references. Cancellation and uncertain outcomes retain recovery evidence; cancellation does not roll back side effects. [JCB setup](docs/GETTING-STARTED.md#enable-jcb-operations-and-background-jobs) covers worker prerequisites; the [JCB contract and acceptance matrix](docs/integrations/JCB.md) records tested scenarios and native limitations. -Package `get`, `init`, `pull`, `push`, `reset` and compilation are effectful operations requiring grants, plans and confirmation. Command options and definition/configuration fingerprints are frozen during planning. Execution uses isolated PHP workers and durable principal-owned jobs. Cancellation and uncertain outcomes retain recovery evidence; cancellation does not roll back side effects. Compiler archives become bounded, hash-verified artifact references. See the [JCB contract and acceptance matrix](docs/integrations/JCB.md). +## Source, maintenance and release -Plans describe the selected native definitions, frozen option layers, repository identity, possible effects and revision fingerprints before approval. Credentials and server paths remain private. Native API validation failures retain bounded field and checkout diagnostics so clients can correct rejected input. +This repository owns the installable component, namespace `VDM\Component\JoomEngineMcp`. Its locked production dependencies are committed under `admin/vendor`; Composer is a maintainer tool. External connection code, remote stdio bridging, client documentation and releases belong to `mcp_client`, package `joomengine/mcp-client`. The server's outbound Joomla API transport lives in `admin/src/Http`. See [client separation and handoff](docs/CLIENT-HANDOFF.md). -Joomla core remains usable without JCB. Remote HTTP and stdio clients retain their authenticated Joomla user's authority, including inside background workers. Only the genuine local console creates server-owner authority. +For development or independent component maintenance, a GitHub source ZIP of a reviewed branch or release tag installs directly in Joomla. Installing this component alone does not install either plugin; use the combined package for a complete server installation. -## Current status +[OctoJPack](https://github.com/octoleo/octojpack) builds the combined package using the fixed `.octojpack` configuration and each extension's latest tag, then publishes it to `mcp_package`. The component version determines the package version. The manual **Release** workflow freezes component changelogs, creates its immutable tag, updates and hashes its own feed with OctoShoom, then publishes the package. The package tag starts its separate feed/hash workflow. [Release instructions](docs/RELEASE.md) cover workflow order and secrets. -Native administration, installed core tests, JCB synchronization and job/artifact runtime are implemented. [Implementation status](docs/IMPLEMENTATION.md) separates historical installed Joomla/JCB evidence from verification of the current source and release changes. Published tags identify component releases; package publication belongs to `joomengine/mcp_package`. +Native administration, installed core tests, JCB synchronization and job/artifact runtime are implemented. [Implementation status](docs/IMPLEMENTATION.md) separates historical installed Joomla/JCB evidence from verification of current source and releases. Package availability does not enlarge those runtime-specific verification boundaries. -The original migration source is pinned at `joomengine/joomla-mcp@2cff50f4f6b440da3c684f9995a77efad32e1a36`. It remains unchanged. Joomla 6 native contracts are authoritative; repository/MVC/XML placement follows JCB's extension-root layout. This is hand-authored JCB-aligned source, not an already imported JCB blueprint. +The original migration snapshot is pinned at `joomengine/joomla-mcp@2cff50f4f6b440da3c684f9995a77efad32e1a36`. Imported native handlers retain behavioral contracts and source attribution. Joomla 6 native contracts are authoritative; repository/MVC/XML placement follows JCB's extension-root layout. This is hand-authored JCB-aligned source, not a claim of an imported JCB blueprint. Explicitly unavailable inherited operations are recorded in [migration provenance](docs/migration/README.md). -Imported native handlers retain the original behavioural contracts and source attribution while following the JCB PHP style. The original implementation's deliberately unavailable operations remain explicit diagnostics; they are documented in the [migration provenance](docs/migration/README.md). +Before changing runtime code, read [architecture](docs/ARCHITECTURE.md), [database design](docs/DATABASE.md), [migration plan](docs/MIGRATION.md), [security](SECURITY.md) and [agent instructions](AGENTS.md). User-facing resource details include [custom fields](docs/CUSTOM-FIELDS.md) and [native Joomla API limitations](docs/testing/native-api-limitations.md). -Read [architecture](docs/ARCHITECTURE.md), [database design](docs/DATABASE.md), [migration plan](docs/MIGRATION.md), [security](SECURITY.md), and [agent instructions](AGENTS.md) before changing the runtime. +Changes are recorded in [CHANGELOG.md](CHANGELOG.md) and [changelog.xml](changelog.xml). Pending entries use `[[[NEXT_VERSION]]]`; the release workflow assigns their version. -See [CHANGELOG.md](CHANGELOG.md) for human-readable changes and [changelog.xml](changelog.xml) for Joomla's categorized changelog. Changes awaiting release use `[[[NEXT_VERSION]]]` in both files; the release workflow assigns their version. diff --git a/changelog.xml b/changelog.xml index 937d81b..4311f98 100644 --- a/changelog.xml +++ b/changelog.xml @@ -1,5 +1,16 @@ + + com_joomengine_mcp + component + [[[NEXT_VERSION]]] + + Add package-first Joomla setup, administrator-area, token/ACL, tool, confirmed-write, JCB and recovery guidance, with linked AI and direct-client connection instructions. + + + Lead the README with the actively maintained fourth MCP build, stable package installation, repository roles and user documentation links. + + com_joomengine_mcp component @@ -117,3 +128,4 @@ Development baseline; published immutable tags establish release availability. + diff --git a/docs/CLIENT-CONNECTIONS.md b/docs/CLIENT-CONNECTIONS.md new file mode 100644 index 0000000..d7dbf2b --- /dev/null +++ b/docs/CLIENT-CONNECTIONS.md @@ -0,0 +1,292 @@ +# Connect AI applications and use MCP tools directly + +First complete [Joomla installation and setup](GETTING-STARTED.md). Install the [MCP package](https://github.com/joomengine/mcp_package/tags) on the Joomla site; install the separate [MCP client](https://github.com/joomengine/mcp_client) on the computer or application that will connect to it. + +The installed component executes Joomla/JCB operations. The client discovers its tools, resources and prompts, carries the Joomla user's permissions and presents a remote Joomla server as a local stdio MCP process. It does not contain a separate tool catalogue. + +## Choose a connection + +| Your application | Connection | +| --- | --- | +| Claude Desktop, Claude Code or another application that launches local MCP processes | PHP or Docker stdio bridge below | +| MCP application with Streamable HTTP and configurable authentication headers | Connect directly to the component's HTTP endpoint | +| ChatGPT web or another remote-only connector | See [ChatGPT and remote-only chat connectors](#chatgpt-and-remote-only-chat-connectors) before configuring a URL | +| PHP application or operator using tools without an AI | [Direct SDK tool use](#use-tools-directly-without-an-ai) | + +The client is a PHP SDK and command-line bridge. The component administrator pages manage definitions and operations; they do not provide a browser chat client or a tool invocation dashboard. + +## Install the PHP client and save a site + +Use PHP 8.3+, Composer 2 and the required PHP extensions. Named-site storage requires a POSIX system with `ext-posix`; use the [environment-only connection](#environment-only-connection) on platforms without it. No Joomla installation is needed on the client computer. + +In a new directory or existing PHP project: + +```bash +composer require 'joomengine/mcp-client:^1.0' +composer check-platform-reqs +./vendor/bin/joomengine-mcp help + +export JOOMENGINE_MCP_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/joomengine-mcp" +read -r -p 'Joomla HTTPS installation base URL: ' JOOMENGINE_MCP_SITE +read -r -s -p 'Joomla API token: ' JOOMENGINE_MCP_TOKEN +printf '\n' +export JOOMENGINE_MCP_TOKEN +./vendor/bin/joomengine-mcp configure default "$JOOMENGINE_MCP_SITE" +unset JOOMENGINE_MCP_TOKEN +./vendor/bin/joomengine-mcp sites +``` + +Enter the Joomla installation base URL, including an installation subdirectory if used. Do not enter `/administrator`, `/api/index.php` or the full MCP endpoint here. The client appends `/api/index.php/v1/joomengine-mcp` itself. HTTPS must be reachable from the computer running the client and have a trusted certificate. + +`default` is the saved site alias in these examples. Credentials remain in a private configuration file, protected by ownership and mode 0600; its directory must be mode 0700. This is filesystem-protected plaintext, not encrypted storage. `JOOMENGINE_MCP_CONFIG_DIR` makes the same directory explicit for the AI launcher. + +## PHP stdio launcher + +The AI application starts the client process and communicates over stdin/stdout. From the same Composer project, this command prints a complete launcher configuration with the actual PHP, executable and configuration-directory paths; it does not print the token: + +```bash +php -r ' +$launcher = realpath("vendor/bin/joomengine-mcp"); +$directory = getenv("JOOMENGINE_MCP_CONFIG_DIR"); +if ($launcher === false || !is_string($directory) || $directory === "") { + fwrite(STDERR, "Run the installation and named-site setup first.\n"); + exit(2); +} +echo json_encode(["mcpServers" => ["joomla" => [ + "command" => PHP_BINARY, + "args" => [$launcher, "serve", "default"], + "env" => ["JOOMENGINE_MCP_CONFIG_DIR" => $directory] +]]], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR), PHP_EOL; +' +``` + +Use the printed `joomla` entry in your application's MCP settings. Applications that use separate fields need the same command, arguments and environment values; their configuration format may differ. Keep this project at the recorded path and run the AI application as the same operating-system user that saved the credentials. + +For **Claude Desktop**, open its desktop settings, select **Developer → Edit Config**, and merge the printed entry into `mcpServers` in `claude_desktop_config.json`. Preserve existing entries, save, fully quit and restart Claude, then inspect the connected server's tools. See the [official local-server guide](https://modelcontextprotocol.io/docs/develop/connect-local-servers). + +For **Claude Code**, register the saved alias from the project directory: + +```bash +claude mcp add --env "JOOMENGINE_MCP_CONFIG_DIR=$JOOMENGINE_MCP_CONFIG_DIR" --transport stdio --scope user joomla -- "$(php -r 'echo PHP_BINARY;')" "$(realpath vendor/bin/joomengine-mcp)" serve default +claude mcp list +``` + +This registers the explicit configuration directory with the launcher. Open `/mcp` inside Claude Code to inspect connection status. See the [official Claude Code MCP reference](https://code.claude.com/docs/en/mcp). + +### Environment-only connection + +Instead of saving an alias, set `JOOMENGINE_MCP_URL` to the HTTPS Joomla installation base URL and `JOOMENGINE_MCP_TOKEN` to its user's API token through the AI application's environment or secret settings. Launch the installed executable with the single argument `connect`. + +| Launcher field | Value | +| --- | --- | +| Command | Absolute path to PHP | +| Arguments | Absolute path to `vendor/bin/joomengine-mcp`, then `connect` | +| Environment | `JOOMENGINE_MCP_URL`, `JOOMENGINE_MCP_TOKEN` | + +This mode does not need POSIX credential storage. Obtain the actual paths with `php -r 'echo PHP_BINARY, PHP_EOL, realpath("vendor/bin/joomengine-mcp"), PHP_EOL;'`. Never pass the token as a command-line argument. + +## Docker stdio launcher + +Docker Engine and Compose v2 provide the PHP runtime. Clone the released client source, build it once and configure the AI application's launcher: + +```bash +git clone --branch v1.0.0 --depth 1 https://github.com/joomengine/mcp_client.git +cd mcp_client +docker compose build --pull mcp +realpath compose.yaml +``` + +| Launcher field | Value | +| --- | --- | +| Command | `docker` | +| Arguments, in order | `compose`, `--file`, the absolute `compose.yaml` path printed above, `run`, `--rm`, `--no-deps`, `-T`, `mcp` | +| Environment/secret settings | `JOOMENGINE_MCP_URL` = HTTPS Joomla base URL; `JOOMENGINE_MCP_TOKEN` = that user's Joomla API token | + +For an `mcpServers` configuration, generate the command and argument entry using PHP already inside the built image: + +```bash +docker compose run --rm --no-deps -T --entrypoint php mcp -r ' +echo json_encode(["mcpServers" => ["joomla" => [ + "command" => "docker", + "args" => ["compose", "--file", $argv[1], "run", "--rm", "--no-deps", "-T", "mcp"] +]]], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR), PHP_EOL; +' "$(realpath compose.yaml)" +``` + +Merge the printed entry and supply the two environment values through your application's environment/secret configuration. The Docker process inherits those values and forwards them to the container. Build before connecting so build output does not enter the MCP protocol. Use `run -T`, which preserves stdio, rather than `up`. The image exposes no HTTP port. For private certificate authorities and full Docker operation, see [the client Docker guide](https://github.com/joomengine/mcp_client/blob/main/docs/DOCKER.md). + +## Direct Streamable HTTP connection + +A compatible MCP application can bypass the stdio bridge: + +| Setting | Value | +| --- | --- | +| Transport | Streamable HTTP | +| URL | Joomla installation base URL followed by `/api/index.php/v1/joomengine-mcp` | +| Authentication header | `X-Joomla-Token` with the Joomla API token, or `Authorization: Bearer` followed by the token | +| Authority | The token user's Joomla API login, MCP access and action permissions | + +The webservices plugin must be enabled and the component's configured API base must match this installation. The HTTP session ID is not a credential. This server uses Joomla's static-token authentication; it does not provide an MCP OAuth authorization flow. + +## ChatGPT and remote-only chat connectors + +ChatGPT web connects to remote MCP URLs; it cannot start `joomengine-mcp serve default` on your computer. Its [official developer-mode instructions](https://developers.openai.com/api/docs/guides/developer-mode) describe streaming HTTP/SSE and OAuth, no-authentication or mixed authentication. They do not document a field for this component's `X-Joomla-Token` header. + +Consequently, the PHP/Docker launcher above is ready for local stdio applications, but is not by itself a ChatGPT web connector. A remote-only application must support Joomla's token header directly, or use a separately hosted compatibility adapter that implements the application's supported authentication and supplies the Joomla token upstream. This repository does not include that adapter or an HTTP listener for the standalone client. An OAuth-required connector also needs an OAuth-capable adapter. + +Once a compatible remote endpoint and authentication are available, enable developer mode, create a connection with that endpoint, inspect the discovered tools and select it in the conversation. Follow the provider's current instructions and workspace controls. A URL to the client repository, a Joomla administrator page, or a local stdio command cannot replace that endpoint. + +## Verify and use an AI connection + +First ask the connected agent to list available sites and capabilities using discovered read tools. With the seeded catalogue, `joomla_sites_list` accepts `{}`; use the returned site identifiers for later calls rather than guessing one. + +A useful first instruction is: “List the Joomla sites and capabilities available to this MCP connection. Show what you can read before making changes.” Then request a specific read or change. The installed definitions determine which Joomla and JCB features are available. + +Writes retain Joomla ACL and server confirmation rules. A tool may return a plan or permission request before it can execute; an AI's own approval dialog does not replace the server's grant. Follow the returned tool schemas and challenges. For long-running operations, inspect the returned job/operation identifier and status; losing a connection does not prove cancellation or rollback. + +## Use tools directly without an AI + +The same PHP client can list and invoke tools without any chatbot. After the Composer installation and named `default` site setup above, save the following as `mcp-tools.php` in that Composer project's root: + +```php + 3) +{ + fwrite(STDERR, "Usage: php mcp-tools.php [list|call] [site-alias]\n"); + exit(2); +} + +require __DIR__ . '/vendor/autoload.php'; + +$mode = $argv[1] ?? 'list'; +$alias = $argv[2] ?? 'default'; + +if (!in_array($mode, ['list', 'call'], true)) +{ + fwrite(STDERR, "Use list or call.\n"); + exit(2); +} + +$client = null; +$status = 0; + +try +{ + $directory = getenv('JOOMENGINE_MCP_CONFIG_DIR'); + $store = new SiteStore(is_string($directory) && $directory !== '' ? $directory : null); + $client = (new ClientFactory())->connect($store->connection($alias)); + $tools = []; + $cursor = null; + $seen = []; + + do + { + $page = $client->listTools($cursor); + + foreach ($page->tools as $tool) + { + $tools[$tool->name] = $tool; + } + + $cursor = $page->nextCursor; + + if ($cursor !== null) + { + if (isset($seen[$cursor]) || count($seen) >= 100) + { + throw new RuntimeException('Tool discovery did not terminate within its bound.'); + } + + $seen[$cursor] = true; + } + } + while ($cursor !== null); + + ksort($tools); + + foreach ($tools as $name => $tool) + { + echo $name, PHP_EOL; + } + + if ($mode === 'call') + { + fwrite(STDERR, "Tool name from the list: "); + $name = trim((string) fgets(STDIN)); + + if (!isset($tools[$name])) + { + throw new RuntimeException('Choose a discovered tool.'); + } + + echo json_encode($tools[$name], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES + | JSON_THROW_ON_ERROR), PHP_EOL; + fwrite(STDERR, "Arguments as one JSON object ({} if none): "); + $arguments = json_decode((string) fgets(STDIN), false, 64, JSON_THROW_ON_ERROR); + + if (!$arguments instanceof stdClass) + { + throw new RuntimeException('Arguments must be a JSON object.'); + } + + fwrite(STDERR, "Type CALL to execute this tool with these arguments: "); + + if (trim((string) fgets(STDIN)) !== 'CALL') + { + throw new RuntimeException('Call not submitted.'); + } + + $result = $client->callTool($name, get_object_vars($arguments)); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES + | JSON_THROW_ON_ERROR), PHP_EOL; + $status = $result->isError ? 1 : 0; + } +} +catch (Throwable) +{ + fwrite(STDERR, "MCP request failed or was not submitted. Check configuration, input and permissions.\n"); + $status = 1; +} +finally +{ + if ($client !== null) + { + try + { + $client->disconnect(); + } + catch (Throwable) + { + fwrite(STDERR, "MCP session cleanup failed.\n"); + $status = 1; + } + } +} + +exit($status); +``` + +Run `php mcp-tools.php` to list tools. Run `php mcp-tools.php call` to select a discovered tool, inspect its full schema, enter arguments and execute it explicitly. Start with `joomla_sites_list` and `{}`. To use another saved site alias, run `php mcp-tools.php call` followed by that alias. + +The script sends one selected tool call and prints its content, structured result and `isError` value. Its local `CALL` prompt does not grant server write permission. For writes, use the server's discovered planning, approval and apply tools in the required order. Do not repeat a write after an ambiguous network failure; read its operation state first. + +The SDK also exposes `listResources()`, `listResourceTemplates()`, `readResource()`, `listPrompts()` and `getPrompt()`; use discovered URIs, names and schemas. These capabilities can be empty on your site. See the [client PHP API](https://github.com/joomengine/mcp_client#php-api) and [server transport contract](https://github.com/joomengine/mcp_client/blob/main/docs/SERVER-CONTRACT.md). + +## Connection troubleshooting + +| Symptom | Check | +| --- | --- | +| Client waits with no ordinary output | `serve` and `connect` wait for MCP JSON-RPC; use an AI launcher or the SDK script rather than expecting a terminal menu | +| HTTP 404 | Package/webservices installation, enabled plugin, installation subdirectory and exact API route | +| HTTP 401/403 | Joomla API token, API authentication plugins, `core.login.api`, MCP access and action permissions | +| No tools, or a missing feature | Published definitions, enabled provider/extension and authenticated user's ACL; the client cannot add absent server features | +| Named-site startup failure | Same OS user, explicit configuration directory, POSIX support and private ownership/modes | +| Docker cannot reach the site | Container DNS/routing and trusted certificate; container `localhost` is the container itself | +| Timeout during a write/job | Read the resulting operation/job state before resubmitting | + +See [site setup](GETTING-STARTED.md), [write confirmations](GETTING-STARTED.md#plan-and-confirm-writes), [JCB jobs](GETTING-STARTED.md#enable-jcb-operations-and-background-jobs), [administrator operations](GETTING-STARTED.md#use-the-administrator-areas), [security](../SECURITY.md) and the [client README](https://github.com/joomengine/mcp_client). + diff --git a/docs/GETTING-STARTED.md b/docs/GETTING-STARTED.md new file mode 100644 index 0000000..f6c428d --- /dev/null +++ b/docs/GETTING-STARTED.md @@ -0,0 +1,197 @@ +# Get started on an existing Joomla site + +Install the stable [JoomEngine MCP package](https://github.com/joomengine/mcp_package/tags), configure Joomla, then connect an AI application or use the client directly. This guide covers the Joomla side; [client connections](CLIENT-CONNECTIONS.md) covers workstation installation, Claude and other stdio hosts, ChatGPT connection requirements, Docker and direct PHP tool calls. + +## Install the package + +Use **Joomla 6.1–6.x** with **PHP 8.3 or later** and the PHP extensions `curl`, `fileinfo`, `json`, `mbstring` and `sodium`. Production PHP dependencies are included in the extension ZIPs; Composer and Node.js are not installation steps on the Joomla server. + +1. Open the [package tags](https://github.com/joomengine/mcp_package/tags) and download the ZIP for the latest stable version. +2. In Joomla administrator, open **System → Install → Extensions** and upload that package ZIP. +3. Confirm the installation completed, then open **Components → JoomEngine MCP**. + +The package installs these three extensions together: + +| Extension | Repository | Purpose | +| --- | --- | --- | +| `com_joomengine_mcp` | [mcp_component](https://github.com/joomengine/mcp_component) | Server, database catalogue, administrator interface, permissions, actions, jobs and artifacts | +| `plg_webservices_joomengine_mcp` | [mcp_webservices](https://github.com/joomengine/mcp_webservices) | Authenticated HTTP endpoint | +| `plg_console_joomengine_mcp` | [mcp_plugin](https://github.com/joomengine/mcp_plugin) | Direct local Joomla console commands and stdio server | + +[Joomla Component Builder (JCB)](https://github.com/joomengine/pkg-component-builder) and the [external MCP client](https://github.com/joomengine/mcp_client) are separate installations. JCB is needed for JCB operations; Joomla core operations remain usable without it. + +The package is refreshed by the component's release build using the tagged component and plugins. Prefer a stable package tag for installation and updates. Individual repository ZIPs remain installable for development or independent extension maintenance. + +## Enable the plugins + +Open **System → Manage → Plugins**. Check these entries: + +| Plugin | Required for | +| --- | --- | +| **Web Services - JoomEngine MCP** (`webservices/joomengine_mcp`) | All remote HTTP clients and AI connections | +| **Console - JoomEngine MCP** (`console/joomengine_mcp`) | Direct commands on the Joomla server | +| **API Authentication - Web Services Joomla Token** (`api-authentication/token`) | Joomla API token authentication | +| **User - Joomla API Token** (`user/token`) | Creating and managing users' API tokens | + +The MCP plugins are enabled on a fresh installation. Updates preserve their existing enabled or disabled state, so check them after an update if a connection is unavailable. Enable the Joomla core Web Services plugins for the resources you intend to use, such as **Web Services - Content** for articles. + +The MCP plugins register routes and commands; configure the server in the **component Options**, and credentials in the **Joomla user's token profile** and **external client**. + +## Configure the component + +Open **Components → JoomEngine MCP → Options → Endpoint and limits**. + +| Setting | What to enter | +| --- | --- | +| **Canonical Joomla API URL** | The trusted HTTPS URL of this installation ending in `/api/index.php`. Include any Joomla subdirectory. | +| **Site alias** | Keep `default` initially. This is the server's site identity in tool arguments and grants. | +| **Allowed browser origins** | Only explicit origins needed by a browser client, one per line, such as `https://console.example.com`. No paths or wildcards. Non-browser clients can omit `Origin`; the site's own origin is allowed automatically. | +| **PHP CLI executable** | Leave blank for ordinary Joomla API use. For JCB background jobs, set an absolute executable path if automatic detection does not find the compatible PHP CLI. | +| **Private artifact directory** | Optional existing writable directory outside the public Joomla installation. Blank uses the system temporary directory. | +| Other limits and lifetimes | Keep the defaults initially. Indefinite grants are disabled by default. | + +For a Joomla installation at `https://example.com/joomla`, the three addresses have different purposes: + +| Address | Use | +| --- | --- | +| `https://example.com/joomla` | Site base URL supplied to `mcp_client` | +| `https://example.com/joomla/api/index.php` | Component's **Canonical Joomla API URL** | +| `https://example.com/joomla/api/index.php/v1/joomengine-mcp` | MCP Streamable HTTP endpoint | + +Save the options. The canonical HTTPS host must be reachable both by the client and by Joomla's own API forwarding. A reverse proxy must preserve the public host and forward authentication headers. Production configuration requires HTTPS; see [client connections](CLIENT-CONNECTIONS.md) for local development with a trusted certificate. + +## Create an API identity and token + +Use a Joomla account whose permissions match the work you intend to expose. + +1. In **Users**, create or select the account and its user group. The account must be active and unblocked. +2. In **User - Joomla API Token**, set **Allowed User Groups** to include that account's group. Joomla defaults this setting to Super Users; a dedicated group can be configured instead. +3. In **System → Global Configuration → Permissions**, allow that group **Web Services Login** (`core.login.api`). +4. In **JoomEngine MCP → Options → Permissions**, allow **Access the MCP endpoint** (`mcp.access`) and **Discover and execute definitions** (`mcp.execute`). +5. Grant the native Joomla permissions for the intended resource. For example, article access still follows `com_content` permissions. Also check the provider/definition **Viewing access level** and asset permissions. +6. Log in as that account and edit its own profile. If no token exists yet, save the profile and reopen it to generate one. Open **Joomla API Token**, set **Active** to **Yes** and save, then copy your own **Token**. + +Joomla only displays your own token. An administrator editing another account can reset or disable its token but cannot copy it. Configure the client with this token using the private configuration procedure in [client connections](CLIENT-CONNECTIONS.md); never commit it to a repository. + +For confirmed writes, the identity also needs **Request confirmed mutations** (`mcp.write`), the target resource's create/edit/delete permission, and **Approve requested MCP write grants** (`mcp.approve`) to approve its own permission requests. Administrator catalogue editing additionally requires native administration permissions. A grant cannot extend any Joomla permission. + +## Connect and make a first read + +Follow [client connections](CLIENT-CONNECTIONS.md) to install `mcp_client` on the workstation or bridge host and provide the **site base URL** and **API token**. The client discovers the server's tools, resources and prompts. Its configuration nickname is local to the client; an optional tool `site` argument must use the component's **Site alias**, not a different client nickname. + +Choose the connection supported by your application: + +- An AI host with local MCP stdio support can launch `joomengine-mcp serve` through its MCP server configuration. +- A host with Streamable HTTP and configurable token headers can connect to the authenticated endpoint. +- A cloud chatbot that cannot launch local commands or supply the required authentication needs a compatible bridge or adapter. Connection support depends on the host; a static Joomla token is not an OAuth login flow. +- Without an AI host, use the [direct PHP client example](CLIENT-CONNECTIONS.md#use-tools-directly-without-an-ai) or the local console below. + +Once connected, use this small discovery and read sequence. These are MCP tool names and JSON arguments, usable through an AI host or a direct client. + +| Step | Tool or MCP method | Arguments | +| --- | --- | --- | +| Discover available tools | `tools/list` | Follow `nextCursor` until all pages are read | +| Check the installation identity | `joomla_sites_list` | `{}` | +| Inspect the available catalogue | `joomla_capabilities` | `{}` | +| Find article actions | `joomla_actions_search` | `{"text":"articles"}` | +| Read the exact action contract | `joomla_action_describe` | `{"action":"content.articles.list"}` | +| Read a small article page | `joomla_content_articles_list` | `{"offset":0,"limit":5}` | + +Successful identity/capability results and an article list establish discovery and resource access. An empty article list is a valid result on a fresh site. Discovery is filtered by installed extensions, publication, viewing levels and the current user's permissions; another identity may see a different catalogue. + +Use the discovered schema for each call. Send JSON objects as objects (`{}`), preserve arrays as arrays, and use the exact action identifier returned by search. Generic `joomla_action_read` executes a discovered read action with its action-specific `input`. Inspect the action description first: some native GET operations also perform Joomla bookkeeping. + +## Use the administrator areas + +Open **Components → JoomEngine MCP** to manage what the server exposes. + +| Area | What it controls | +| --- | --- | +| **Providers** | Integrations and required extension dependencies; publication, viewing access and permissions | +| **Schemas** | Reusable JSON input and output contracts | +| **Actions** | Semantic operations, domain, effect, risk and permission scope | +| **Bindings** | Reviewed API or local CLI execution track, handler and mappings for an action | +| **Tools** | Published MCP entry points and their schema/handler configuration | +| **Resources** | Readable MCP documents identified by URI or URI template | +| **Prompts** | Administrator-defined prompt templates; the initial shipped catalogue has no prompts | +| **Targets** | Registered local console command metadata and availability | +| **Operations** | Executions, jobs, artifacts, permission grants and audit metadata; authorized recovery controls | +| **Options** | Endpoint, limits, worker settings and component permissions | + +The **Tools** screen edits definitions. Run tools through an MCP client or the local console. Read resources using MCP `resources/list` and `resources/read`; the shipped core catalogue URI is `joomla://catalog/core`. Discover published prompts using `prompts/list` and retrieve them with `prompts/get` when configured. + +Joomla **Users → Groups** and **Users → Viewing Access Levels** determine identity and visibility. Providers organize integrations, while action **Permission scope** values group write permissions; these are distinct from Joomla user groups. + +Ordinary use requires no catalogue edits. Changing a shipped definition marks it as customized; seed updates and JCB refresh preserve such changes. Unpublishing a provider or definition removes affected capabilities from discovery and execution. Definitions select registered handlers and contain data; they cannot introduce an arbitrary PHP or shell executor. See [database design](DATABASE.md) before extending the catalogue. + +In **Operations**, authorized administrators can revoke grants, request job cancellation and reconcile uncertain executions after inspecting the actual effects. Inspection needs `core.manage` and `mcp.audit`; revocation needs `mcp.grants`, and cancellation/reconciliation needs `mcp.reconcile`. Reconciliation records your assessment and releases the retained lock; it does not replay or undo the operation. + +## Plan and confirm writes + +Remote writes use a separate grant and confirmation flow: + +1. Discover and describe the write action to read its schema, permission scope and effects. +2. Optionally call `joomla_action_write_plan` with `dryRun: true` and a UUID `idempotencyKey`. This preview performs no mutation and returns no confirmation token. +3. Check `joomla_permissions_list`. If the required scope has no usable grant, call `joomla_permission_request` with that scope, a reason and duration `once` or `30-minutes`. +4. Show the returned request and exact `acknowledgement` to the operator. Call `joomla_permission_approve` with its `requestId` and the exact phrase only after the operator supplies it. +5. Call `joomla_action_write_plan`, or the discovered typed plan tool, with the reviewed input and the operation's UUID `idempotencyKey`. Inspect the returned plan, effects and expiry. +6. After confirmation, call `joomla_write_apply` with that plan's `confirmationToken`. +7. Inspect the returned verification and read back the affected record. Revoke temporary grants with `joomla_permission_revoke` when finished. + +Plans bind the identity, input, definitions and relevant state. Expired or changed plans require a fresh plan. Retain the original idempotency key and execution evidence for the same operation; creating a new key after a lost response can duplicate a write. Inspect **Operations** and any owned job before retrying an uncertain result. + +## Enable JCB operations and background jobs + +Install and enable [JCB](https://github.com/joomengine/pkg-component-builder) and its native command plugin separately. If you use JCB API operations, install/enable the JCB webservices distribution that actually supplies those routes. The MCP package contains its own component and plugins, not JCB. + +Refresh the installed definitions with **Operations → Refresh JCB definitions**, or run this from the Joomla installation root: + +```bash +php cli/joomla.php joomla:mcp:jcb-sync +``` + +Administrator refresh requires native administration permission on both `com_joomengine_mcp` and `com_componentbuilder`. Repeat it after changing JCB or its route/command plugins. Refresh inspects the actual installed contracts and preserves administrator customization. A distribution without JCB API routes yields no invented API endpoints; disabling a registration plugin makes its affected operations unavailable. + +Package `get`, `init`, `pull`, `push`, `reset` and compilation have effects. Discover their current schemas and scopes, then use the grant, plan and confirmation flow. Do not treat package `get` as a normal read. + +For background operations, the server needs a compatible PHP CLI with `pcntl_fork`, `posix_setsid` and `proc_open` available. The web-server account must be able to launch it and write private artifact storage. Restricted shared hosting can still use ordinary Joomla API operations when these worker facilities are unavailable. + +An accepted background execution returns a job reference, not proof that compilation or a repository operation has finished. Use `joomla_job_status` with the returned `jobId`; list retained output with `joomla_job_artifacts` and read bounded chunks with `joomla_job_artifact_read`. Preserve the returned size and SHA-256 verification when assembling downloads. Jobs and artifacts remain owned by the requesting identity. + +Use `joomla_job_cancel` to request cancellation. Queued cancellation prevents execution; running cancellation may leave partial effects. `joomla_job_redispatch` applies only to never-started queued jobs using the existing claim. Inspect uncertain/partial results before further writes. See [JCB contracts and current acceptance boundaries](integrations/JCB.md) for native limitations and tested scenarios. + +## Use the local Joomla console without an AI + +With server shell access, run these from the Joomla installation root: + +```bash +php cli/joomla.php joomla:mcp:self-test +php cli/joomla.php joomla:mcp:describe +php cli/joomla.php joomla:mcp:cli-inventory +``` + +Execute a read through the component's local dispatch interface: + +```bash +php cli/joomla.php joomla:mcp:dispatch --input=- --format=json <<'JSON' +{"protocol":"joomla-mcp/1","id":"system-check","action":"system.info","input":{}} +JSON +``` + +For a local MCP stdio host, use `php cli/joomla.php joomla:mcp:serve`. That process waits for MCP messages on stdin. This is direct trusted server access; the external client's remote stdio bridge retains the API user's permissions and does not acquire local console authority. + +## Troubleshooting + +| Symptom | Check | +| --- | --- | +| Installation rejected | Joomla/PHP versions, required PHP extensions and that the ZIP is the package tag download | +| HTTP 404 at the MCP endpoint | Package/component installed, **Web Services - JoomEngine MCP** enabled, correct subdirectory and proxy routing | +| HTTP 401 / token rejected | Both Joomla token plugins enabled, allowed user group, active account and token, `core.login.api`, and token headers forwarded | +| HTTP 403 / denied or missing capability | Canonical host, explicit browser Origin, `mcp.access`/`mcp.execute`, viewing levels, row/provider assets, target-resource ACL and required extension plugins | +| Endpoint not configured / HTTP 503 | Save **Canonical Joomla API URL**, ending in `/api/index.php` | +| AI host cannot connect | Supported transport/authentication, client logs and [host connection requirements](CLIENT-CONNECTIONS.md) | +| JCB actions absent | JCB and its registration plugins enabled; refresh definitions after installation/update | +| Background worker unavailable | Compatible CLI executable, process/pcntl/POSIX support, launch permissions and private storage; leave optional fields blank for API-only use | +| Lost write response / uncertain execution | Inspect owned job and **Operations → Executions** before retrying; record inspected effects through authorized reconciliation | + +For resource-specific behavior, read [custom fields](CUSTOM-FIELDS.md), [native Joomla API limitations](testing/native-api-limitations.md), [implementation evidence](IMPLEMENTATION.md) and [security](../SECURITY.md).