-
-
Notifications
You must be signed in to change notification settings - Fork 26
MCP Server
Akeeba Panopticon includes an optional Model Context Protocol (MCP) server. It lets AI agents and chatbots — such as Claude Code, Claude Desktop, Codex, Cursor, VS Code, or JetBrains IDEs — drive Panopticon using the same operations as the JSON API, so you can ask an assistant things like “which of my sites have pending updates?” or “refresh site 12 and tell me if its backup is healthy”.
Important
Minimum version: the MCP server is available in Akeeba Panopticon 2.2.0 and later.
The MCP server is disabled by default. You must enable it, and every request must authenticate with a Panopticon API token. An AI agent can only ever see and do what the token's owner could do through the JSON API.
- Log into Panopticon as a Super User.
- Go to System Configuration → Security → MCP Server.
- Turn on Enable the MCP server and save.
You can also enable it from the command line or by setting the mcp_enabled configuration option to true (see
Configuration parameters).
While the server is disabled the endpoint responds as if it does not exist (HTTP 404).
The endpoint is:
https://panopticon.example.com/index.php/mcp
This form works on every server, with or without URL rewriting, so it is the one to use in the AI-tool configuration examples below.
If your server rewrites URLs — Apache with the shipped .htaccess (which includes the required rewrite rule), or an
equivalent rule on Nginx/IIS — you can use the shorter form instead:
https://panopticon.example.com/index.php/mcp
Important
The short /mcp form needs a rewrite rule. The shipped htaccess.txt provides it, but you must rename that file to
.htaccess (see The .htaccess file). Without it, /mcp returns a plain 404 and you must
use the /index.php/mcp form. This rewrite rule was added in Panopticon 2.2.1; on 2.2.0 the /mcp form does not
work even with the .htaccess — use /index.php/mcp.
Both forms route to the same server. The MCP server implements the Streamable HTTP transport in stateless mode: each request is self-contained and authenticated by a static HTTP header, so there is no session handshake to manage.
Every request must carry a Panopticon API token in a standard HTTP Bearer Authorization header:
Authorization: Bearer YOUR_API_TOKEN
To mint a token, log into Panopticon, click your name (top-right) → API Tokens, and create one. The token inherits your account's permissions. You can also restrict a token to specific scopes (e.g. read-only) — the MCP server honours those scopes exactly like the JSON API does. See API Overview for details on tokens and scopes.
Tip
Treat an API token like a password. Anyone holding it can use the MCP server with your account's permissions. Prefer a dedicated, least-privilege token (restricted scopes, and an account that only has access to the sites you want the assistant to manage).
Important
Many web server / PHP combinations strip the Authorization header before it reaches PHP, which makes every
request fail with a 401 even when the token is correct. The shipped .htaccess handles this for Apache; Nginx and
IIS need a small amount of configuration. See The .htaccess file for the exact directives. If
you cannot forward the header at all — for example on shared hosting running cgi-fcgi/LSPHP with a restricted
AllowOverride, where the header is dropped before PHP even starts and no server-side workaround can recover it —
use the X-Panopticon-Token header described next.
If the Authorization header does not reach PHP on your host, send the token in the X-Panopticon-Token header
instead. Panopticon accepts it identically to a Bearer token, and — because it is a custom header rather than
Authorization — most cgi-fcgi/LSPHP setups forward it untouched:
X-Panopticon-Token: YOUR_API_TOKEN
Some MCP clients only speak stdio, or do not let you set a raw request header. A convenient bridge is
supergateway, which turns any Streamable HTTP MCP server into a stdio
server and lets you attach arbitrary headers. This configuration works even on hosts that strip Authorization:
{
"mcpServers": {
"panopticon-yoursite": {
"command": "npx",
"args": [
"-y", "supergateway",
"--streamableHttp", "https://panopticon.example.com/index.php/mcp",
"--header", "X-Panopticon-Token: YOUR_API_TOKEN"
]
}
}
}Replace https://panopticon.example.com/index.php/mcp with your endpoint and YOUR_API_TOKEN with your token. The
X-Panopticon-Token header can be substituted for Authorization: Bearer … in any of the AI-tool examples below whose
client lets you name the header.
The MCP server is designed so that an AI agent can never exceed the boundaries of the token it uses:
- Same permissions as the API. Every tool enforces the same access control as the equivalent API endpoint. A user who can only access sites A and B will not even see that sites C and D exist when listing sites.
-
Token scopes apply. A tool is only offered if the token grants the scope that the matching API endpoint requires
(for example, the
schedule_cms_updatetool needs thesites:cms-updatescope). A token with no explicit scopes is treated as granting all scopes, exactly as in the API. - Secrets are not exposed. Unlike the raw JSON API, MCP tools deliberately omit stored secrets (such as extension download keys and connection credentials) from their output, so they are never fed into an AI model's context.
There are two layers of control over the set of tools the MCP server offers, on top of the per-user permissions above.
1. Globally disabled tools (the kill-switch). In System Configuration → Security → MCP Server, the Globally
disabled tools field accepts a comma-separated list of tool names that are never exposed to anyone, regardless of
user, token, or group. For example, add get_sysconfig to keep system configuration entirely out of MCP. This list
always wins.
2. Per-user-group disabled tools. When editing a user group, the Disabled MCP tools field lets a Super User deny specific tools to members of that group.
Important
When a user belongs to several groups, a tool is denied only if every one of their groups disables it. Being granted a tool by any group overrides being denied it by another group.
This is the opposite of Joomla's “deny wins” access control. It is a deliberate convention over configuration choice: tools stay available unless they are universally restricted. If you need an absolute block, use the global Globally disabled tools kill-switch described above, which always takes precedence.
| Tool | What it does | Required scope | Super User only |
|---|---|---|---|
list_sites |
List the sites you can access (with search/filter) | sites:read |
no |
get_site |
Get a single site's details | sites:read |
no |
get_site_status |
Health summary for a site (CMS/PHP/extensions/backup) | sites:read |
no |
list_site_extensions |
List a site's extensions/plugins and update state | sites:extensions |
no |
list_tasks |
List scheduled tasks (others must pass a site_id they administer) |
tasks:read |
no |
get_task |
Get a single scheduled task | tasks:read |
no |
get_stats |
Global dashboard counters across all sites/tasks | sites:read |
yes |
get_sysconfig |
Read non-sensitive system configuration | sysconfig:read |
yes |
get_selfupdate_info |
Whether a Panopticon update is available | selfupdate:read |
yes |
refresh_site |
Refresh a site's information now | sites:refresh |
no |
schedule_cms_update |
Schedule a CMS core update for a site | sites:cms-update |
no |
cancel_cms_update |
Cancel a scheduled CMS update | sites:cms-update |
no |
schedule_extension_update |
Schedule an extension/plugin update | sites:extensions |
no |
cancel_extension_update |
Cancel a queued extension/plugin update | sites:extensions |
no |
All of the coding tools below support Streamable HTTP MCP servers with a static HTTP header. The configuration key for
the server URL is url for every tool except Antigravity (which uses serverUrl) and Qwen Code (which uses httpUrl).
In every example, replace https://panopticon.example.com/index.php/mcp with your endpoint and YOUR_API_TOKEN with
your token. The examples use the universal /index.php/mcp form; if your server has the rewrite rule (Apache with the
shipped .htaccess), you can shorten it to /mcp.
Use the CLI to add the server:
claude mcp add --transport http panopticon https://panopticon.example.com/index.php/mcp \
--header "Authorization: Bearer YOUR_API_TOKEN"Open Settings → Connectors → Add custom connector, give it a name (e.g. Panopticon), and set the URL to your
endpoint. If your build of Claude Desktop lets you add request headers, add Authorization: Bearer YOUR_API_TOKEN.
Otherwise, append the token as a query parameter instead (…/index.php/mcp?_panopticon_token=YOUR_API_TOKEN), which
Panopticon also accepts.
Important
When you pass the token in the _panopticon_token query parameter you must URL-encode it. API tokens are Base64
and routinely contain +, / and =, which have special meaning in a URL — an unencoded + in particular is
decoded to a space and corrupts the token. Most clients URL-encode query parameters for you; if you are building the
URL by hand, encode the token first. Prefer the Authorization header in production: the query parameter also leaks
the token into server access logs and Referer headers.
Edit ~/.codex/config.toml:
[mcp_servers.panopticon]
url = "https://panopticon.example.com/index.php/mcp"
[mcp_servers.panopticon.http_headers]
Authorization = "Bearer YOUR_API_TOKEN"In Codex Desktop's MCP settings, add a new server of type Streamable HTTP (or Remote), set the URL to your endpoint,
and add an Authorization: Bearer YOUR_API_TOKEN header.
Qwen Code uses the key httpUrl (not url). Edit ~/.qwen/settings.json:
{
"mcpServers": {
"panopticon": {
"httpUrl": "https://panopticon.example.com/index.php/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_TOKEN"
}
}
}
}In Mistral's tool/connector settings, add a custom MCP connector pointing at your endpoint URL and add an
Authorization: Bearer YOUR_API_TOKEN header.
Add the server to your OpenHands MCP configuration:
{
"mcpServers": {
"panopticon": {
"url": "https://panopticon.example.com/index.php/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_TOKEN"
}
}
}
}Antigravity uses the key serverUrl (not url):
{
"mcpServers": {
"panopticon": {
"serverUrl": "https://panopticon.example.com/index.php/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_TOKEN"
}
}
}
}Create .mcp.json in your workspace (or use MCP: Add Server from the Command Palette):
{
"servers": {
"panopticon": {
"type": "http",
"url": "https://panopticon.example.com/index.php/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_TOKEN"
}
}
}
}Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project):
{
"mcpServers": {
"panopticon": {
"url": "https://panopticon.example.com/index.php/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_TOKEN"
}
}
}
}In Settings → Tools → AI Assistant → Model Context Protocol (MCP), add a server. Choose the HTTP / SSE type, set
the URL to your endpoint, and add an Authorization: Bearer YOUR_API_TOKEN header. (You can also paste the JSON form
with a url key and a headers object.)
The consumer ChatGPT app does not support adding a custom Streamable HTTP MCP server like this one. If you want to use Panopticon with OpenAI's tooling, install Codex Desktop (or the Codex CLI) on your computer and configure it as shown above.
-
404 with a JSON body (
{"error":{"code":-32601,"message":"The MCP server is not enabled."}}): the MCP server is disabled. Enable it in System Configuration. -
404 with a plain HTML page (your web server's own 404, no JSON): the request never reached Panopticon. You are
almost certainly using the short
/mcpform on a server without the rewrite rule. Switch to/index.php/mcp, or install the shipped.htaccess(Panopticon 2.2.1 or later — see The .htaccess file). -
401 responses: the token is invalid, disabled, or expired — or the
Authorizationheader is being stripped before it reaches PHP. Header stripping is the most common cause on shared hosting: verify your web server forwards theAuthorizationheader (The .htaccess file). If the header is dropped before PHP starts (common oncgi-fcgi/LSPHP) and no configuration recovers it, send the token in theX-Panopticon-Tokenheader instead. If you are using the_panopticon_tokenquery parameter, make sure the token is URL-encoded. You can confirm which is happening: each failed attempt is written to the audit log with a reason —missing_tokenmeans no token reached PHP (header stripping),no_secretmeans yourconfig.phphas no persistedsecret(fixed in Panopticon 2.2.1; upgrade and re-mint your tokens, as tokens created while the secret was missing can never validate). - A tool you expected is missing from the list: check (1) the token's scopes, (2) whether the tool is in the Globally disabled tools list, (3) whether every one of your groups disables it, and (4) for Super-User-only tools, whether your account is a Super User.
-
GETrequests return 405: that is expected. The stateless server only acceptsPOSTfor JSON-RPC messages.
Documentation Copyright ©2023–2025 Akeeba Ltd.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
You can also obtain a copy of the GNU Free Documentation License from the Free Software Foundation
- Overview pages
- Working with sites
- Site Overview
- Backup Management with Akeeba Backup Pro
- Security Management with Admin Tools Pro
- Core File Integrity Check
- Scheduled Update Summary
- Scheduled Action Summary
- Backup Tasks
- Scanner Tasks
- System Configuration
- Managing Sites
- Mail templates
- Web Push Notifications
- Legal Policies
- Users and Groups
- Tasks
- Log files
- Update Panopticon
- Database Backups
- Fixing your session save path
- The .htaccess file
- Advanced Customisation (user code)
- Plugins
- Custom CSS
- Custom Templates
- Advanced Permissions
- .env For Configuration
- API Overview
- Sites endpoints
- Stats & Site Status endpoints
- System configuration endpoints
- Tasks endpoints
- Self-update endpoints