SAP published MCP servers for UI5, CAP, and Fiori tools. For background and official positioning, see the release post overview SAP Build introduces MCP servers.
The SAP Build article positions MCP as the standard bridge from coding assistants to SAP tools and support across popular IDE agents like Cursor, Windsurf, GitHub Copilot, Cline, and Claude Code. The emphasis is on best‑practice scaffolds, guardrails aligned to BTP, and consistent tool behavior across the portfolio.
This post is a hands‑on review, not another introduction. I focus on what matters when you actually use these servers locally, how they complement my SAP Docs MCP server, and where the current limits are. My Blog Posts about MCP can be found here.
Why the official CAP, Fiori, and UI5 MCP servers matter
SAP now provides MCP servers focused on concrete development tasks in CAP, Fiori tools, and UI5. They complement a documentation-first server like my SAP Docs MCP by giving the AI project awareness and executable workflows. In practice, this means better results directly in your editor, without relying on Joule for Developers.
CAP MCP server
Package: @cap-js/mcp-server.
GitHub: github.com/cap-js/mcp-server.
Release background and usage intent are covered in Boost your CAP Development with AI: Introducing the MCP Server for CAP.
What it does: gives LLMs a fuzzy search over your compiled CDS model (entities, services, annotations, HTTP endpoints) and a semantic search over CAP docs (similar to my SAP Docs MCP server). The goal is agentic coding for CAP projects with guaranteed grounding to your model and the official guide.
Install:
npm i -g @cap-js/mcp-server
Client config (example VS Code):
{
“mcpServers”: {
“cds-mcp”: {
“command”: “cds-mcp”,
“args”: [],
“env”: {}
}
}
}
Rules (recommended in your AGENTS.md .cursorrules or depending on the client):
– You MUST search for CDS definitions, like entities, fields and services (which include HTTP endpoints) with cds-mcp, only if it fails you MAY read *.cds files in the project.
– You MUST search for CAP docs with cds-mcp EVERY TIME you modify CDS models or when using APIs from CAP. Do NOT propose, suggest or make any changes without first checking it.
CLI usage for quick tests:
# Search CDS model
cds-mcp search_model . Books entity
# Search CAP docs
cds-mcp search_docs “how to add columns to a select statement in CAP Node.js” 1
CAP tools in detail
search_model returns CSN definitions with elements, annotations, file locations and HTTP endpoints. Useful to build queries or OData URLs.
{
“tool”: “search_model”,
“params”: {
“projectPath”: “/absolute/path/to/cap/project”,
“name”: “Books”,
“kind”: “entity”,
“topN”: 3,
“namesOnly”: false
}
}
For a sample project of mine, the response looks like this:
[
{
“kind”: “entity”,
“includes”: [
“cuid”,
“managed”
],
“elements”: {
“ID”: {
“key”: true,
“type”: “cds.UUID”
},
“createdAt”: {
“@cds.on.insert”: {
“=”: “$now”
},
“@UI.HiddenFilter”: true,
“@UI.ExcludeFromNavigationContext”: true,
“@Core.Immutable”: true,
“@title”: “{i18n>CreatedAt}”,
“@readonly”: true,
“type”: “cds.Timestamp”,
“@Core.Computed”: true,
“@Common.Label”: “{i18n>CreatedAt}”
},
“createdBy”: {
“@cds.on.insert”: {
“=”: “$user”
},
“@UI.HiddenFilter”: true,
“@UI.ExcludeFromNavigationContext”: true,
“@Core.Immutable”: true,
“@title”: “{i18n>CreatedBy}”,
“@readonly”: true,
“@description”: “{i18n>UserID.Description}”,
“type”: “cds.String”,
“length”: 255,
“@Core.Computed”: true,
“@Common.Label”: “{i18n>CreatedBy}”,
“@Core.Description”: “{i18n>UserID.Description}”
},
“modifiedAt”: {
“@cds.on.insert”: {
“=”: “$now”
},
“@cds.on.update”: {
“=”: “$now”
},
“@UI.HiddenFilter”: true,
“@UI.ExcludeFromNavigationContext”: true,
“@title”: “{i18n>ChangedAt}”,
“@readonly”: true,
“type”: “cds.Timestamp”,
“@Core.Computed”: true,
“@Common.Label”: “{i18n>ChangedAt}”
},
“modifiedBy”: {
“@cds.on.insert”: {
“=”: “$user”
},
“@cds.on.update”: {
“=”: “$user”
},
“@UI.HiddenFilter”: true,
“@UI.ExcludeFromNavigationContext”: true,
“@title”: “{i18n>ChangedBy}”,
“@readonly”: true,
“@description”: “{i18n>UserID.Description}”,
“type”: “cds.String”,
“length”: 255,
“@Core.Computed”: true,
“@Common.Label”: “{i18n>ChangedBy}”,
“@Core.Description”: “{i18n>UserID.Description}”
},
“username”: {
“@mandatory”: true,
“type”: “cds.String”,
“length”: 100,
“$location”: {
“file”: “db/schema.cds”,
“line”: 7,
“col”: 3
},
“@Common.FieldControl”: {
“#”: “Mandatory”
}
},
“email”: {
“@mandatory”: true,
“type”: “cds.String”,
“length”: 255,
“$location”: {
“file”: “db/schema.cds”,
“line”: 8,
“col”: 3
},
“@Common.FieldControl”: {
“#”: “Mandatory”
}
},
“firstName”: {
“type”: “cds.String”,
“length”: 100,
“$location”: {
“file”: “db/schema.cds”,
“line”: 9,
“col”: 3
}
},
“lastName”: {
“type”: “cds.String”,
“length”: 100,
“$location”: {
“file”: “db/schema.cds”,
“line”: 10,
“col”: 3
}
},
“role”: {
“type”: “cds.Association”,
“target”: “volleyball.tournament.UserRoles”,
“keys”: [
{
“ref”: [
“code”
],
“$generatedFieldName”: “role_code”
}
],
“$location”: {
“file”: “db/schema.cds”,
“line”: 11,
“col”: 3
}
},
“role_code”: {
“type”: “cds.String”,
“@odata.foreignKey4”: “role”
},
“isActive”: {
“type”: “cds.Boolean”,
“default”: {
“val”: true
},
“$location”: {
“file”: “db/schema.cds”,
“line”: 12,
“col”: 3
}
}
},
“$location”: {
“file”: “db/schema.cds”,
“line”: 6,
“col”: 8
},
“name”: “volleyball.tournament.Users”
},
{
“kind”: “entity”,
“@cds.autoexpose”: true,
“@cds.persistence.skip”: “if-unused”,
“@UI.Identification”: [
{
“Value”: {
“=”: “name”
}
}
],
“@cds.odata.valuelist”: true,
“includes”: [
“sap.common.CodeList”
],
“elements”: {
“name”: {
“@title”: “{i18n>Name}”,
“localized”: true,
“type”: “cds.String”,
“length”: 255,
“@Common.Label”: “{i18n>Name}”
},
“descr”: {
“@title”: “{i18n>Description}”,
“localized”: true,
“type”: “cds.String”,
“length”: 1000,
“@Common.Label”: “{i18n>Description}”
},
“code”: {
“key”: true,
“type”: “cds.String”,
“enum”: {
“Admin”: {
“val”: “ADMIN”,
“$location”: {
“file”: “db/schema.cds”,
“line”: 17,
“col”: 5
}
},
“EventCreator”: {
“val”: “EVENT_CREATOR”,
“$location”: {
“file”: “db/schema.cds”,
“line”: 18,
“col”: 5
}
},
“ResultsInputer”: {
“val”: “RESULTS_INPUTER”,
“$location”: {
“file”: “db/schema.cds”,
“line”: 19,
“col”: 5
}
},
“Reader”: {
“val”: “READER”,
“$location”: {
“file”: “db/schema.cds”,
“line”: 20,
“col”: 5
}
}
},
“$location”: {
“file”: “db/schema.cds”,
“line”: 16,
“col”: 7
}
},
“texts”: {
“type”: “cds.Composition”,
“cardinality”: {
“max”: “*”
},
“target”: “volleyball.tournament.UserRoles.texts”,
“on”: [
{
“ref”: [
“texts”,
“code”
]
},
“=”,
{
“ref”: [
“code”
]
}
]
},
“localized”: {
“type”: “cds.Association”,
“target”: “volleyball.tournament.UserRoles.texts”,
“on”: [
{
“ref”: [
“localized”,
“code”
]
},
“=”,
{
“ref”: [
“code”
]
},
“and”,
{
“ref”: [
“localized”,
“locale”
]
},
“=”,
{
“ref”: [
“$user”,
“locale”
]
}
]
}
},
“$location”: {
“file”: “db/schema.cds”,
“line”: 15,
“col”: 8
},
“$localized”: true,
“name”: “volleyball.tournament.UserRoles”
}
]
search_docs searches CAP docs locally (embeddings) and returns relevant chunks.
{
“tool”: “search_docs”,
“params”: { “query”: “draft activation action”, “maxResults”: 3 }
}
The response to the above query looks like this:
Fiori Support > Lean Draft > Programmatic Invocation of Draft Actions <Beta />
API, draft actions, JavaScript, Fiori, programmatic, service implementation
Demonstrates how to programmatically invoke Fiori draft actions using ApplicationService API: creating, discarding, editing, and saving (activating) drafts.
“`js
await srv.new(MyEntity.drafts, data) // create new draft
await srv.discard(MyEntity.drafts, keys) // discard draft
await srv.edit(MyEntity, keys) // create draft from active instance
await srv.new(MyEntity.drafts).for(keys) // same as above
await srv.save(MyEntity.drafts, keys) // activate draft
“`
—
Fiori Drafts > Activating Drafts
drafts, Java, event handler, CREATE, validation
Registers a @Before handler for the CREATE event. Used to validate user input or entity state before an active entity is created or updated as part of draft activation (Save action). Applies to activation flow of SAP Fiori draft-enabled entities.
“`java
@Before
public void validateOrderItem(CdsCreateEventContext context, OrderItems orderItem) {
// Add validation logic
}
“`
—
Fiori Support > Lean Draft > Handlers Registration
draft-specific events, event handler, Fiori, JavaScript, CANCEL, EDIT, NEW, SAVE
Illustrates how to add custom logic for specific draft events: NEW, CANCEL, EDIT, and SAVE. These let you react to various points in the Fiori draft process, including draft creation, discard, editing, and persisting changes.
“`js
// When a new draft is created
srv.on(‘NEW’, ‘MyEntity.drafts’, /*…*/)
// When a draft is discarded
srv.on(‘CANCEL’, ‘MyEntity.drafts’, /*…*/)
// When a new draft is created from an active instance
srv.on(‘EDIT’, ‘MyEntity’, /*…*/)
// When the active entity is changed
srv.on(‘SAVE’, ‘MyEntity’, /*…*/)
“`
Fiori MCP server
Package: @sap-ux/fiori-mcp-server.
GitHub Repo: github.com/SAP/open-ux-tools/packages/fiori-mcp-server
Release Blog Post: SAP Fiori Tools Update – First Release of the SAP Fiori MCP Server for Agentic AI Workflows
What it does: generates or modifies SAP Fiori apps, including adding pages, controller extensions, FCL, and manifest changes. It returns required parameters for each functionality and executes the change.
This MCP server also recommends adding a rules markdown file with the following content, so the LLM knows how to use the server better:
– When asked to create an SAP Fiori elements app check whether the user input can be interpreted as an application organized into one or more pages containing table data or forms, these can be translated into a SAP Fiori elements application, else ask the user for suitable input.
– The application typically starts with a List Report page showing the data of the base entity of the application in a table. Details of a specific table row are shown in the ObjectPage. This first Object Page is therefore based on the base entity of the application.
– An Object Page can contain one or more table sections based on to-many associations of its entity type. The details of a table section row can be shown in an another Object Page based on the associations target entity.
– The data model must be suitable for usage in a SAP Fiori elements frontend application. So there must be one main entity and one or more navigation properties to related entities.
– Each property of an entity must have a proper datatype.
– For all entities in the data model provide primary keys of type UUID.
– When creating sample data in CSV files, all primary keys and foreign keys MUST be in UUID format (e.g., `550e8400-e29b-41d4-a716-446655440001`).
– When generating or modifying the SAP Fiori elements application on top of the CAP service use the Fiori MCP server if available.
– When attempting to modify the SAP Fiori elements application like adding columns you must not use the screen personalization but instead modify the code of the project, before this first check whether an MCP server provides a suitable function.
– When previewing the SAP Fiori elements application use the most specific script for the app in the `package.json`.
Use via npx (no install needed):
{
“mcpServers”: {
“fiori-mcp”: {
“command”: “npx”,
“args”: [“–yes”,”@sap-ux/fiori-mcp-server@latest”, “fiori-mcp”]
}
}
}
Main tools: list-fiori-apps, list-functionality, get-functionality-details, execute-functionality. The typical flow is 1) list-functionality, 2) get-functionality-details, 3) execute-functionality.
Fiori tools and 3-step workflow
Discovery:
{
“tool”: “list-fiori-apps”,
“params”: { “workspaceDir”: “/abs/path/to/mono” }
}
The response for my sample repo looks like this:
{
“applications”: [
{
“name”: “resultsdashboard”,
“appPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/results-dashboard”,
“projectPath”: “/Users/marianzeis/DEV/mcp-sap-test”,
“projectType”: “CAPNodejs”,
“odataVersion”: “4.0”
},
{
“name”: “eventmanagement”,
“appPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/event-management”,
“projectPath”: “/Users/marianzeis/DEV/mcp-sap-test”,
“projectType”: “CAPNodejs”,
“odataVersion”: “4.0”
},
{
“name”: “matchresults”,
“appPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/match-results”,
“projectPath”: “/Users/marianzeis/DEV/mcp-sap-test”,
“projectType”: “CAPNodejs”,
“odataVersion”: “4.0”
},
{
“name”: “teammanagement”,
“appPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/team-management”,
“projectPath”: “/Users/marianzeis/DEV/mcp-sap-test”,
“projectType”: “CAPNodejs”,
“odataVersion”: “4.0”
}
]
}
Step 1:
{
“tool”: “list-functionality”,
“params”: { “appPath”: “/abs/path/to/app” }
}
The redacted response is worth for my Fiori elements app about 13k tokens:
{
“applicationPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/event-management”,
“functionalities”: [
{
“functionalityId”: “add-page”,
“description”: “Create new fiori elements page like ListReport, ObjectPage, CustomPage”
},
{
“functionalityId”: “generate-fiori-ui-app”,
“description”: “Creates (generates) a new SAP Fiori UI application within an existing CAP project.n Crucially, you must first construct the appGenConfig JSON argument.n To do this, you **MUST** use the ***CDS MCP*** to search the model for service definitions, entities, associations, and UI annotations.n As a fallback, only if no such tool is available, you should manually read and parse all .cds files in the projectPath to extract this information.n The data obtained from either method must then be formatted into a JSON object and passed as the appGenConfig parameter.”
},
{
“functionalityId”: “delete-page”,
“description”: “Remove existing fiori elements page from the application”
},
{
“functionalityId”: “create-controller-extension”,
“description”: “Add new controller extension by creating javascript or typescript file and updates manifest.json with entry. Controller extensions allow users to extensiate default behaviour with custom controllers code.”
},
{
“functionalityId”: [
“settings”,
“path”
],
“description”: “Represents a prefix that is prepended in front of the viewName”
},
{
“functionalityId”: [
“settings”,
“viewType”
],
“description”: “standard view type of views”
},
{
“functionalityId”: [
“settings”,
“title”
],
“description”: “Defines the title for the application.”
},
{
“functionalityId”: [
“settings”,
“description”
],
“description”: “Defines the description for the application.”
},
{
“functionalityId”: [
“settings”,
“flexEnabled”
],
“description”: “Enables key user adaptation for an application.”
},
{
“functionalityId”: [
“settings”,
“cloudDevAdaptationStatus”
],
“description”: “Represents the release status for the developer adaptation in the cloud (relevant for SAP internal only). The supported types are released, deprecated, obsolete, no value means not released.”
},
{
“functionalityId”: [
“settings”,
“flexibleColumnLayout”
],
“description”: “The flexible column layout allows users to see more details on the page, and to expand and collapse the screen areas.”
},
{
“functionalityId”: [
“settings”,
“flexibleColumnLayout”,
“limitFCLToTwoColumns”
],
“description”: “Determines whether the Flexible Column Layout is limited to two columns. If set to true, the third level will be displayed in full screen mode rather than a third column.”
},
{
“functionalityId”: [
“settings”,
“flexibleColumnLayout”,
“defaultTwoColumnLayoutType”
],
“description”: “Default Two Column Layout Type”
},
{
“functionalityId”: [
“settings”,
“flexibleColumnLayout”,
“defaultThreeColumnLayoutType”
],
“description”: “Default Three Column Layout Type”
},
{
“functionalityId”: [
“settings”,
“controllerExtensions”
],
“description”: “Controller extensions allow users to extensiate default behaviour with custom controllers code.”
},
{
“functionalityId”: [
“settings”,
“hideDraft”
],
“description”: “Hidden draft features.”
},
{
“functionalityId”: [
“settings”,
“hideDraft”,
“enabled”
],
“description”: “All features related to draft handling can be hidden from the UI while the draft functionality remains active in the background. To achieve this, enable the ‘Hide Draft’ property.”
},
{
“functionalityId”: [
“settings”,
“hideDraft”,
“stayOnCurrentPageAfterSave”
],
“description”: “Determines whether to stay on the current page after saving an object.nTo ensure a consistent experience, set this and ‘Stay On Current Page After Cancel’ to the same value.”
},
Step 2:
{
“tool”: “get-functionality-details”,
“params”: { “appPath”: “/abs/path/to/app”, “functionalityId”: “add-page” }
}
Here is a response for the functionality “add-page”:
{
“functionalityId”: “add-page”,
“name”: “Add new page to application by updating manifest.json”,
“description”: “Create new fiori elements page like ListReport, ObjectPage, CustomPage”,
“parameters”: [
{
“id”: “parentPage”,
“type”: “string”,
“description”: “Parent page is id/name of parent page. First try to extract parent page from user input in a format defined in example, if not possible suggest content defined in options”,
“options”: [
“EventsObjectPage”
],
“required”: true,
“examples”: [
“parentPage: EventsObjectPage”
]
},
{
“id”: “pageNavigation”,
“type”: “string”,
“description”: “Page navigation option for parent page. First try to extract navigation option from user input in a format defined in example, if not possible suggest content defined in options”,
“options”: [
“for EventsObjectPage: available navigation(s) is/are one of: teams, groups, matches”
],
“examples”: [
“pageNavigation: teams”
],
“required”: true
},
{
“id”: “pageType”,
“type”: “string”,
“description”: “Type of page to be created. First try to extract page type from user input in a format defined in example, if not possible suggest content defined in options.”,
“options”: [
“ObjectPage”,
“ListReport”,
“CustomPage”,
“FPMCustomPage”,
“AnalyticalListPage”
],
“examples”: [
“pageType: ObjectPage”
],
“required”: true
}
]
}
The problem here is that the MCP server returns an error:
{“error”: “MCP error -32602: Structured content does not
match the tool’s output schema: data should have
required property ‘.id'”}
I tested a few different functionalities and always saw the same error, so unfortunately this can’t be used yet.
Step 3:
{
“tool”: “execute-functionality”,
“params”: {
“appPath”: “/abs/path/to/app”,
“functionalityId”: “add-page”,
“parameters”: {
“pageType”: “ObjectPage”,
“entity”: “Books”,
“navigation”: “toAuthors”
}
}
}
As I got stuck at step 2, I unfortunately couldn’t properly test step 3.
UI5 MCP server
Package: @ui5/mcp-server.
GitHub: github.com/UI5/mcp-server
Release Blog Post:Give Your AI Agent Some Tools: Introducing the UI5 MCP Server
What it does: scaffolds UI5 apps, fetches API reference and guidelines, inspects an existing UI5 project, retrieves framework version info, and runs the UI5 linter for actionable fixes.
Quick client config:
{
“mcpServers”: {
“ui5mcp”: {
“command”: “npx”,
“args”: [“@ui5/mcp-server”]
}
}
}
Environment options (examples):
{
“mcpServers”: {
“ui5mcp”: {
“command”: “npx”,
“args”: [“@ui5/mcp-server”],
“env”: {
“UI5_MCP_SERVER_ALLOWED_ODATA_DOMAINS”: “localhost, services.odata.org”,
“UI5_LOG_LVL”: “verbose”
}
}
}
}
Available tools: create_ui5_app, get_api_reference, get_guidelines, get_project_info, get_version_info, run_ui5_linter.
UI5 tools in detail
create_ui5_app scaffolds a project from built-in templates (JS or TS). It can also preconfigure an OData V4 model if you pass a service URL that matches the allowed domains.
{
“tool”: “create_ui5_app”,
“params”: {
“projectDir”: “/abs/path/new-ui5-app”,
“template”: “ts”,
“oDataV4Url”: “https://services.odata.org/V4/OData/OData.svc/”
}
}
get_api_reference downloads and caches api.json files for the configured UI5 version and returns focused API info for a symbol.
{
“tool”: “get_api_reference”,
“params”: { “projectDir”: “/abs/path/ui5-app”, “symbol”: “sap.m.Button#text” }
}
In my tests this did not work. One app was using version 1.108.1 in ui5.yaml, and using this tool I got the following response:
Failed to fetch resource from CDN. Error: The requested resource does not exist for URL: https://ui5.sap.com/1.108.1/resources/sap-ui-version.json
My second Fiori elements app was using SAPUI5 version 1.136.7. The API reference tool gets the reference from the OpenUI5 SDK, which has the current maximum patch of 1.136.5. Because of this I got the error:
Failed to fetch resource from CDN. Error: The requested resource does not exist for URL: https://sdk.openui5.org/1.136.7/resources/sap-ui-version.json
Even after changing the version in the manifest I could not get the tool to work. It was still fetching the wrong version.
get_guidelines returns a curated markdown with UI5 and CAP development guidelines for agents.
{
“tool”: “get_guidelines”,
“params”: {}
}
Response:
# UI5 Development Guidelines
> *This document outlines the fundamental rules and best practices an AI agent must follow when developing or modifying SAPUI5 projects. Adherence to these guidelines is critical for creating modern, maintainable, and performant applications.*
## 1. Coding Guidelines
– **NEVER** use global variables to access UI5 framework objects (e.g., `sap.m.Button`). Instead, explicitly declare all dependencies, so that they are loaded asynchronously before your code executes.
– in Javascript: Using `sap.ui.define` at the top of the file (which also registers the file as a UI5 module) or dynamically using `sap.ui.require`
– in TypeScript: Using ES6 `import` statements
– in XML:
– For controls it is sufficient to declare the corresponding XML tag (e.g. `<m:Button></m:Button>`). The XML Template engine will load the corresponding resource automatically.
– However, when referring to programmatic API like formatters or types, those must be “imported” using a `core:require` directive
– Example
“`xml
<ObjectListItem
core:require=”{
Currency: ‘sap/ui/model/type/Currency’
}”
title=”{invoice>Quantity} x {invoice>ProductName}”
number=”{
parts: [
‘invoice>ExtendedPrice’,
‘view>/currency’
],
type: ‘Currency’,
formatOptions: {
showMeasure: false
}
}”
numberUnit=”{view>/currency}”/>
“`
– Find more information on the UI5 documentation page “Require Modules in XML View and Fragment”
– **ALWAYS** use the `sap/ui/core/ComponentSupport` module to initialize a UI5 application/component in an HTML page
– Example:
“`html
<!– index.html –>
<script id=”sap-ui-bootstrap”
src=”resources/sap-ui-core.js”
data-sap-ui-on-init=”module:sap/ui/core/ComponentSupport”
data-sap-ui-async=”true”
data-sap-ui-resource-roots='{ “my.app”: “./” }’
data-…=”…”>
</script>
“`
– Find more information on the UI5 documentation page “Declarative API for Initial Components”
– **ALWAYS** use data binding in views to connect UI controls to data or i18n models.
– When binding data from OData services, **NEVER** use custom formatters for standard data types (e.g., dates, numbers, currencies). The built-in types handle these cases automatically.
– When making changes to `*.properties` files, **ALWAYS** apply the changes to all relevant locales. This ensures consistency across different language versions of the application.
– **Example:** If you add a new key to `i18n.properties`, also add it to existing translation files like e.g `i18n_en.properties`, `i18n_de.properties`, etc.
– **NEVER** use inline script in HTML
– All application logic must reside in dedicated JS or TS files. Inline `<script>` would violate the recommended CSP settings for UI5 applications.
– Find more information on the UI5 documentation page “Content Security Policy”
### TypeScript: Special Handling for Control Event Handlers
– **Rule:** For any control event handler, import and use the specific event type from the control’s module. The type is typically named `<ControlName>$<EventName>Event`. Notice the “Event” suffix.
– **Example:** For the `press` event of `sap.m.Button`, use `import {Button$PressEvent} from “sap/m/Button”`.
– The event handler then may look like this: `onPress(event: Button$PressEvent): void { […]`.
– **Benefit:** This provides static type checking and autocompletion for event parameters (e.g., `event.getParameter(…)`) without needing manual casting or comments.
– **Version Compatibility:**
– **UI5 >= 1.115.0:** This feature is available and **MUST** be used.
– **UI5 < 1.115.0:** These specific types are **NOT** available. Use the generic `import Event from “sap/ui/base/Event”` as the fallback type.
**Example (UI5 >= 1.115.0):**
“`ts
// Import the specific event type from the control’s module
import { Table$RowSelectionChangeEvent } from “sap/ui/table/Table”;
import Table from “sap/ui/table/Table”;
// … inside a controller class
public onRowSelectionChange(event: Table$RowSelectionChangeEvent): void {
// Correctly typed: getParameter is known and its return value can be inferred
const selectedContext = event.getParameter(“rowContext”);
// …
}
“`
## 2. Tooling and Environment Interaction
An AI agent must understand how to use and interpret the standard UI5 development tools, primarily through the available MCP tools.
– **API Lookup:** To get information on UI5 controls and APIs, **ALWAYS** use the `get_api_reference` tool. This provides direct access to the official UI5 API Reference. Provide it with a path to the current project and it will provide the correct API reference for the UI5 version in use.
– **Code Validation:** To identify issues, **ALWAYS** use the `run_ui5_linter` tool. It detects deprecated APIs, accessibility issues, and other potential bugs.
– **Code Fixes:** To apply fixes suggested by the linter, always confirm with the user first. Then use the `fix` parameter of the `run_ui5_linter` tool. This will automatically correct _some_ of the identified issues. The tool can also provide context information that can be used to manually fix the remaining issues when tasked to do so.
– **Local Server Behavior:** When interacting with the UI5 CLI’s development server, understand that it does **NOT** serve a default index file. You **MUST ALWAYS** reference files by their full path when using the browser (e.g., `http://localhost:8080/index.html`, not `http://localhost:8080/`).
## 3. CAP (Cloud Application Programming Model) Integration
When creating a new UI5 project within a CAP project, a specific set of rules apply to ensure seamless integration.
– **Project Location:** **ALWAYS** create UI5 projects within the `app/` directory of the CAP project root.
– **Service Information:**
– If CDS tools are available to you, **ALWAYS** use them to get information about the definitions, services and their endpoints.
– If no CDS tools are available to you, **ALWAYS** run `cds compile ‘*’` to get information about the definitions and `cds compile ‘*’ –to serviceinfo` to get information about the services and their endpoints.
– **Service Integration:** When creating the UI5 project, **ALWAYS** provide the absolute OData V4 service URL and the target entity set when prompted by the tooling.
– **Plugin Installation:** **ALWAYS** run `npm i -D cds-plugin-ui5` in the CAP project root directory to ensure the latest version of `cds-plugin-ui5` is installed. This plugin automatically handles serving the UI5 applications.
– **Running the Server:**
– **NEVER** run a separate `ui5 serve` or `npm start` command inside the UI5 project folder.
– **ALWAYS** run `cds watch` (or `cds run`) from the **root** of the CAP project. This single command serves both the backend services and all UI5 applications.
– **Data Connection:**
– **NEVER** configure a `ui5-middleware-simpleproxy` in the `ui5.yaml` file to connect to the local CAP service.
– **Why:** The `cds watch` command ensures the UI and the service are served from the same origin (`http://localhost:4004`), making a proxy unnecessary.
– **Accessing the App:** Check the CAP launch page (typically `http://localhost:4004`) for a list of available services and links to the UI5 applications.
get_project_info inspects ui5.yaml and manifest to report framework, version, and libraries.
{
“tool”: “get_project_info”,
“params”: { “projectDir”: “/abs/path/ui5-app” }
}
The response is a bit underwhelming, as I was expecting more information about the project as described in the output format:
{
“projectDir”: “/Users/marianzeis/DEV/mcp-sap-test-2/app/match-management”,
“projectName”: “matchmanagement”,
“projectType”: “application”,
“frameworkLibraries”: []
}
get_version_info pulls version.json from the selected CDN to show latest and LTS.
{
“tool”: “get_version_info”,
“params”: { “framework”: “OpenUI5” }
}
Response:
{
“versions”: {
“latest”: {
“version”: “1.139.0”,
“support”: “Maintenance”,
“lts”: false
},
“active”: {
“version”: “1.139.0”,
“support”: “Maintenance”,
“lts”: false
},
“1.139”: {
“version”: “1.139.0”,
“support”: “Maintenance”,
“lts”: false
},
“1.136”: {
“version”: “1.136.8”,
“support”: “Maintenance”,
“lts”: true
},
“1.133”: {
“version”: “1.133.5”,
“support”: “Maintenance”,
“lts”: false
},
“1.130”: {
“version”: “1.130.11”,
“support”: “Maintenance”,
“lts”: false
},
“1.120”: {
“version”: “1.120.35”,
“support”: “Maintenance”,
“lts”: true
},
“1.108”: {
“version”: “1.108.45”,
“support”: “Maintenance”,
“lts”: true
},
“1.96”: {
“version”: “1.96.43”,
“support”: “Maintenance”,
“lts”: true
},
“1.84”: {
“version”: “1.84.54”,
“support”: “Maintenance”,
“lts”: true
},
“1.71”: {
“version”: “1.71.76”,
“support”: “Maintenance”,
“lts”: true
},
“1.38”: {
“version”: “1.38.65”,
“support”: “Maintenance”,
“lts”: true
}
}
}
run_ui5_linter analyzes the project and can auto-fix; optionally include context information for API references, rule descriptions and migration guides.
{
“tool”: “run_ui5_linter”,
“params”: {
“projectDir”: “/abs/path/ui5-app”,
“fix”: true,
“provideContextInformation”: true
}
}
The response is a complete overview, just like when running the UI5 linter directly. The benefit is that it is fed directly into the LLM so remaining issues can be fixed.
Using these servers in VS Code
You can run all three servers in VS Code. For CAP and Fiori, install globally or use npx and configure your MCP-capable client inside VS Code. If your client cannot be configured, you can still validate functionality by calling the server CLIs directly (for CAP) or by using the tool flows that write files and then reviewing the diffs. For quick inspection of HTTP-based MCP endpoints you can use the MCP Inspector:
npx @modelcontextprotocol/inspector
Which MCP server when?
This overview helps decide which server to use first. You can run them together in one client.
Server
Primary goal
Scope
Local project awareness
Typical use
Notes
@cap-js/mcp-server
Understand and change CAP models safely
CDS model, CAP docs
Yes (compiled CDS)
Search entities/services, check docs before edits
CLI tools available
@SAP-ux/fiori-mcp-server
Create/modify Fiori elements apps
FE app scaffolding and refactoring
Yes (scans workspace)
Add pages, FCL, controller extensions, manifest changes
three-step functionality flow
@ui5/mcp-server
Bootstrap and fix UI5 apps
Templates, API, guidelines, lint fixes
Yes (project inspection)
Create UI5 app, read API, run linter
Find the right official page, API, sample
SAPUI5, CAP, UI5 Tooling, OpenUI5 API, wdi5, SAP Help, SAP Community
No (documentation-first)
Answer questions with sources; verify changes
Hosted endpoints available; consistent result format
First tests in Cursor
In an initial test with all MCP servers, the CAP server performed particularly well.
Based on the recommendations for the MCP server, I created a detailed rules file to better guide the MCP server and the LLM.
Unfortunately, the Fiori tools server did not work, otherwise the Fiori elements apps would have been generated successfully.
A test without the SAP MCP server successfully generated Fiori elements apps.
I think the best way is to combine the MCP SAP Docs server with the MCP servers from SAP and control them with rules so that they work well together.
My rules file which you can use in your project:
# SAP Development Rules for AI Assistants
## MCP Server Usage Rules
### CAP MCP Server (@cap-js/mcp-server)
– You MUST search for CDS definitions, like entities, fields and services (which include HTTP endpoints) with cds-mcp, only if it fails you MAY read *.cds files in the project.
– You MUST search for CAP docs with cds-mcp EVERY TIME you modify CDS models or when using APIs from CAP. Do NOT propose, suggest or make any changes without first checking it.
– Always refer to @cap docs for better information about SAP CAP (Cloud Application Programming) applications.
### Fiori MCP Server (@sap-ux/fiori-mcp-server)
– When asked to create an SAP Fiori elements app check whether the user input can be interpreted as an application organized into one or more pages containing table data or forms.
– When generating or modifying SAP Fiori elements applications on top of CAP services, use the Fiori MCP server if available.
– When attempting to modify SAP Fiori elements applications like adding columns, you must NOT use screen personalization but instead modify the code of the project. First check whether an MCP server provides a suitable function.
– Follow the 3-step workflow: list-functionality → get-functionality-details → execute-functionality.
### UI5 MCP Server (@ui5/mcp-server)
– This tool MUST be called once to retrieve UI5 guidelines before working on any UI5 (SAPUI5/OpenUI5) related task or project.
– Use for UI5 linting, API reference, project information, and version details.
– Always run UI5 linter after making changes and verify no new problems are introduced.
## SAP CAP Development Rules
### Project Initialization
– Always use `cds init` and don’t use `cds init projectname`
– Always create nodejs CAP based applications (don’t add –add, just init is fine)
– Always add `cds lint` after generating the application
– Always enable draft for CAP applications but AVOID draft on composed entities
– Don’t add random samples using `cds add sample`
– MANDATORY: Set up npm workspaces for UI5 applications in package.json:
“`json
{
“workspaces”: [
“app/*”
]
}
“`
### Data Modeling
– If using cuid aspect, a default column ID is added and usually has UUIDs
– When cuid is added to entity, then ID will be uuid, so ensure sample data will have ID type uuid
– Prefer composition over association for child entities in SAP CAP
– Use cds managed aspect wherever necessary and add it to entity for it to work
– Don’t use enums, prefer associated tables with preload configuration data
– For all entities in the data model provide primary keys of type UUID
– When creating sample data in CSV files, all primary keys and foreign keys MUST be in UUID format (e.g., `550e8400-e29b-41d4-a716-446655440001`)
#### CRITICAL: Draft Entity Composition Rules
– NEVER apply @odata.draft.enabled to both parent and child entities in a composition
– Only apply draft to the main/parent entity (e.g., Events but NOT Teams if Events composes Teams)
– Child entities should be managed through the parent’s draft context
– ERROR EXAMPLE: Events @odata.draft.enabled + Teams @odata.draft.enabled + Events composes Teams = BUILD FAILURE
### Value Helps and Views
– For cds views use #TextOnly
– For smaller set of data, prefer fixed values (dropdown) instead of popup help – ValueListWithFixedValues: true
### Testing and Development
– Use `cds build` to find any annotation errors and fix them before testing
– Use `cds watch` to test locally
– After `cds watch`, don’t call `sleep 5 or 3`, it will stop cds watch
– Use browser testing to confirm if it’s working fine and UI looks good
## Fiori Application Generation
### JSON Configuration Template
Always use this configuration structure for Fiori app generation:
“`json
{
“version”: “0.2”,
“floorplan”: “FE_LROP”,
“project”: {
“name”: “app-name”,
“targetFolder”: “/path/to/project”,
“title”: “App Title”,
“description”: “App Description”,
“ui5Version”: “1.132.1”,
“localUI5Version”: “1.82.2”,
“sapux”: true
},
“service”: {
“servicePath”: “/service/path/”,
“capService”: {
“projectPath”: “/path/to/project”,
“serviceName”: “serviceName”,
“serviceCdsPath”: “srv/service.cds”
}
},
“entityConfig”: {
“mainEntity”: {
“entityName”: “EntityName”
},
“generateFormAnnotations”: true
},
“projectType”: “FORM_ENTRY_OBJECT_PAGE”,
“telemetryData”: {
“generationSourceName”: “AI Headless”,
“generationSourceVersion”: “1.18.1”
}
}
“`
### Required Steps for Fiori Generation
1. First generate the JSON config file as shown above
2. Run the command: `yo @sap/fiori:headless “/path/to/config.json” –force`
3. Add necessary annotations in the generated fiori application (usually in annotations.cds file)
4. Check https://github.com/SAP-samples/fiori-elements-feature-showcase for guidance on annotations
### Package Requirements
– Always use node package “yo” with version 4.3.1
– Before installing check if yo is already installed
– Use @sap/generator-fiori for fiori app generation
– CRITICAL: Always install these UI5 dependencies to avoid startup failures:
– `npm install -D @ui5/cli` (required for cds-plugin-ui5)
– `npm install -D @sap/ux-ui5-tooling` (required for advanced UI5 features)
– Always install `npm install -D cds-plugin-ui5` for CAP-UI5 integration
### UI Design Guidelines
– Application typically starts with a List Report page showing data in a table
– Details of specific table row shown in ObjectPage based on the base entity
– ObjectPage can contain table sections based on to-many associations
– Ensure complete UI is generated for requirements and all UI is tested
– Add necessary annotations: Tables for compositions, labels for all fields, value helps, etc.
– Ensure the UI is complete and functional
## Project Management and Documentation
### Product Requirements Document (PRD)
– Always ensure a product requirement document is there (prd.md) with high level requirements
– Status should be “approved” before starting development
– Should be TDD based development -> test after every change
– If PRD is not there, take requirements and generate the PRD
– Initial status should be “pending” – only work when status is “approved”
– Don’t assume anything, first ask user to verify the PRD
### PRD Structure
“`markdown
# Product Requirements Document
## Status: pending/approved
## Requirements
[High level requirements]
## Development Steps
[ ] step 1
[ ] step 2
[ ] step n
[ ] substep 1
[ ] substep 2
“`
– Steps and substeps should be very detailed
– Ensure the whole application is complete – with UI and necessary logic
– After every step completion, mark it as completed [X], for sub and main steps
## Code Quality Rules
### Comments and Documentation
– Don’t remove already existing code comments, may improve them
– Maintain existing documentation structure
– Add meaningful comments for complex logic
### Testing and Quality Assurance
– Always test after every change to ensure the outcome is correct
– Ensure complete UI is generated for the requirements
– All UI must be tested and functional
– Use browser testing MCP to confirm functionality and UI appearance
## Additional Guidelines
### Data Types and Structure
– Each property of an entity must have a proper datatype
– Data model must be suitable for SAP Fiori elements frontend applications
– Must have one main entity and one or more navigation properties to related entities
### Annotations Reference
– For annotation details check https://github.com/SAP-samples/fiori-elements-feature-showcase
– Use proper annotations for tables, labels, value helps, etc.
– Ensure UI completeness through proper annotations
#### CRITICAL: Navigation Property Syntax in Annotations
– ALWAYS use dot notation (.) for navigation properties in CDS annotations
– CORRECT: `group.groupName`, `homeTeam.teamName`, `event.name`
– WRONG: `group/groupName`, `homeTeam/teamName`, `event/name` (OData URL syntax)
– ERROR EXAMPLE: Using ‘/’ will cause “Mismatched ‘/’, expecting ‘,’, ‘.’, ‘}’, ‘#'” compilation errors
### Version Specifications
– Always use UI5 versions: “ui5Version”: “1.132.1”, “localUI5Version”: “1.82.2”
– Keep version consistency across the project
## Development Workflow
1. Create/verify PRD (status: pending → approved)
2. Initialize CAP project with `cds init`
3. Add `cds lint` to the project
4. Create data model with proper entities, compositions, and managed aspects
5. Generate sample data with UUID format for keys
6. Generate Fiori application using 3-step process
7. Add comprehensive annotations
8. Use `cds build` to check for errors
9. Test with `cds watch`
10. Verify UI functionality with browser testing
11. Mark steps as completed in PRD
Remember: Always use MCP servers for their respective domains and follow the specific guidelines for each technology stack.
## Critical Issues & Solutions from Real Development Experience
### UI5 Dependency Resolution Issues
**Problem**: CDS server starts but fails to mount UI5 applications with errors like:
– `Cannot find module ‘@ui5/cli/package.json’`
– `Cannot find module ‘@sap/ux-ui5-tooling/package.json’`
**Root Cause**: Fiori generator creates applications with UI5 tooling requirements not installed in project root
**MANDATORY Solution**:
1. Always install: `npm install -D @ui5/cli @sap/ux-ui5-tooling`
2. Install before generating Fiori applications
3. If applications already exist, install dependencies then restart `cds watch`
### Service Import Issues in Annotations
**Problem**: Cannot import services in annotation files with errors like:
– `Can’t find local module ‘../srv/service-name’`
**Solution**:
– Import services using destructuring: `using { ServiceName } from ‘../srv/service-file’;`
– If import fails, create separate annotation files per service
– Use relative paths correctly from app/ to srv/ directory
### Draft Entity Composition Conflicts
**Problem**: Build error “Composition in draft-enabled entity can’t lead to another entity with @odata.draft.enabled”
**Solution**:
– Only enable draft on parent entities in compositions
– Child entities are automatically managed through parent draft context
– Example: Events (draft enabled) → Teams (no draft) is correct
### npm Workspaces for UI5 Applications
**MANDATORY Setup**:
“`json
{
“workspaces”: [
“app/*”
],
“scripts”: {
“watch-app1”: “cds watch –open app1/webapp/index.html”,
“watch-app2”: “cds watch –open app2/webapp/index.html”
}
}
“`
### Authorization Testing
– Protected endpoints returning “Unauthorized” is CORRECT behavior
– Test public endpoints for anonymous access
– Use different service definitions for different security levels
– @requires at service level, @restrict at entity level
### Troubleshooting Checklist
When CDS server fails to start with Fiori applications:
1. ✅ Check @ui5/cli is installed
2. ✅ Check @sap/ux-ui5-tooling is installed
3. ✅ Check cds-plugin-ui5 is installed
4. ✅ Verify npm workspaces configuration
5. ✅ Check draft entity composition conflicts
6. ✅ Verify annotation syntax (. not / for navigation)
7. ✅ Run `npm audit fix` for security vulnerabilities
### Testing Verification Steps
1. `cds watch` starts without errors
2. http://localhost:4004 shows launch page
3. All UI5 applications listed and accessible
4. Service endpoints return data or proper authorization errors
5. Fiori preview links work for all entities
Quick comparison: SAP MCP servers vs SAP Docs MCP server
Aspect
Official CAP/Fiori/UI5 MCP
SAP Docs MCP (my server)
Startup guidance
Project-aware; returns concrete tools and parameters
Finds the right pages (CAP getting started, UI5 what’s new)
Model and API grounding
CAP: search_model/search_docs; UI5: get_api_reference
Cross-source docs incl. SAP Help and Community posts
Scaffolding
UI5: create_ui5_app; Fiori: generate flow (schema issues in test client)
No scaffolding, documentation-first
Quality gates
UI5 linter with contextual docs and migration guides
Verify answers against official sources
Outcome in this test
CAP and UI5 flows helped; Fiori flow blocked by schema validation → manual FE generation produced object pages only
Docs server supplied confirmation for versions, annotations and FE patterns
Final words
First of all, I want to praise my colleagues at SAP in the UI5, CAP, and Fiori tools teams. Making these MCP servers available as open source is the right decision—it enables not only developers who use BAS, but all developers, including those outside of BTP.
For day-to-day development I prefer a local client with MCP servers. The official CAP, Fiori, and UI5 servers add project awareness and executable actions. Combined with a documentation-first server like my SAP Docs MCP, you can cover both creation and verification without switching to Joule for Developers. You can also use MCP servers with BAS; I will cover this in another blog post.
From my tests: the UI5 server ties linter output to API references and migration guides, closing a common gap where fixes lacked context. The cache under the data directory speeds up repeated queries, but verify version alignment via get_project_info and get_version_info before applying fixes. The Fiori server’s three-step approach makes changes explicit and reviewable, which helps keep pull requests predictable—if you automate this in CI, keep it behind a branch. The CAP server provides safe discovery over the compiled model and a docs search, reducing wrong assumptions about services and endpoints.
It is important to note that these MCP tools were only released this week. Not everything works perfectly yet, but once you start using them, it is hard to work without them. Work with Git so any changes can be reversed if necessary.
The MCP protocol is still new, and it is fair to ask whether it is worth the investment. I think it is promising: it can solve the problem of missing or outdated context for LLMs and, as these servers show, it is not just about context but also about executing the right actions with Fiori tools and CAP.
Links
@cap-js/mcp-server
@sap-ux/fiori-mcp-server
@ui5/mcp-server
UI5 MCP server repository
UI5 MCP server release post
SAP Build introduces MCP servers
CAP MCP server release post
Fiori MCP server repository
CAP MCP server repository
SAP published MCP servers for UI5, CAP, and Fiori tools. For background and official positioning, see the release post overview SAP Build introduces MCP servers.The SAP Build article positions MCP as the standard bridge from coding assistants to SAP tools and support across popular IDE agents like Cursor, Windsurf, GitHub Copilot, Cline, and Claude Code. The emphasis is on best‑practice scaffolds, guardrails aligned to BTP, and consistent tool behavior across the portfolio.This post is a hands‑on review, not another introduction. I focus on what matters when you actually use these servers locally, how they complement my SAP Docs MCP server, and where the current limits are. My Blog Posts about MCP can be found here.Why the official CAP, Fiori, and UI5 MCP servers matterSAP now provides MCP servers focused on concrete development tasks in CAP, Fiori tools, and UI5. They complement a documentation-first server like my SAP Docs MCP by giving the AI project awareness and executable workflows. In practice, this means better results directly in your editor, without relying on Joule for Developers.CAP MCP serverPackage: @cap-js/mcp-server.GitHub: github.com/cap-js/mcp-server.Release background and usage intent are covered in Boost your CAP Development with AI: Introducing the MCP Server for CAP.What it does: gives LLMs a fuzzy search over your compiled CDS model (entities, services, annotations, HTTP endpoints) and a semantic search over CAP docs (similar to my SAP Docs MCP server). The goal is agentic coding for CAP projects with guaranteed grounding to your model and the official guide.Install:npm i -g @cap-js/mcp-serverClient config (example VS Code):{
“mcpServers”: {
“cds-mcp”: {
“command”: “cds-mcp”,
“args”: [],
“env”: {}
}
}
}Rules (recommended in your AGENTS.md .cursorrules or depending on the client):- You MUST search for CDS definitions, like entities, fields and services (which include HTTP endpoints) with cds-mcp, only if it fails you MAY read *.cds files in the project.- You MUST search for CAP docs with cds-mcp EVERY TIME you modify CDS models or when using APIs from CAP. Do NOT propose, suggest or make any changes without first checking it.CLI usage for quick tests:# Search CDS model
cds-mcp search_model . Books entity
# Search CAP docs
cds-mcp search_docs “how to add columns to a select statement in CAP Node.js” 1CAP tools in detailsearch_model returns CSN definitions with elements, annotations, file locations and HTTP endpoints. Useful to build queries or OData URLs.{
“tool”: “search_model”,
“params”: {
“projectPath”: “/absolute/path/to/cap/project”,
“name”: “Books”,
“kind”: “entity”,
“topN”: 3,
“namesOnly”: false
}
}For a sample project of mine, the response looks like this:[
{
“kind”: “entity”,
“includes”: [
“cuid”,
“managed”
],
“elements”: {
“ID”: {
“key”: true,
“type”: “cds.UUID”
},
“createdAt”: {
“@cds.on.insert”: {
“=”: “$now”
},
“@UI.HiddenFilter”: true,
“@UI.ExcludeFromNavigationContext”: true,
“@Core.Immutable”: true,
“@title”: “{i18n>CreatedAt}”,
“@readonly”: true,
“type”: “cds.Timestamp”,
“@Core.Computed”: true,
“@Common.Label”: “{i18n>CreatedAt}”
},
“createdBy”: {
“@cds.on.insert”: {
“=”: “$user”
},
“@UI.HiddenFilter”: true,
“@UI.ExcludeFromNavigationContext”: true,
“@Core.Immutable”: true,
“@title”: “{i18n>CreatedBy}”,
“@readonly”: true,
“@description”: “{i18n>UserID.Description}”,
“type”: “cds.String”,
“length”: 255,
“@Core.Computed”: true,
“@Common.Label”: “{i18n>CreatedBy}”,
“@Core.Description”: “{i18n>UserID.Description}”
},
“modifiedAt”: {
“@cds.on.insert”: {
“=”: “$now”
},
“@cds.on.update”: {
“=”: “$now”
},
“@UI.HiddenFilter”: true,
“@UI.ExcludeFromNavigationContext”: true,
“@title”: “{i18n>ChangedAt}”,
“@readonly”: true,
“type”: “cds.Timestamp”,
“@Core.Computed”: true,
“@Common.Label”: “{i18n>ChangedAt}”
},
“modifiedBy”: {
“@cds.on.insert”: {
“=”: “$user”
},
“@cds.on.update”: {
“=”: “$user”
},
“@UI.HiddenFilter”: true,
“@UI.ExcludeFromNavigationContext”: true,
“@title”: “{i18n>ChangedBy}”,
“@readonly”: true,
“@description”: “{i18n>UserID.Description}”,
“type”: “cds.String”,
“length”: 255,
“@Core.Computed”: true,
“@Common.Label”: “{i18n>ChangedBy}”,
“@Core.Description”: “{i18n>UserID.Description}”
},
“username”: {
“@mandatory”: true,
“type”: “cds.String”,
“length”: 100,
“$location”: {
“file”: “db/schema.cds”,
“line”: 7,
“col”: 3
},
“@Common.FieldControl”: {
“#”: “Mandatory”
}
},
“email”: {
“@mandatory”: true,
“type”: “cds.String”,
“length”: 255,
“$location”: {
“file”: “db/schema.cds”,
“line”: 8,
“col”: 3
},
“@Common.FieldControl”: {
“#”: “Mandatory”
}
},
“firstName”: {
“type”: “cds.String”,
“length”: 100,
“$location”: {
“file”: “db/schema.cds”,
“line”: 9,
“col”: 3
}
},
“lastName”: {
“type”: “cds.String”,
“length”: 100,
“$location”: {
“file”: “db/schema.cds”,
“line”: 10,
“col”: 3
}
},
“role”: {
“type”: “cds.Association”,
“target”: “volleyball.tournament.UserRoles”,
“keys”: [
{
“ref”: [
“code”
],
“$generatedFieldName”: “role_code”
}
],
“$location”: {
“file”: “db/schema.cds”,
“line”: 11,
“col”: 3
}
},
“role_code”: {
“type”: “cds.String”,
“@odata.foreignKey4”: “role”
},
“isActive”: {
“type”: “cds.Boolean”,
“default”: {
“val”: true
},
“$location”: {
“file”: “db/schema.cds”,
“line”: 12,
“col”: 3
}
}
},
“$location”: {
“file”: “db/schema.cds”,
“line”: 6,
“col”: 8
},
“name”: “volleyball.tournament.Users”
},
{
“kind”: “entity”,
“@cds.autoexpose”: true,
“@cds.persistence.skip”: “if-unused”,
“@UI.Identification”: [
{
“Value”: {
“=”: “name”
}
}
],
“@cds.odata.valuelist”: true,
“includes”: [
“sap.common.CodeList”
],
“elements”: {
“name”: {
“@title”: “{i18n>Name}”,
“localized”: true,
“type”: “cds.String”,
“length”: 255,
“@Common.Label”: “{i18n>Name}”
},
“descr”: {
“@title”: “{i18n>Description}”,
“localized”: true,
“type”: “cds.String”,
“length”: 1000,
“@Common.Label”: “{i18n>Description}”
},
“code”: {
“key”: true,
“type”: “cds.String”,
“enum”: {
“Admin”: {
“val”: “ADMIN”,
“$location”: {
“file”: “db/schema.cds”,
“line”: 17,
“col”: 5
}
},
“EventCreator”: {
“val”: “EVENT_CREATOR”,
“$location”: {
“file”: “db/schema.cds”,
“line”: 18,
“col”: 5
}
},
“ResultsInputer”: {
“val”: “RESULTS_INPUTER”,
“$location”: {
“file”: “db/schema.cds”,
“line”: 19,
“col”: 5
}
},
“Reader”: {
“val”: “READER”,
“$location”: {
“file”: “db/schema.cds”,
“line”: 20,
“col”: 5
}
}
},
“$location”: {
“file”: “db/schema.cds”,
“line”: 16,
“col”: 7
}
},
“texts”: {
“type”: “cds.Composition”,
“cardinality”: {
“max”: “*”
},
“target”: “volleyball.tournament.UserRoles.texts”,
“on”: [
{
“ref”: [
“texts”,
“code”
]
},
“=”,
{
“ref”: [
“code”
]
}
]
},
“localized”: {
“type”: “cds.Association”,
“target”: “volleyball.tournament.UserRoles.texts”,
“on”: [
{
“ref”: [
“localized”,
“code”
]
},
“=”,
{
“ref”: [
“code”
]
},
“and”,
{
“ref”: [
“localized”,
“locale”
]
},
“=”,
{
“ref”: [
“$user”,
“locale”
]
}
]
}
},
“$location”: {
“file”: “db/schema.cds”,
“line”: 15,
“col”: 8
},
“$localized”: true,
“name”: “volleyball.tournament.UserRoles”
}
]search_docs searches CAP docs locally (embeddings) and returns relevant chunks.{
“tool”: “search_docs”,
“params”: { “query”: “draft activation action”, “maxResults”: 3 }
}The response to the above query looks like this: Fiori Support > Lean Draft > Programmatic Invocation of Draft Actions <Beta />
API, draft actions, JavaScript, Fiori, programmatic, service implementation
Demonstrates how to programmatically invoke Fiori draft actions using ApplicationService API: creating, discarding, editing, and saving (activating) drafts.
“`js
await srv.new(MyEntity.drafts, data) // create new draft
await srv.discard(MyEntity.drafts, keys) // discard draft
await srv.edit(MyEntity, keys) // create draft from active instance
await srv.new(MyEntity.drafts).for(keys) // same as above
await srv.save(MyEntity.drafts, keys) // activate draft
“`
—
Fiori Drafts > Activating Drafts
drafts, Java, event handler, CREATE, validation
Registers a @Before handler for the CREATE event. Used to validate user input or entity state before an active entity is created or updated as part of draft activation (Save action). Applies to activation flow of SAP Fiori draft-enabled entities.
“`java
@Before
public void validateOrderItem(CdsCreateEventContext context, OrderItems orderItem) {
// Add validation logic
}
“`
—
Fiori Support > Lean Draft > Handlers Registration
draft-specific events, event handler, Fiori, JavaScript, CANCEL, EDIT, NEW, SAVE
Illustrates how to add custom logic for specific draft events: NEW, CANCEL, EDIT, and SAVE. These let you react to various points in the Fiori draft process, including draft creation, discard, editing, and persisting changes.
“`js
// When a new draft is created
srv.on(‘NEW’, ‘MyEntity.drafts’, /*…*/)
// When a draft is discarded
srv.on(‘CANCEL’, ‘MyEntity.drafts’, /*…*/)
// When a new draft is created from an active instance
srv.on(‘EDIT’, ‘MyEntity’, /*…*/)
// When the active entity is changed
srv.on(‘SAVE’, ‘MyEntity’, /*…*/)
“`Fiori MCP serverPackage: @sap-ux/fiori-mcp-server.GitHub Repo: github.com/SAP/open-ux-tools/packages/fiori-mcp-serverRelease Blog Post: SAP Fiori Tools Update – First Release of the SAP Fiori MCP Server for Agentic AI WorkflowsWhat it does: generates or modifies SAP Fiori apps, including adding pages, controller extensions, FCL, and manifest changes. It returns required parameters for each functionality and executes the change.This MCP server also recommends adding a rules markdown file with the following content, so the LLM knows how to use the server better:- When asked to create an SAP Fiori elements app check whether the user input can be interpreted as an application organized into one or more pages containing table data or forms, these can be translated into a SAP Fiori elements application, else ask the user for suitable input.
– The application typically starts with a List Report page showing the data of the base entity of the application in a table. Details of a specific table row are shown in the ObjectPage. This first Object Page is therefore based on the base entity of the application.
– An Object Page can contain one or more table sections based on to-many associations of its entity type. The details of a table section row can be shown in an another Object Page based on the associations target entity.
– The data model must be suitable for usage in a SAP Fiori elements frontend application. So there must be one main entity and one or more navigation properties to related entities.
– Each property of an entity must have a proper datatype.
– For all entities in the data model provide primary keys of type UUID.
– When creating sample data in CSV files, all primary keys and foreign keys MUST be in UUID format (e.g., `550e8400-e29b-41d4-a716-446655440001`).
– When generating or modifying the SAP Fiori elements application on top of the CAP service use the Fiori MCP server if available.
– When attempting to modify the SAP Fiori elements application like adding columns you must not use the screen personalization but instead modify the code of the project, before this first check whether an MCP server provides a suitable function.
– When previewing the SAP Fiori elements application use the most specific script for the app in the `package.json`.Use via npx (no install needed):{
“mcpServers”: {
“fiori-mcp”: {
“command”: “npx”,
“args”: [“–yes”,”@sap-ux/fiori-mcp-server@latest”, “fiori-mcp”]
}
}
}Main tools: list-fiori-apps, list-functionality, get-functionality-details, execute-functionality. The typical flow is 1) list-functionality, 2) get-functionality-details, 3) execute-functionality.Fiori tools and 3-step workflowDiscovery:{
“tool”: “list-fiori-apps”,
“params”: { “workspaceDir”: “/abs/path/to/mono” }
}The response for my sample repo looks like this:{
“applications”: [
{
“name”: “resultsdashboard”,
“appPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/results-dashboard”,
“projectPath”: “/Users/marianzeis/DEV/mcp-sap-test”,
“projectType”: “CAPNodejs”,
“odataVersion”: “4.0”
},
{
“name”: “eventmanagement”,
“appPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/event-management”,
“projectPath”: “/Users/marianzeis/DEV/mcp-sap-test”,
“projectType”: “CAPNodejs”,
“odataVersion”: “4.0”
},
{
“name”: “matchresults”,
“appPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/match-results”,
“projectPath”: “/Users/marianzeis/DEV/mcp-sap-test”,
“projectType”: “CAPNodejs”,
“odataVersion”: “4.0”
},
{
“name”: “teammanagement”,
“appPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/team-management”,
“projectPath”: “/Users/marianzeis/DEV/mcp-sap-test”,
“projectType”: “CAPNodejs”,
“odataVersion”: “4.0”
}
]
}Step 1:{
“tool”: “list-functionality”,
“params”: { “appPath”: “/abs/path/to/app” }
}The redacted response is worth for my Fiori elements app about 13k tokens:{
“applicationPath”: “/Users/marianzeis/DEV/mcp-sap-test/app/event-management”,
“functionalities”: [
{
“functionalityId”: “add-page”,
“description”: “Create new fiori elements page like ListReport, ObjectPage, CustomPage”
},
{
“functionalityId”: “generate-fiori-ui-app”,
“description”: “Creates (generates) a new SAP Fiori UI application within an existing CAP project.n Crucially, you must first construct the appGenConfig JSON argument.n To do this, you **MUST** use the ***CDS MCP*** to search the model for service definitions, entities, associations, and UI annotations.n As a fallback, only if no such tool is available, you should manually read and parse all .cds files in the projectPath to extract this information.n The data obtained from either method must then be formatted into a JSON object and passed as the appGenConfig parameter.”
},
{
“functionalityId”: “delete-page”,
“description”: “Remove existing fiori elements page from the application”
},
{
“functionalityId”: “create-controller-extension”,
“description”: “Add new controller extension by creating javascript or typescript file and updates manifest.json with entry. Controller extensions allow users to extensiate default behaviour with custom controllers code.”
},
{
“functionalityId”: [
“settings”,
“path”
],
“description”: “Represents a prefix that is prepended in front of the viewName”
},
{
“functionalityId”: [
“settings”,
“viewType”
],
“description”: “standard view type of views”
},
{
“functionalityId”: [
“settings”,
“title”
],
“description”: “Defines the title for the application.”
},
{
“functionalityId”: [
“settings”,
“description”
],
“description”: “Defines the description for the application.”
},
{
“functionalityId”: [
“settings”,
“flexEnabled”
],
“description”: “Enables key user adaptation for an application.”
},
{
“functionalityId”: [
“settings”,
“cloudDevAdaptationStatus”
],
“description”: “Represents the release status for the developer adaptation in the cloud (relevant for SAP internal only). The supported types are released, deprecated, obsolete, no value means not released.”
},
{
“functionalityId”: [
“settings”,
“flexibleColumnLayout”
],
“description”: “The flexible column layout allows users to see more details on the page, and to expand and collapse the screen areas.”
},
{
“functionalityId”: [
“settings”,
“flexibleColumnLayout”,
“limitFCLToTwoColumns”
],
“description”: “Determines whether the Flexible Column Layout is limited to two columns. If set to true, the third level will be displayed in full screen mode rather than a third column.”
},
{
“functionalityId”: [
“settings”,
“flexibleColumnLayout”,
“defaultTwoColumnLayoutType”
],
“description”: “Default Two Column Layout Type”
},
{
“functionalityId”: [
“settings”,
“flexibleColumnLayout”,
“defaultThreeColumnLayoutType”
],
“description”: “Default Three Column Layout Type”
},
{
“functionalityId”: [
“settings”,
“controllerExtensions”
],
“description”: “Controller extensions allow users to extensiate default behaviour with custom controllers code.”
},
{
“functionalityId”: [
“settings”,
“hideDraft”
],
“description”: “Hidden draft features.”
},
{
“functionalityId”: [
“settings”,
“hideDraft”,
“enabled”
],
“description”: “All features related to draft handling can be hidden from the UI while the draft functionality remains active in the background. To achieve this, enable the ‘Hide Draft’ property.”
},
{
“functionalityId”: [
“settings”,
“hideDraft”,
“stayOnCurrentPageAfterSave”
],
“description”: “Determines whether to stay on the current page after saving an object.nTo ensure a consistent experience, set this and ‘Stay On Current Page After Cancel’ to the same value.”
},Step 2:{
“tool”: “get-functionality-details”,
“params”: { “appPath”: “/abs/path/to/app”, “functionalityId”: “add-page” }
}Here is a response for the functionality “add-page”:{
“functionalityId”: “add-page”,
“name”: “Add new page to application by updating manifest.json”,
“description”: “Create new fiori elements page like ListReport, ObjectPage, CustomPage”,
“parameters”: [
{
“id”: “parentPage”,
“type”: “string”,
“description”: “Parent page is id/name of parent page. First try to extract parent page from user input in a format defined in example, if not possible suggest content defined in options”,
“options”: [
“EventsObjectPage”
],
“required”: true,
“examples”: [
“parentPage: EventsObjectPage”
]
},
{
“id”: “pageNavigation”,
“type”: “string”,
“description”: “Page navigation option for parent page. First try to extract navigation option from user input in a format defined in example, if not possible suggest content defined in options”,
“options”: [
“for EventsObjectPage: available navigation(s) is/are one of: teams, groups, matches”
],
“examples”: [
“pageNavigation: teams”
],
“required”: true
},
{
“id”: “pageType”,
“type”: “string”,
“description”: “Type of page to be created. First try to extract page type from user input in a format defined in example, if not possible suggest content defined in options.”,
“options”: [
“ObjectPage”,
“ListReport”,
“CustomPage”,
“FPMCustomPage”,
“AnalyticalListPage”
],
“examples”: [
“pageType: ObjectPage”
],
“required”: true
}
]
}The problem here is that the MCP server returns an error:{“error”: “MCP error -32602: Structured content does not
match the tool’s output schema: data should have
required property ‘.id'”}I tested a few different functionalities and always saw the same error, so unfortunately this can’t be used yet.Step 3:{
“tool”: “execute-functionality”,
“params”: {
“appPath”: “/abs/path/to/app”,
“functionalityId”: “add-page”,
“parameters”: {
“pageType”: “ObjectPage”,
“entity”: “Books”,
“navigation”: “toAuthors”
}
}
}As I got stuck at step 2, I unfortunately couldn’t properly test step 3.UI5 MCP serverPackage: @ui5/mcp-server.GitHub: github.com/UI5/mcp-serverRelease Blog Post:Give Your AI Agent Some Tools: Introducing the UI5 MCP ServerWhat it does: scaffolds UI5 apps, fetches API reference and guidelines, inspects an existing UI5 project, retrieves framework version info, and runs the UI5 linter for actionable fixes.Quick client config:{
“mcpServers”: {
“ui5mcp”: {
“command”: “npx”,
“args”: [“@ui5/mcp-server”]
}
}
}Environment options (examples):{
“mcpServers”: {
“ui5mcp”: {
“command”: “npx”,
“args”: [“@ui5/mcp-server”],
“env”: {
“UI5_MCP_SERVER_ALLOWED_ODATA_DOMAINS”: “localhost, services.odata.org”,
“UI5_LOG_LVL”: “verbose”
}
}
}
}Available tools: create_ui5_app, get_api_reference, get_guidelines, get_project_info, get_version_info, run_ui5_linter.UI5 tools in detailcreate_ui5_app scaffolds a project from built-in templates (JS or TS). It can also preconfigure an OData V4 model if you pass a service URL that matches the allowed domains.{
“tool”: “create_ui5_app”,
“params”: {
“projectDir”: “/abs/path/new-ui5-app”,
“template”: “ts”,
“oDataV4Url”: “https://services.odata.org/V4/OData/OData.svc/”
}
}get_api_reference downloads and caches api.json files for the configured UI5 version and returns focused API info for a symbol.{
“tool”: “get_api_reference”,
“params”: { “projectDir”: “/abs/path/ui5-app”, “symbol”: “sap.m.Button#text” }
}In my tests this did not work. One app was using version 1.108.1 in ui5.yaml, and using this tool I got the following response:Failed to fetch resource from CDN. Error: The requested resource does not exist for URL: https://ui5.sap.com/1.108.1/resources/sap-ui-version.jsonMy second Fiori elements app was using SAPUI5 version 1.136.7. The API reference tool gets the reference from the OpenUI5 SDK, which has the current maximum patch of 1.136.5. Because of this I got the error:Failed to fetch resource from CDN. Error: The requested resource does not exist for URL: https://sdk.openui5.org/1.136.7/resources/sap-ui-version.jsonEven after changing the version in the manifest I could not get the tool to work. It was still fetching the wrong version.get_guidelines returns a curated markdown with UI5 and CAP development guidelines for agents.{
“tool”: “get_guidelines”,
“params”: {}
}Response:# UI5 Development Guidelines
> *This document outlines the fundamental rules and best practices an AI agent must follow when developing or modifying SAPUI5 projects. Adherence to these guidelines is critical for creating modern, maintainable, and performant applications.*
## 1. Coding Guidelines
– **NEVER** use global variables to access UI5 framework objects (e.g., `sap.m.Button`). Instead, explicitly declare all dependencies, so that they are loaded asynchronously before your code executes.
– in Javascript: Using `sap.ui.define` at the top of the file (which also registers the file as a UI5 module) or dynamically using `sap.ui.require`
– in TypeScript: Using ES6 `import` statements
– in XML:
– For controls it is sufficient to declare the corresponding XML tag (e.g. `<m:Button></m:Button>`). The XML Template engine will load the corresponding resource automatically.
– However, when referring to programmatic API like formatters or types, those must be “imported” using a `core:require` directive
– Example
“`xml
<ObjectListItem
core:require=”{
Currency: ‘sap/ui/model/type/Currency’
}”
title=”{invoice>Quantity} x {invoice>ProductName}”
number=”{
parts: [
‘invoice>ExtendedPrice’,
‘view>/currency’
],
type: ‘Currency’,
formatOptions: {
showMeasure: false
}
}”
numberUnit=”{view>/currency}”/>
“`
– Find more information on the UI5 documentation page “Require Modules in XML View and Fragment”
– **ALWAYS** use the `sap/ui/core/ComponentSupport` module to initialize a UI5 application/component in an HTML page
– Example:
“`html
<!– index.html –>
<script id=”sap-ui-bootstrap”
src=”resources/sap-ui-core.js”
data-sap-ui-on-init=”module:sap/ui/core/ComponentSupport”
data-sap-ui-async=”true”
data-sap-ui-resource-roots='{ “my.app”: “./” }’
data-…=”…”>
</script>
“`
– Find more information on the UI5 documentation page “Declarative API for Initial Components”
– **ALWAYS** use data binding in views to connect UI controls to data or i18n models.
– When binding data from OData services, **NEVER** use custom formatters for standard data types (e.g., dates, numbers, currencies). The built-in types handle these cases automatically.
– When making changes to `*.properties` files, **ALWAYS** apply the changes to all relevant locales. This ensures consistency across different language versions of the application.
– **Example:** If you add a new key to `i18n.properties`, also add it to existing translation files like e.g `i18n_en.properties`, `i18n_de.properties`, etc.
– **NEVER** use inline script in HTML
– All application logic must reside in dedicated JS or TS files. Inline `<script>` would violate the recommended CSP settings for UI5 applications.
– Find more information on the UI5 documentation page “Content Security Policy”
### TypeScript: Special Handling for Control Event Handlers
– **Rule:** For any control event handler, import and use the specific event type from the control’s module. The type is typically named `<ControlName>$<EventName>Event`. Notice the “Event” suffix.
– **Example:** For the `press` event of `sap.m.Button`, use `import {Button$PressEvent} from “sap/m/Button”`.
– The event handler then may look like this: `onPress(event: Button$PressEvent): void { […]`.
– **Benefit:** This provides static type checking and autocompletion for event parameters (e.g., `event.getParameter(…)`) without needing manual casting or comments.
– **Version Compatibility:**
– **UI5 >= 1.115.0:** This feature is available and **MUST** be used.
– **UI5 < 1.115.0:** These specific types are **NOT** available. Use the generic `import Event from “sap/ui/base/Event”` as the fallback type.
**Example (UI5 >= 1.115.0):**
“`ts
// Import the specific event type from the control’s module
import { Table$RowSelectionChangeEvent } from “sap/ui/table/Table”;
import Table from “sap/ui/table/Table”;
// … inside a controller class
public onRowSelectionChange(event: Table$RowSelectionChangeEvent): void {
// Correctly typed: getParameter is known and its return value can be inferred
const selectedContext = event.getParameter(“rowContext”);
// …
}
“`
## 2. Tooling and Environment Interaction
An AI agent must understand how to use and interpret the standard UI5 development tools, primarily through the available MCP tools.
– **API Lookup:** To get information on UI5 controls and APIs, **ALWAYS** use the `get_api_reference` tool. This provides direct access to the official UI5 API Reference. Provide it with a path to the current project and it will provide the correct API reference for the UI5 version in use.
– **Code Validation:** To identify issues, **ALWAYS** use the `run_ui5_linter` tool. It detects deprecated APIs, accessibility issues, and other potential bugs.
– **Code Fixes:** To apply fixes suggested by the linter, always confirm with the user first. Then use the `fix` parameter of the `run_ui5_linter` tool. This will automatically correct _some_ of the identified issues. The tool can also provide context information that can be used to manually fix the remaining issues when tasked to do so.
– **Local Server Behavior:** When interacting with the UI5 CLI’s development server, understand that it does **NOT** serve a default index file. You **MUST ALWAYS** reference files by their full path when using the browser (e.g., `http://localhost:8080/index.html`, not `http://localhost:8080/`).
## 3. CAP (Cloud Application Programming Model) Integration
When creating a new UI5 project within a CAP project, a specific set of rules apply to ensure seamless integration.
– **Project Location:** **ALWAYS** create UI5 projects within the `app/` directory of the CAP project root.
– **Service Information:**
– If CDS tools are available to you, **ALWAYS** use them to get information about the definitions, services and their endpoints.
– If no CDS tools are available to you, **ALWAYS** run `cds compile ‘*’` to get information about the definitions and `cds compile ‘*’ –to serviceinfo` to get information about the services and their endpoints.
– **Service Integration:** When creating the UI5 project, **ALWAYS** provide the absolute OData V4 service URL and the target entity set when prompted by the tooling.
– **Plugin Installation:** **ALWAYS** run `npm i -D cds-plugin-ui5` in the CAP project root directory to ensure the latest version of `cds-plugin-ui5` is installed. This plugin automatically handles serving the UI5 applications.
– **Running the Server:**
– **NEVER** run a separate `ui5 serve` or `npm start` command inside the UI5 project folder.
– **ALWAYS** run `cds watch` (or `cds run`) from the **root** of the CAP project. This single command serves both the backend services and all UI5 applications.
– **Data Connection:**
– **NEVER** configure a `ui5-middleware-simpleproxy` in the `ui5.yaml` file to connect to the local CAP service.
– **Why:** The `cds watch` command ensures the UI and the service are served from the same origin (`http://localhost:4004`), making a proxy unnecessary.
– **Accessing the App:** Check the CAP launch page (typically `http://localhost:4004`) for a list of available services and links to the UI5 applications.get_project_info inspects ui5.yaml and manifest to report framework, version, and libraries.{
“tool”: “get_project_info”,
“params”: { “projectDir”: “/abs/path/ui5-app” }
}The response is a bit underwhelming, as I was expecting more information about the project as described in the output format:{
“projectDir”: “/Users/marianzeis/DEV/mcp-sap-test-2/app/match-management”,
“projectName”: “matchmanagement”,
“projectType”: “application”,
“frameworkLibraries”: []
}get_version_info pulls version.json from the selected CDN to show latest and LTS.{
“tool”: “get_version_info”,
“params”: { “framework”: “OpenUI5” }
}Response:{
“versions”: {
“latest”: {
“version”: “1.139.0”,
“support”: “Maintenance”,
“lts”: false
},
“active”: {
“version”: “1.139.0”,
“support”: “Maintenance”,
“lts”: false
},
“1.139”: {
“version”: “1.139.0”,
“support”: “Maintenance”,
“lts”: false
},
“1.136”: {
“version”: “1.136.8”,
“support”: “Maintenance”,
“lts”: true
},
“1.133”: {
“version”: “1.133.5”,
“support”: “Maintenance”,
“lts”: false
},
“1.130”: {
“version”: “1.130.11”,
“support”: “Maintenance”,
“lts”: false
},
“1.120”: {
“version”: “1.120.35”,
“support”: “Maintenance”,
“lts”: true
},
“1.108”: {
“version”: “1.108.45”,
“support”: “Maintenance”,
“lts”: true
},
“1.96”: {
“version”: “1.96.43”,
“support”: “Maintenance”,
“lts”: true
},
“1.84”: {
“version”: “1.84.54”,
“support”: “Maintenance”,
“lts”: true
},
“1.71”: {
“version”: “1.71.76”,
“support”: “Maintenance”,
“lts”: true
},
“1.38”: {
“version”: “1.38.65”,
“support”: “Maintenance”,
“lts”: true
}
}
}run_ui5_linter analyzes the project and can auto-fix; optionally include context information for API references, rule descriptions and migration guides.{
“tool”: “run_ui5_linter”,
“params”: {
“projectDir”: “/abs/path/ui5-app”,
“fix”: true,
“provideContextInformation”: true
}
}The response is a complete overview, just like when running the UI5 linter directly. The benefit is that it is fed directly into the LLM so remaining issues can be fixed.Using these servers in VS CodeYou can run all three servers in VS Code. For CAP and Fiori, install globally or use npx and configure your MCP-capable client inside VS Code. If your client cannot be configured, you can still validate functionality by calling the server CLIs directly (for CAP) or by using the tool flows that write files and then reviewing the diffs. For quick inspection of HTTP-based MCP endpoints you can use the MCP Inspector:npx @modelcontextprotocol/inspectorWhich MCP server when?This overview helps decide which server to use first. You can run them together in one client.ServerPrimary goalScopeLocal project awarenessTypical useNotes@cap-js/mcp-serverUnderstand and change CAP models safelyCDS model, CAP docsYes (compiled CDS)Search entities/services, check docs before editsCLI tools available@SAP-ux/fiori-mcp-serverCreate/modify Fiori elements appsFE app scaffolding and refactoringYes (scans workspace)Add pages, FCL, controller extensions, manifest changesthree-step functionality flow@ui5/mcp-serverBootstrap and fix UI5 appsTemplates, API, guidelines, lint fixesYes (project inspection)Create UI5 app, read API, run linter SAP Docs MCPFind the right official page, API, sampleSAPUI5, CAP, UI5 Tooling, OpenUI5 API, wdi5, SAP Help, SAP CommunityNo (documentation-first)Answer questions with sources; verify changesHosted endpoints available; consistent result formatFirst tests in CursorIn an initial test with all MCP servers, the CAP server performed particularly well.Based on the recommendations for the MCP server, I created a detailed rules file to better guide the MCP server and the LLM.Unfortunately, the Fiori tools server did not work, otherwise the Fiori elements apps would have been generated successfully.A test without the SAP MCP server successfully generated Fiori elements apps.I think the best way is to combine the MCP SAP Docs server with the MCP servers from SAP and control them with rules so that they work well together.My rules file which you can use in your project:# SAP Development Rules for AI Assistants
## MCP Server Usage Rules
### CAP MCP Server (@cap-js/mcp-server)
– You MUST search for CDS definitions, like entities, fields and services (which include HTTP endpoints) with cds-mcp, only if it fails you MAY read *.cds files in the project.
– You MUST search for CAP docs with cds-mcp EVERY TIME you modify CDS models or when using APIs from CAP. Do NOT propose, suggest or make any changes without first checking it.
– Always refer to @cap docs for better information about SAP CAP (Cloud Application Programming) applications.
### Fiori MCP Server (@sap-ux/fiori-mcp-server)
– When asked to create an SAP Fiori elements app check whether the user input can be interpreted as an application organized into one or more pages containing table data or forms.
– When generating or modifying SAP Fiori elements applications on top of CAP services, use the Fiori MCP server if available.
– When attempting to modify SAP Fiori elements applications like adding columns, you must NOT use screen personalization but instead modify the code of the project. First check whether an MCP server provides a suitable function.
– Follow the 3-step workflow: list-functionality → get-functionality-details → execute-functionality.
### UI5 MCP Server (@ui5/mcp-server)
– This tool MUST be called once to retrieve UI5 guidelines before working on any UI5 (SAPUI5/OpenUI5) related task or project.
– Use for UI5 linting, API reference, project information, and version details.
– Always run UI5 linter after making changes and verify no new problems are introduced.
## SAP CAP Development Rules
### Project Initialization
– Always use `cds init` and don’t use `cds init projectname`
– Always create nodejs CAP based applications (don’t add –add, just init is fine)
– Always add `cds lint` after generating the application
– Always enable draft for CAP applications but AVOID draft on composed entities
– Don’t add random samples using `cds add sample`
– MANDATORY: Set up npm workspaces for UI5 applications in package.json:
“`json
{
“workspaces”: [
“app/*”
]
}
“`
### Data Modeling
– If using cuid aspect, a default column ID is added and usually has UUIDs
– When cuid is added to entity, then ID will be uuid, so ensure sample data will have ID type uuid
– Prefer composition over association for child entities in SAP CAP
– Use cds managed aspect wherever necessary and add it to entity for it to work
– Don’t use enums, prefer associated tables with preload configuration data
– For all entities in the data model provide primary keys of type UUID
– When creating sample data in CSV files, all primary keys and foreign keys MUST be in UUID format (e.g., `550e8400-e29b-41d4-a716-446655440001`)
#### CRITICAL: Draft Entity Composition Rules
– NEVER apply @odata.draft.enabled to both parent and child entities in a composition
– Only apply draft to the main/parent entity (e.g., Events but NOT Teams if Events composes Teams)
– Child entities should be managed through the parent’s draft context
– ERROR EXAMPLE: Events @odata.draft.enabled + Teams @odata.draft.enabled + Events composes Teams = BUILD FAILURE
### Value Helps and Views
– For cds views use #TextOnly
– For smaller set of data, prefer fixed values (dropdown) instead of popup help – ValueListWithFixedValues: true
### Testing and Development
– Use `cds build` to find any annotation errors and fix them before testing
– Use `cds watch` to test locally
– After `cds watch`, don’t call `sleep 5 or 3`, it will stop cds watch
– Use browser testing to confirm if it’s working fine and UI looks good
## Fiori Application Generation
### JSON Configuration Template
Always use this configuration structure for Fiori app generation:
“`json
{
“version”: “0.2”,
“floorplan”: “FE_LROP”,
“project”: {
“name”: “app-name”,
“targetFolder”: “/path/to/project”,
“title”: “App Title”,
“description”: “App Description”,
“ui5Version”: “1.132.1”,
“localUI5Version”: “1.82.2”,
“sapux”: true
},
“service”: {
“servicePath”: “/service/path/”,
“capService”: {
“projectPath”: “/path/to/project”,
“serviceName”: “serviceName”,
“serviceCdsPath”: “srv/service.cds”
}
},
“entityConfig”: {
“mainEntity”: {
“entityName”: “EntityName”
},
“generateFormAnnotations”: true
},
“projectType”: “FORM_ENTRY_OBJECT_PAGE”,
“telemetryData”: {
“generationSourceName”: “AI Headless”,
“generationSourceVersion”: “1.18.1”
}
}
“`
### Required Steps for Fiori Generation
1. First generate the JSON config file as shown above
2. Run the command: `yo @sap/fiori:headless “/path/to/config.json” –force`
3. Add necessary annotations in the generated fiori application (usually in annotations.cds file)
4. Check https://github.com/SAP-samples/fiori-elements-feature-showcase for guidance on annotations
### Package Requirements
– Always use node package “yo” with version 4.3.1
– Before installing check if yo is already installed
– Use @sap/generator-fiori for fiori app generation
– CRITICAL: Always install these UI5 dependencies to avoid startup failures:
– `npm install -D @ui5/cli` (required for cds-plugin-ui5)
– `npm install -D @sap/ux-ui5-tooling` (required for advanced UI5 features)
– Always install `npm install -D cds-plugin-ui5` for CAP-UI5 integration
### UI Design Guidelines
– Application typically starts with a List Report page showing data in a table
– Details of specific table row shown in ObjectPage based on the base entity
– ObjectPage can contain table sections based on to-many associations
– Ensure complete UI is generated for requirements and all UI is tested
– Add necessary annotations: Tables for compositions, labels for all fields, value helps, etc.
– Ensure the UI is complete and functional
## Project Management and Documentation
### Product Requirements Document (PRD)
– Always ensure a product requirement document is there (prd.md) with high level requirements
– Status should be “approved” before starting development
– Should be TDD based development -> test after every change
– If PRD is not there, take requirements and generate the PRD
– Initial status should be “pending” – only work when status is “approved”
– Don’t assume anything, first ask user to verify the PRD
### PRD Structure
“`markdown
# Product Requirements Document
## Status: pending/approved
## Requirements
[High level requirements]
## Development Steps
[ ] step 1
[ ] step 2
[ ] step n
[ ] substep 1
[ ] substep 2
“`
– Steps and substeps should be very detailed
– Ensure the whole application is complete – with UI and necessary logic
– After every step completion, mark it as completed [X], for sub and main steps
## Code Quality Rules
### Comments and Documentation
– Don’t remove already existing code comments, may improve them
– Maintain existing documentation structure
– Add meaningful comments for complex logic
### Testing and Quality Assurance
– Always test after every change to ensure the outcome is correct
– Ensure complete UI is generated for the requirements
– All UI must be tested and functional
– Use browser testing MCP to confirm functionality and UI appearance
## Additional Guidelines
### Data Types and Structure
– Each property of an entity must have a proper datatype
– Data model must be suitable for SAP Fiori elements frontend applications
– Must have one main entity and one or more navigation properties to related entities
### Annotations Reference
– For annotation details check https://github.com/SAP-samples/fiori-elements-feature-showcase
– Use proper annotations for tables, labels, value helps, etc.
– Ensure UI completeness through proper annotations
#### CRITICAL: Navigation Property Syntax in Annotations
– ALWAYS use dot notation (.) for navigation properties in CDS annotations
– CORRECT: `group.groupName`, `homeTeam.teamName`, `event.name`
– WRONG: `group/groupName`, `homeTeam/teamName`, `event/name` (OData URL syntax)
– ERROR EXAMPLE: Using ‘/’ will cause “Mismatched ‘/’, expecting ‘,’, ‘.’, ‘}’, ‘#'” compilation errors
### Version Specifications
– Always use UI5 versions: “ui5Version”: “1.132.1”, “localUI5Version”: “1.82.2”
– Keep version consistency across the project
## Development Workflow
1. Create/verify PRD (status: pending → approved)
2. Initialize CAP project with `cds init`
3. Add `cds lint` to the project
4. Create data model with proper entities, compositions, and managed aspects
5. Generate sample data with UUID format for keys
6. Generate Fiori application using 3-step process
7. Add comprehensive annotations
8. Use `cds build` to check for errors
9. Test with `cds watch`
10. Verify UI functionality with browser testing
11. Mark steps as completed in PRD
Remember: Always use MCP servers for their respective domains and follow the specific guidelines for each technology stack.
## Critical Issues & Solutions from Real Development Experience
### UI5 Dependency Resolution Issues
**Problem**: CDS server starts but fails to mount UI5 applications with errors like:
– `Cannot find module ‘@ui5/cli/package.json’`
– `Cannot find module ‘@sap/ux-ui5-tooling/package.json’`
**Root Cause**: Fiori generator creates applications with UI5 tooling requirements not installed in project root
**MANDATORY Solution**:
1. Always install: `npm install -D @ui5/cli @sap/ux-ui5-tooling`
2. Install before generating Fiori applications
3. If applications already exist, install dependencies then restart `cds watch`
### Service Import Issues in Annotations
**Problem**: Cannot import services in annotation files with errors like:
– `Can’t find local module ‘../srv/service-name’`
**Solution**:
– Import services using destructuring: `using { ServiceName } from ‘../srv/service-file’;`
– If import fails, create separate annotation files per service
– Use relative paths correctly from app/ to srv/ directory
### Draft Entity Composition Conflicts
**Problem**: Build error “Composition in draft-enabled entity can’t lead to another entity with @odata.draft.enabled”
**Solution**:
– Only enable draft on parent entities in compositions
– Child entities are automatically managed through parent draft context
– Example: Events (draft enabled) → Teams (no draft) is correct
### npm Workspaces for UI5 Applications
**MANDATORY Setup**:
“`json
{
“workspaces”: [
“app/*”
],
“scripts”: {
“watch-app1”: “cds watch –open app1/webapp/index.html”,
“watch-app2”: “cds watch –open app2/webapp/index.html”
}
}
“`
### Authorization Testing
– Protected endpoints returning “Unauthorized” is CORRECT behavior
– Test public endpoints for anonymous access
– Use different service definitions for different security levels
– @requires at service level, @restrict at entity level
### Troubleshooting Checklist
When CDS server fails to start with Fiori applications:
1. ✅ Check @ui5/cli is installed
2. ✅ Check @sap/ux-ui5-tooling is installed
3. ✅ Check cds-plugin-ui5 is installed
4. ✅ Verify npm workspaces configuration
5. ✅ Check draft entity composition conflicts
6. ✅ Verify annotation syntax (. not / for navigation)
7. ✅ Run `npm audit fix` for security vulnerabilities
### Testing Verification Steps
1. `cds watch` starts without errors
2. http://localhost:4004 shows launch page
3. All UI5 applications listed and accessible
4. Service endpoints return data or proper authorization errors
5. Fiori preview links work for all entitiesQuick comparison: SAP MCP servers vs SAP Docs MCP serverAspectOfficial CAP/Fiori/UI5 MCPSAP Docs MCP (my server)Startup guidanceProject-aware; returns concrete tools and parametersFinds the right pages (CAP getting started, UI5 what’s new)Model and API groundingCAP: search_model/search_docs; UI5: get_api_referenceCross-source docs incl. SAP Help and Community postsScaffoldingUI5: create_ui5_app; Fiori: generate flow (schema issues in test client)No scaffolding, documentation-firstQuality gatesUI5 linter with contextual docs and migration guidesVerify answers against official sourcesOutcome in this testCAP and UI5 flows helped; Fiori flow blocked by schema validation → manual FE generation produced object pages onlyDocs server supplied confirmation for versions, annotations and FE patternsFinal wordsFirst of all, I want to praise my colleagues at SAP in the UI5, CAP, and Fiori tools teams. Making these MCP servers available as open source is the right decision—it enables not only developers who use BAS, but all developers, including those outside of BTP.For day-to-day development I prefer a local client with MCP servers. The official CAP, Fiori, and UI5 servers add project awareness and executable actions. Combined with a documentation-first server like my SAP Docs MCP, you can cover both creation and verification without switching to Joule for Developers. You can also use MCP servers with BAS; I will cover this in another blog post.From my tests: the UI5 server ties linter output to API references and migration guides, closing a common gap where fixes lacked context. The cache under the data directory speeds up repeated queries, but verify version alignment via get_project_info and get_version_info before applying fixes. The Fiori server’s three-step approach makes changes explicit and reviewable, which helps keep pull requests predictable—if you automate this in CI, keep it behind a branch. The CAP server provides safe discovery over the compiled model and a docs search, reducing wrong assumptions about services and endpoints.It is important to note that these MCP tools were only released this week. Not everything works perfectly yet, but once you start using them, it is hard to work without them. Work with Git so any changes can be reversed if necessary.The MCP protocol is still new, and it is fair to ask whether it is worth the investment. I think it is promising: it can solve the problem of missing or outdated context for LLMs and, as these servers show, it is not just about context but also about executing the right actions with Fiori tools and CAP.Links@cap-js/mcp-server@sap-ux/fiori-mcp-server@ui5/mcp-serverUI5 MCP server repositoryUI5 MCP server release postSAP Build introduces MCP serversCAP MCP server release postFiori MCP server repositoryCAP MCP server repository Read More Technology Blog Posts by Members articles
#SAP
#SAPTechnologyblog