Update-Manager

Aktuelle Version

3.5.0-rc.7-900beca2

Updates gültig bis: 2028-01-06 13:08:25

Update verfügbar

3.5.0-rc.18

patch

Veröffentlicht: 2026-08-14

Added

  • Every install now serves its own documentation to AI agents: The docs corpus and its search and reference indexes already shipped inside the package for the admin viewer; a new bundled extension, totalcms/docs, exposes them through the site's own MCP server as docs_search, docs_get and docs_lookup. The point is version matching: an agent working on a site running this release looks up that install's Twig signatures, field options, API endpoints and CLI flags, rather than whatever the model remembers about some other version — the gap between "what the docs say" and "what this site does" stops existing. It is promoted from the private extension that has served totalcms.co since mcp.totalcms.co was retired, with tool names, descriptions, schemas and annotations byte-identical to it. Unlike every other bundled extension it ships enabled, because documentation tools nobody switches on help nobody — but enabled is not public: the tools register at authenticated access, so an anonymous caller on a customer's site never sees them. Sites whose anonymous audience genuinely is Total CMS builders — a docs mirror, a support site — can opt in under Admin → Extensions → Total CMS Docs → Settings. Disable the extension entirely to remove all three tools from every persona
  • Five guided workflows for agents working on a Total CMS site: Tools let an agent read the documentation; nothing told it when to bother. The docs extension also registers five MCP prompts — tcms_research (answer a question from this install's docs rather than from memory), tcms_build_page (plan and build a Site Builder page), tcms_explain_field (explain a field type from the reference index), tcms_twig_recipe (find the right Twig helper and write the template), and tcms_troubleshoot_mcp (diagnose a connection failure in the order the causes actually occur). Prompts are user-selected rather than model-invoked, so they appear in the client's own prompt picker. They follow the tools' access level, since a prompt instructing an agent to call docs_lookup is useless to a caller who cannot see docs_lookup
  • A connection checker for MCP, because the failures are invisible from the outside: An AI client that cannot connect reports almost nothing — claude.ai shows "Couldn't connect to the server" whether the cause is a CDN blocking the agent's user-agent, a stripped Authorization header, a missing rewrite rule, or a discovery document served from the wrong authority. The MCP settings page now runs six outbound self-probes covering exactly those, each reporting pass, warn, fail or unreachable, so an operator can see which layer is at fault instead of guessing. Born from a live customer connector failure where three separate causes were stacked on top of each other
  • The MCP endpoint answers a listening stream on GET: The MCP PHP SDK has no GET case, so GET /mcp fell through to 405. That is spec-legal — a server with nothing to push may refuse — but strict clients reject it outright, and OpenAI's plugin-directory scanner fails its tool scan on it. The endpoint now answers with a bounded keepalive-only SSE stream, opened only for GET plus Accept: text/event-stream, so browsers, crawlers and uptime monitors still receive the SDK's 405 and never hold a worker
  • MCP tools declare their output schemas: Callers previously had to infer a tool's result shape by running it. Every tool now publishes an output schema, and query_collection and saved-query tools share a single result contract instead of returning subtly different envelopes for the same job. Saved-query tools also carry titled, fully explicit annotations, so a client can tell a read from a write without calling it
  • Bundled extensions may ship enabled by default: A new default_enabled manifest field, honored only for extensions bundled inside the package. An extension installed into tcms-data/extensions/ cannot declare itself bundled and cannot enable itself, so third-party code still waits for an operator. A saved state record always wins in both directions, so disabling a default-enabled extension sticks

Changed

  • mcp.publicAccess now defaults to on: Anonymous MCP callers resolve to the public persona out of the box instead of being refused, matching the default the settings form already advertised. This is a posture change on upgrade for installs that never set the flag, but the exposure it grants is bounded by a second gate that has not changed: the public persona only ever sees collections explicitly marked mcp.access = public, so a site that has marked nothing public still exposes nothing. Operators who want the endpoint closed regardless set mcp.publicAccess => false

Fixed

  • Bearer tokens silently degraded to anonymous on Apache CGI and FastCGI hosts: Apache does not pass the Authorization header to PHP under CGI/FastCGI unless told to, so an MCP or REST client would complete its OAuth flow, receive a valid token, and then have every subsequent call treated as anonymous — authorization appeared to succeed and nothing worked afterwards, with no error naming the cause. The shipped .htaccess now re-exposes the header, with a middleware fallback for installs whose rewrite rules cannot be changed. Found on a customer's Stacks-hosted site where it was one of three stacked causes
  • Extension-registered MCP prompts could not receive arguments: registerMcpPrompt() has always documented its handler as taking the caller's arguments, but no handler ever saw them, and the arguments an extension declared were not advertised either. The SDK derives a prompt's published argument list by reflecting its handler and then fills those parameters by name, so a handler written the documented way advertised a single argument literally named arguments and dropped whatever the caller sent. In a client that renders as one unlabelled box whose contents go nowhere. Prompts are now registered through the SDK's explicit-schema entry point, so the declared prompt is the published schema: argument names, descriptions and required flags all survive, and handlers receive the caller's arguments as documented. Nothing shipped depended on the old behavior, because no shipped prompt could have worked
  • resources/read buried every payload one level too deep: The three core resource handlers each returned a complete result envelope, and the SDK then wrapped that again — so contents[0].text decoded not to the collection's items but to a second, entire envelope holding them. A capable agent digs through the extra layer, which is why it went unnoticed; anything mechanical does not. Claude Desktop attaches a resource by reading that field, so selecting a collection produced a file containing another envelope rather than the content. Handlers now return flat content and let the SDK build the single envelope
  • A deleted upstream repository broke every fresh install: khanzadimahdi/uploadmanager was a direct dependency whose author removed their GitHub repository. Packagist still advertises the package and still points at the now-dead archive, so composer install failed for anyone installing from source, CI included. The package was entirely unreferenced and has been removed, along with two other libraries — glenscott/url-normalizer and halaxa/json-machine — that were added as promising and never used. ext-fileinfo is now declared directly: the removed package had been supplying that platform requirement transitively, and the upload security validator depends on it for MIME detection
  • The Cache Manager reported absent backends as errors: A backend that is simply not installed rendered as a red error row, which reads as a fault on a site that is perfectly healthy — with APCu and Redis both running, Memcached's absence is not a problem. Backends explicitly switched off in cache settings are now omitted from the manager entirely, and a merely-not-installed backend renders as a neutral "Not Installed" badge. The recommendations block still advises adding a memory tier when no cache tier exists at all
  • Saving a form left the cursor in an invisible field: A form whose first input is hidden by a visibility condition would open with focus in an element the operator cannot see, and a failed save could send the cursor to an invalid field that was equally hidden. Focus now skips inputs that are not visible, and a failed save returns the cursor to the first invalid field the operator can actually reach
  • Card fields blamed the wrong field for their own invalid contents: A validation failure inside a card's sub-field was reported against the sub-field by its internal name, which does not appear anywhere in the form. The error is now raised against the card the operator can see
  • tcms oauth:setup printed a command that was missing its arguments: The setup instructions showed a truncated command, so copying it produced an error. The full command is now shown
  • Video embeds failed on sites with a strict referrer policy (YouTube error 153, part two): rc.17 fixed the mangled player parameters, but YouTube has a second trigger for the same error: receiving no Referer header at all. That's exactly what happens on a site whose host, security plugin, or <meta name="referrer"> tag sets a site-wide no-referrer policy — the embed works everywhere else and fails there, with nothing visible to explain why. Embed iframes now carry referrerpolicy="strict-origin-when-cross-origin", the same attribute YouTube's own embed snippet ships. It restates the browser default on just the player frame, so strict-policy sites embed correctly and nothing changes anywhere else

Enhanced

  • Documentation for connecting AI clients: A new page walks through pointing Claude Desktop, Claude on the web, Claude Code, Cursor and VS Code at a site's MCP endpoint, including the one-click install links Cursor and VS Code support and where to find each client's own configuration. Every method on the page was tested end to end
  • The configuration docs now state which layer wins: config/tcms.php is not the last word — settings saved in the admin are merged after it, so a setting with an admin control cannot be overridden from the file. The file still loads and its other keys still apply, so the symptom is a value that silently refuses to change. The precedence order is now documented in both the configuration guide and the project's own config/tcms.php header, along with the one-line check that tells you which case you are in

This installation is managed by Composer. Run composer update totalcms/cms to update.