Skip to content

MCP Providers For Developers ​

QUIQQER packages can add their own MCP tools and skills. Use tools when a module provides domain behavior that should be callable by AI clients, for example content helpers, product tools, import helpers, search tools, or project-specific automation.

Use skills when a package should provide reusable Markdown instructions for AI clients, for example package development workflows, content rules, operational checks, or project conventions.

MCP tools are part of a package API. Keep them small, permission-checked, and explicit about the project and language they operate on.

Tool Provider Requirements ​

A package that provides MCP tools needs:

  • quiqqer/ai-mcp installed in the target system
  • a provider class that implements QUI\AI\MCP\ProviderInterface
  • a provider entry in package.xml
  • permissions that control who may use the tools
  • clear tool names, descriptions, and input schemas

Register The Provider ​

Register the MCP provider in package.xml:

xml
<quiqqer>
    <package>
        <provider>
            <mcp src="\Vendor\Package\MCP\Provider"/>
        </provider>
    </package>
</quiqqer>

During setup, QUIQQER imports package providers. The MCP server discovers installed MCP providers and registers their tools.

Provider Class ​

Create a provider class that implements ProviderInterface:

php
<?php

namespace Vendor\Package\MCP;

use Mcp\Server\Builder;
use QUI\AI\MCP\ProviderInterface;
use QUI\AI\MCP\Server;
use QUI\AI\MCP\ToolHelper;
use QUI\Permissions\Permission;
use Throwable;

final class Provider implements ProviderInterface
{
    public function register(Builder $serverBuilder): void
    {
        if (!$this->canUseTools()) {
            return;
        }

        $serverBuilder->addTool(
            function (string $project, string $lang): mixed {
                try {
                    Permission::checkPermission(
                        'vendor.package.mcp',
                        Server::getRequestUser()
                    );

                    return [
                        'project' => $project,
                        'lang' => $lang
                    ];
                } catch (Throwable $Exception) {
                    return ToolHelper::parseExceptionToResult($Exception);
                }
            },
            name: 'vendor_package_example',
            description: 'Example MCP tool for this package.',
            inputSchema: [
                'type' => 'object',
                'additionalProperties' => false,
                'required' => ['project', 'lang'],
                'properties' => [
                    'project' => [
                        'type' => 'string',
                        'description' => 'QUIQQER project name.'
                    ],
                    'lang' => [
                        'type' => 'string',
                        'description' => 'Project language.'
                    ]
                ]
            ]
        );
    }

    private function canUseTools(): bool
    {
        try {
            Permission::checkPermission(
                'vendor.package.mcp',
                Server::getRequestUser()
            );

            return true;
        } catch (Throwable) {
            return false;
        }
    }
}

For larger packages, create separate tool classes and let the provider register them. This keeps permissions, parsing, and test coverage easier to maintain.

Permissions ​

Every tool provider should define a package-specific MCP permission. Use a dedicated permission instead of relying only on a broad administrator role.

Example permissions.xml:

xml
<?xml version="1.0" encoding="UTF-8"?>
<quiqqer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="https://www.quiqqer.com/docs/schemas/2.x/permissions.xsd">
    <permissions>
        <permission name="vendor.package.mcp" type="bool">
            <defaultvalue>0</defaultvalue>
            <rootPermission>1</rootPermission>
            <everyonePermission>0</everyonePermission>
            <guestPermission>0</guestPermission>
        </permission>
    </permissions>
</quiqqer>

The tool should also check normal domain permissions. For example, a tool that updates a site should check the relevant project and site edit permissions. A tool that changes media should check media permissions.

Tool Design Rules ​

  • Use stable, namespaced tool names such as vendor_package_action.
  • Write descriptions for AI clients, not for PHP developers.
  • Require project and lang when the tool acts on project data.
  • Use strict input schemas with additionalProperties: false.
  • Return structured arrays instead of formatted strings.
  • Catch exceptions and return MCP-compatible error results.
  • Never expose secrets, raw credentials, or internal paths.
  • Prefer separate read and write tools over one broad tool that does everything.
  • Keep delete and publish operations behind explicit permissions.

Project And Language Inputs ​

For project data, include project and language parameters explicitly:

json
{
  "project": "default",
  "lang": "en",
  "siteId": 12
}

Do not infer the language from the prompt. AI clients can be wrong about the target language; tools should require the context when content can be changed.

Cache And Setup ​

Provider registration is imported through package setup. Run setup after adding or changing the MCP provider declaration in package.xml:

shell
./console setup

If the MCP tool list does not change after setup, clear the relevant caches and retry the client connection.

Testing Checklist ​

Before publishing a package MCP provider:

  • The provider is registered in package.xml.
  • The provider class exists and implements ProviderInterface.
  • Every tool checks a package-specific MCP permission.
  • Write tools check normal domain permissions.
  • Tool names are stable and namespaced.
  • Inputs are documented through inputSchema.
  • Project tools require project and language context.
  • The tool works with a restricted AI account, not only with a superuser.

Skill Providers ​

Since quiqqer/ai-mcp 1.5.0, packages can register Skill Providers with <mcpSkill src="..." />. A Skill Provider registers Markdown skill files that AI clients can discover and load through the MCP endpoint.

Minimal provider:

php
<?php

namespace Vendor\Package;

use QUI\AI\MCP\Skill\SkillProviderInterface;
use QUI\AI\MCP\Skill\SkillRepository;

final class MySkillProvider implements SkillProviderInterface
{
    public function registerSkills(SkillRepository $repository): void
    {
        $repository->addFromMarkdownFile(
            dirname(__DIR__, 1) . '/skills/developer/vendor_package_developer.md'
        );
    }
}

Register it in package.xml:

xml
<provider>
    <mcpSkill src="\Vendor\Package\MySkillProvider" />
</provider>

Skill files use the path format skills/<category>/<skill_name>.md and require frontmatter fields name, description, and category.

See MCP Skills for the complete file format, supported categories, exposed resources, and tool fallbacks.

Released under GPL-3.0-or-later.