Versions: Grav 2.2.9, API plugin 1.0.50, grav-mcp 0.1.2 (via npx -y grav-mcp), Claude Desktop. Multilingual site with nl (default) and en, include_default_lang_file_extension: true.
Problem
update_page with lang: "en" never updates the English version:
- On a page with both item.nl.md and item.en.md, the change is written to the Dutch file.
- On a page that only has item.en.md, the call fails. With an etag it returns 409 Conflict; without one it returns 500. The log shows:
Security::detectXssInEditorContent(): Argument #1 ($rawContent) must be of type string, null given (from Page->save() in PagesController::update()).
get_page and delete_page with lang work correctly.
Cause
The API docs list lang for PATCH /pages/{route} as a query parameter. In src/tools/pages.ts, update_page puts it in the JSON body body.lang = args.lang), so the API ignores it and resolves the page in the default language. For an English-only page that resolves to an empty page object, which explains the 409 (the etag is compared against that empty page) and the 500 (null content on save).
Fix
The client's patch() already accepts a query option:
```ts
// remove:
if (args.lang !== undefined) body.lang = args.lang;
// and pass lang as a query parameter:
const response = await client.patch<Page>/pages/${route}, body, {
etag: args.etag,
query: buildQuery({ lang: args.lang }),
});
```
Workaround until then
Append the language to the route, e.g. route: "/blog/my-post?lang=en". I tested this on both page types: the write lands in item.en.md, the etag is accepted, and the default-language file is untouched.
Side note for the API plugin
It might be worth guarding Page::save() (or the update controller) against a page that only resolves through the default-language fallback, so it returns a 404 or 422 instead of a 500.
Thanks for grav-mcp, it is otherwise working very well for us.