Related Feature
Feature request: N/A — this is a bug report on the existing download_odata_service_metadata tool exposed by @sap-ux/fiori-mcp-server.
Description
The MCP tool download_odata_service_metadata (exposed by @sap-ux/fiori-mcp-server) requires its appPath parameter to point to an already-existing directory into which metadata.xml will be written. This pre-condition is not documented in the tool's input schema description, so LLMs consuming the MCP server routinely pass a folder that has not been created yet — for example, the target folder of a Fiori application they are about to scaffold. When that happens the metadata download fails and the whole "download metadata → generate app" chain breaks in a way that is hard for the LLM to recover from.
The problem is not the runtime behaviour per se (writing a file into a non-existent folder is a legitimate error) — the problem is that the tool's description gives the LLM no signal that this pre-condition exists.
Current parameter description (from the tool's JSON Schema):
appPath (required, string): "Absolute path to the folder where metadata.xml will be saved. Typically the project target folder."
Why this misleads the LLM:
- "folder where metadata.xml will be saved" describes the folder's purpose, not its lifecycle. Many filesystem primitives the LLM has been trained on (
mkdir -p && …, various generator CLIs, some fs.writeFile variants) auto-create parent directories, so absent a rule to the contrary the LLM defaults to that convention.
- "Typically the project target folder" reinforces the wrong intuition: for a new project, "the project target folder" is exactly the thing the LLM is about to create. So the LLM concludes it is safe to pass a path that does not exist yet.
- The description contains no pre-condition line, no failure-mode hint, no post-condition line.
- The parameter name
appPath is semantically loaded ("the app's path"), which further hides the fact that this is just "an existing directory to drop a file into".
Steps to Reproduce
- From an MCP client (e.g. Claude Code, GitHub Copilot with
fiori-mcp installed), start a conversation like:
"Create a Fiori elements List Report for the OData service at https://…/sap/opu/odata/sap/<SERVICE>/ and put it under C:\dev\my-new-fiori-app."
- The LLM chains the recommended workflow:
a. Calls download_odata_service_metadata with appPath: "C:/dev/my-new-fiori-app" (a path that does not exist yet).
b. Intends to follow up with generate_fiori_app_odata.
- The metadata download step fails because the folder does not exist. Depending on the client, the LLM sees either a raw filesystem error or a truncated failure and cannot recover automatically.
Expected results
Either:
- (a) The tool description makes the pre-condition explicit ("this folder MUST exist; this tool does not create directories; create it with
mkdir -p <appPath> first"), so the LLM plans a preparatory mkdir step; or
- (b) The server-side handler creates the directory recursively (
fs.mkdirSync(appPath, { recursive: true })) and the description states this behaviour, so the current LLM planning is correct-by-default; or
- (c) The server-side handler validates and returns a precise, actionable error message ("
appPath does not exist. Create the directory before calling this tool: mkdir -p <appPath>. This tool does not create directories."), so the LLM can self-correct on the next turn.
Recommended combination: (a) + (c) — clarify the contract in the description and fail fast with a specific error string. Both are cheap and give defence in depth against LLMs that skim the schema.
Proposed replacement description for appPath:
Absolute path to an existing folder where metadata.xml will be written. The folder MUST exist before this tool is invoked — this tool does not create directories. If the caller is about to scaffold a new Fiori project, create the target folder first (e.g. mkdir -p <appPath>) and only then call this tool. Typically this is the same folder that will later be passed as the project target to generate_fiori_app_odata.
Proposed fail-fast guard at the top of the handler:
if (!fs.existsSync(appPath)) {
throw new Error(
`appPath does not exist: ${appPath}. Create the directory before calling this tool ` +
`(e.g. \`mkdir -p ${appPath}\`). This tool does not create directories.`
);
}
Actual results
The tool description does not state the pre-condition; the handler does not create the directory; and (based on the observed demo) the resulting error is not verbose enough for the LLM to recognise the root cause and self-correct.
Screenshots
N/A — text-based tool invocation. Trace/log excerpt can be added if useful.
Version/Components/Environment
OS:
Root Cause Analysis
Problem
{describe the problem}
Fix
{describe the fix}
Why was it missed
{Some explanation why this issue might have been missed during normal development/testing cycle}
How can we avoid this
{if we don't want to see this type of issues anymore what we should do to prevent}
Related Feature
Feature request: N/A — this is a bug report on the existing
download_odata_service_metadatatool exposed by@sap-ux/fiori-mcp-server.Description
The MCP tool
download_odata_service_metadata(exposed by@sap-ux/fiori-mcp-server) requires itsappPathparameter to point to an already-existing directory into whichmetadata.xmlwill be written. This pre-condition is not documented in the tool's input schema description, so LLMs consuming the MCP server routinely pass a folder that has not been created yet — for example, the target folder of a Fiori application they are about to scaffold. When that happens the metadata download fails and the whole "download metadata → generate app" chain breaks in a way that is hard for the LLM to recover from.The problem is not the runtime behaviour per se (writing a file into a non-existent folder is a legitimate error) — the problem is that the tool's description gives the LLM no signal that this pre-condition exists.
Current parameter description (from the tool's JSON Schema):
Why this misleads the LLM:
mkdir -p && …, various generator CLIs, somefs.writeFilevariants) auto-create parent directories, so absent a rule to the contrary the LLM defaults to that convention.appPathis semantically loaded ("the app's path"), which further hides the fact that this is just "an existing directory to drop a file into".Steps to Reproduce
fiori-mcpinstalled), start a conversation like:a. Calls
download_odata_service_metadatawithappPath: "C:/dev/my-new-fiori-app"(a path that does not exist yet).b. Intends to follow up with
generate_fiori_app_odata.Expected results
Either:
mkdir -p <appPath>first"), so the LLM plans a preparatorymkdirstep; orfs.mkdirSync(appPath, { recursive: true })) and the description states this behaviour, so the current LLM planning is correct-by-default; orappPathdoes not exist. Create the directory before calling this tool:mkdir -p <appPath>. This tool does not create directories."), so the LLM can self-correct on the next turn.Recommended combination: (a) + (c) — clarify the contract in the description and fail fast with a specific error string. Both are cheap and give defence in depth against LLMs that skim the schema.
Proposed replacement description for
appPath:Proposed fail-fast guard at the top of the handler:
Actual results
The tool description does not state the pre-condition; the handler does not create the directory; and (based on the observed demo) the resulting error is not verbose enough for the LLM to recognise the root cause and self-correct.
Screenshots
N/A — text-based tool invocation. Trace/log excerpt can be added if useful.
Version/Components/Environment
OS:
Mac OS
Windows
Other
Component:
@sap-ux/fiori-mcp-serverTool:
download_odata_service_metadataMCP client: GitHub Copilot (VS Code) — model: Claude 4.7 Opus (AI Core)
fiori-mcp-server version: 1.9.1 (as currently on npm,
dist-tags.latest)Root Cause Analysis
Problem
{describe the problem}
Fix
{describe the fix}
Why was it missed
{Some explanation why this issue might have been missed during normal development/testing cycle}
How can we avoid this
{if we don't want to see this type of issues anymore what we should do to prevent}