Troubleshooting

Silent failures first: the ones with no error, no log line and no exception. Most of this module's loud failures are deliberate — a refusal with a sentence explaining what to do instead is the feature, not the bug.

The tool is not there

Symptom Likely cause
A tool is missing from tools/list and nothing was logged The YAML was never read. The folder has to be named exactly h1McpTools (or h1McpPublicTools) and sit at the root of a module's resources. A typo, a nested path or a module that is not installed all look identical: silence.
Every tool is missing, on every surface h1-mcp-api is installed but no transport is. This module registers and executes tools; it exposes nothing. Without h1-mcp they are registered, valid and unreachable — and nothing warns, because from here everything is fine.
A tool is missing and the log says "le falta 'name'", "le falta 'contentType'", "le falta 'fields'" or "apunta al content type … que no está registrado" A misconfigured GenericContentTypeTool / GenericDecoratedFieldsTool. It hides itself on purpose, and says why: fix the YAML key it names, or check that the content type's light module is installed.
An error mentions generic-content-type-tool-sin-configurar That is the placeholder getName() of a tool with no name in its YAML. The registries call getName() before filtering by availability, so the placeholder can surface in a message even though the tool is never offered.
The tool appears on the admin SSE surface but only the public tools are listed The endpoint event from /v1/mcp/admin/sse advertises /v1/mcp/message, which is the public endpoint's message path, answered from McpPublicToolRegistry. Check the admin surface with POST /.rest/v1/mcp/admin instead. This is a h1-mcp issue, not this module's.
A tool is listed on one instance and not another isAvailable() returned false — the usual reason is an optional module that is absent, or a DX-only feature on a Community instance. Both registries filter on it in listTools and in callTool.
A service injected into a tool is null Tools are instantiated by node2bean, not by Guice. @Inject does nothing in a tool. Use Components.getComponent(MyService.class).

A field is refused

Each of these is intentional. The message names the fix; this table explains the reasoning.

Symptom Likely cause
"El campo 'x' no lo escribe la tool 'y': … su dueño es la tool 'z'" Another module decorated this content type and owns those fields. Call the tool it names, addressing the item by workspace + uuid — the uuid comes from a get on the first tool.
"El campo 'x' existe en el form … pero NINGUNA tool lo escribe" The field arrives through a decoration, the model of this module does not declare it, and no tool claims it. The module that decorated the content type has to declare its own tool — GenericDecoratedFieldsTool does it from YAML with no Java.
"está declarado con formas incompatibles" The form says the field is a simple value and the module's model declares it as a Map/Collection (ADR-017). Usually a read projection that shares its name with the input property — the projection should be named differently.
"no declara ninguno de los campos … así que la decoration que los aporta no está aplicada" GenericDecoratedFieldsTool checked the target content type's form and did not find its fields. A decoration whose file name does not match the target app's name never applies and never warns — check that first.
"es una lista de nodos hijos … y esta tool no la escribe" A decorated field that is a jcrMultiField. Rebuilding the container would rotate its children's uuids, which is what ADR-018 exists to prevent. Edit it in AdminCentral, or through a specialist tool that matches children in place.
A field that is visible in the dialog comes back as "Campo desconocido" The composite that holds it does not use itemProvider: currentItemProvider, so its sub-fields are not properties of the node and are not flattened into the form view. Add it — at every level of the chain.
A payload that mirrors the form structure validates but writes nothing Same cause, seen from the other side: with currentItemProvider the writer walks the content tree (flat) while the form tree is nested. Send the content shape. A get shows you which one it is.
A readOnly field is ignored By design: the server owns it. It is dropped from the write and its real value appears in the re-read response.
Two tools claim the same field toolOwning returns the first registered tool whose ownedFields() contains it, and the iteration order of the registry is not defined — so the error message could name either. Declare a field in exactly one tool.

Create, update, delete

Symptom Likely cause
create fails asking for nodeName GenericContentTypeTool found no identity field in the payload. Either pass nodeName, or declare the content type's identifying field in nodeNameFrom. It deliberately does not invent a UUID name: a node called 8f3a1b9c-… is indistinguishable for whoever manages the content.
Editing an item renamed its node and broke references The node name was derived from a human-readable or i18n field. Magnolia names a node from its name property, and references between content types are stored by path, so fixing a typo renames the node and breaks whatever pointed at it (ADR-014). Derive it from a technical key.
update answers "no se recibió ningún cambio" The payload carried only identity and control keys. That is an error rather than a silent no-op on purpose.
delete, move, rename or rename_folder "did nothing" and returned a description They are two-step. The first call is a preview: confirmationRequired: true plus the scope. Repeat with confirm: true.
create_folder fails saying the parent does not exist It does not create phantom parent chains. Create the parent first — and note the parent must itself be a folder: an item cannot contain folders.
move fails saying the destination does not exist Deliberate: move does not create the destination, so a typo is an error instead of new garbage taxonomy. create does create its taxonomy folder, because there the folder is derived rather than typed.
Content ends up in a folder nobody looks at The brand folder's case does not match the site's rootWebsite. Folder names are sanitised preserving case for exactly this reason; JCR is case-sensitive, and a lower-cased brand folder silently orphans everything in it.
remove_property is refused The property is a required field of the content type. Change its value with update instead. System properties (jcr:, mgnl:) are refused too.
reorder answers reordered: false The node was already in that position. If the answer also has clamped: true and requestedPosition, the index was out of range and was moved to the nearest end — reported, never silent.
A published item does not appear on the public instance Its folder was never published. Publish the folder first (without recursive), then its contents — a child has nothing to hang from if the parent does not exist there.

Listings and permissions

Symptom Likely cause
A listing is empty although the content exists The tool runs in the calling session, so it returns only what that user can read. There is no elevation anywhere in this module. On the public surface that user is typically anonymous.
nodeName resolution says "not found" for something that exists Same cause: the SQL2 search only sees what the session can read. It can also be genuinely ambiguous — several matches raise an error listing the paths.
The order of a listing does not match AdminCentral nodesOfType walks the tree and preserves JCR child order; listByFolder uses SQL2 with no ORDER BY, which is Jackrabbit's undefined order. Use the first where order is part of the contract.
publish fails with a command error The calling user lacks activation rights. Publishing goes through Magnolia's default catalog (activate/deactivate) with the caller's session.
A list on the public surface returns items you meant to hide allowedActions restricts which actions run, not what they see. The ACL is what stops a read; the whitelist is what stops a write attempt. Grant anonymous read only on the workspaces you mean to expose.
allowedActions seems to be ignored It matches on the action argument. A tool whose actions are not driven by an action key gets no restriction from it, and a name misspelled in the list simply never matches.

Languages

Symptom Likely cause
"Idioma no configurado" and nothing was written A locale outside I18nContentSupport was sent. The check runs before any write, so you never end up with half a translation saved.
"No se pudieron persistir propiedades i18n" The properties were written and re-read after saving, and one did not survive the store — typically an unusual character. U+2010 and U+2011 are normalised to ASCII - for you; anything else is reported rather than lost.
The translations of a repeatable composite were ignored The default-language content has to exist first: translations align by order with the container's existing children, and nothing is created or renamed. The log says "el contenido default debe crearse primero".
More translation entries than items, and the extras vanished Same alignment: entries beyond the existing children are dropped. Create the items first.
Other languages disappeared after an unrelated update They should not: the i18n properties are snapshotted before the write and restored afterwards, except for the fields that call rewrote. If it happens, the field was in the payload — its translations for that call win.
A translation was accepted but the field is not translatable It would have been refused: the validator requires each field to exist and be i18n: true, walking into composites and switchables. If it passed, check that you are looking at the same field name the form declares.

Configuration of the generic tools

Symptom Likely cause
"No se pudo determinar el workspace del content type" The content type's datasource is not a JCR one, so the workspace cannot be derived. Declare workspace: in the tool's YAML.
"tiene el segmento 'x', que no es un placeholder" Every segment of folderTemplate must be {field} or {field?}. A literal segment is refused rather than silently treated as a folder name.
Items land in the workspace root instead of their folder A required {field} of the template was not in the payload, so the path falls back to the root. Make the segment optional ({field?}) if that is acceptable, or ask the caller for it — the generated schema already instructs the assistant to ask rather than invent.
A reference field is refused as nonexistent The value must resolve to a real node in the field's target workspace. A key is resolved to a path for you; if the key exists under several brands you get an ambiguity error listing them, and have to send the full path.
A complex value sent as a string is refused {"a":1} or […] as text in a scalar field is detected and refused, not stored. Send the real object or array — and check the field's type in the schema, since a scalar field accepts neither.