From 7ffb05f301f8fc1bd0f57bdfc928e7ea22f83312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Mon, 20 Apr 2026 09:37:26 +0200 Subject: [PATCH 01/10] feat: add Claude plugin metadata --- packages/fiori-mcp-server/.claude-plugin/plugin.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 packages/fiori-mcp-server/.claude-plugin/plugin.json diff --git a/packages/fiori-mcp-server/.claude-plugin/plugin.json b/packages/fiori-mcp-server/.claude-plugin/plugin.json new file mode 100644 index 00000000000..18ef6a38300 --- /dev/null +++ b/packages/fiori-mcp-server/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "fiori-mcp-server", + "description": "MCP server for SAP Fiori development tools for Claude Code. Build and modify SAP Fiori applications with AI assistance.", + "author": { + "name": "SAP SE", + "url": "https://sap.com/" + }, + "homepage": "https://github.com/SAP/open-ux-tools/tree/main/packages/fiori-mcp-server", + "repository": "https://github.com/SAP/open-ux-tools", + "license": "Apache-2.0", + "keywords": ["sap", "fiori", "ui5", "cap", "mcp", "fiori-elements"] +} From 0d47a3b47d1864703820bd18b29fadfbaf1f9220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Mon, 20 Apr 2026 09:38:15 +0200 Subject: [PATCH 02/10] feat: add MCP server config --- packages/fiori-mcp-server/.mcp.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 packages/fiori-mcp-server/.mcp.json diff --git a/packages/fiori-mcp-server/.mcp.json b/packages/fiori-mcp-server/.mcp.json new file mode 100644 index 00000000000..445f448c3a1 --- /dev/null +++ b/packages/fiori-mcp-server/.mcp.json @@ -0,0 +1,9 @@ +{ + "mcpServers": { + "fiori-mcp": { + "type": "stdio", + "command": "npx", + "args": ["--yes", "@sap-ux/fiori-mcp-server@latest", "fiori-mcp"] + } + } +} From 1b9938743b6dbbf01ee090a0137ed8116ae86a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Mon, 20 Apr 2026 09:47:39 +0200 Subject: [PATCH 03/10] feat: add AGENTS.md --- packages/fiori-mcp-server/AGENTS.md | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 packages/fiori-mcp-server/AGENTS.md diff --git a/packages/fiori-mcp-server/AGENTS.md b/packages/fiori-mcp-server/AGENTS.md new file mode 100644 index 00000000000..a2e061a2c76 --- /dev/null +++ b/packages/fiori-mcp-server/AGENTS.md @@ -0,0 +1,44 @@ +# AI Agent Guidelines for `@sap-ux/fiori-mcp-server` + +This document describes the purpose of the key configuration files in this package that relate to MCP server distribution and plugin registries. + +## Configuration Files + +### `server.json` + +This file is the **MCP server registry manifest**. It conforms to the [MCP server schema](https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json) and is used to list this server in MCP server registries (e.g., the official MCP server registry at `registry.modelcontextprotocol.io`). + +Key fields: +- `name` — Unique server identifier in reverse-domain notation (`io.github.SAP/fiori-mcp-server`) +- `description` — Short description shown in registry listings +- `repository` — Points to the GitHub source repository and subfolder +- `version` — Must be kept in sync with `package.json` +- `packages[].environmentVariables` — Documents environment variables users can configure (e.g., `LOG_LEVEL`, `SAP_UX_FIORI_TOOLS_DISABLE_TELEMETRY`) + +> **Important:** When bumping the package version, update `version` in both `package.json` and `server.json`. + +### `.claude-plugin/plugin.json` + +This file is the **Claude Code plugin manifest**. It registers this MCP server as a plugin in the [Claude Code plugin registry](https://code.claude.com/docs/en/plugins), allowing users to discover and install it from within Claude Code. + +Key fields: +- `name` — Plugin identifier shown in the Claude Code registry +- `description` — Brief explanation of what the plugin does (shown to users in registry) +- `author` — Organization name and URL +- `homepage` — URL to the package README (documentation) +- `repository` — URL to the source code repository root +- `license` — SPDX license identifier +- `keywords` — Discovery tags used for search in the registry + +The `.mcp.json` file at the plugin root is automatically picked up by Claude Code to configure the bundled MCP server when the plugin is enabled. + +### `.mcp.json` + +This file is the **project-scoped MCP server configuration** for Claude Code. It follows the [Claude Code `.mcp.json` format](https://code.claude.com/docs/en/mcp#option-1-exclusive-control-with-managed-mcp-json) and serves two purposes: + +1. **Plugin bundling** — When this package is installed as a Claude Code plugin (via `.claude-plugin/plugin.json`), Claude Code reads `.mcp.json` to automatically start the MCP server. +2. **Local development** — Developers working in this repository can use this file directly to connect the locally published server to Claude Code. + +Key fields: +- `mcpServers.fiori-mcp.type` — Transport type (`stdio` for local process) +- `mcpServers.fiori-mcp.command` / `args` — How to launch the server via `npx` From d3ffb8234525d9f775962badc466324b83c75a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Mon, 20 Apr 2026 09:55:45 +0200 Subject: [PATCH 04/10] feat: sync plugin.json version automatically --- packages/fiori-mcp-server/.claude-plugin/plugin.json | 1 + packages/fiori-mcp-server/AGENTS.md | 2 +- .../fiori-mcp-server/scripts/sync-mcp-server-json.js | 10 +++++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/fiori-mcp-server/.claude-plugin/plugin.json b/packages/fiori-mcp-server/.claude-plugin/plugin.json index 18ef6a38300..577fd3410fc 100644 --- a/packages/fiori-mcp-server/.claude-plugin/plugin.json +++ b/packages/fiori-mcp-server/.claude-plugin/plugin.json @@ -1,5 +1,6 @@ { "name": "fiori-mcp-server", + "version": "0.6.49", "description": "MCP server for SAP Fiori development tools for Claude Code. Build and modify SAP Fiori applications with AI assistance.", "author": { "name": "SAP SE", diff --git a/packages/fiori-mcp-server/AGENTS.md b/packages/fiori-mcp-server/AGENTS.md index a2e061a2c76..4f33867b90e 100644 --- a/packages/fiori-mcp-server/AGENTS.md +++ b/packages/fiori-mcp-server/AGENTS.md @@ -15,7 +15,7 @@ Key fields: - `version` — Must be kept in sync with `package.json` - `packages[].environmentVariables` — Documents environment variables users can configure (e.g., `LOG_LEVEL`, `SAP_UX_FIORI_TOOLS_DISABLE_TELEMETRY`) -> **Important:** When bumping the package version, update `version` in both `package.json` and `server.json`. +> **Important:** Do not manually update `version` in `server.json` or `.claude-plugin/plugin.json`. The `scripts/sync-mcp-server-json.js` script runs automatically in the CI/CD pipeline (`version` job in `pipeline.yml`) after changesets bump `package.json`, and keeps all three files in sync. ### `.claude-plugin/plugin.json` diff --git a/packages/fiori-mcp-server/scripts/sync-mcp-server-json.js b/packages/fiori-mcp-server/scripts/sync-mcp-server-json.js index 42b5e21c6fa..7f918a56355 100644 --- a/packages/fiori-mcp-server/scripts/sync-mcp-server-json.js +++ b/packages/fiori-mcp-server/scripts/sync-mcp-server-json.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -// Syncs the version in packages/fiori-mcp-server/server.json with its package.json. +// Syncs the version in packages/fiori-mcp-server/server.json and .claude-plugin/plugin.json with its package.json. // Called from the version job in pipeline.yml after `changeset version` bumps package.json. 'use strict'; @@ -9,9 +9,11 @@ const path = require('path'); const pkgPath = path.join(__dirname, '..', 'package.json'); const serverJsonPath = path.join(__dirname, '..', 'server.json'); +const pluginJsonPath = path.join(__dirname, '..', '.claude-plugin', 'plugin.json'); const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); const serverJson = JSON.parse(fs.readFileSync(serverJsonPath, 'utf8')); +const pluginJson = JSON.parse(fs.readFileSync(pluginJsonPath, 'utf8')); const { version } = pkg; @@ -23,5 +25,11 @@ if (Array.isArray(serverJson.packages) && serverJson.packages.length > 0) { serverJson.packages[0].version = version; } +// Update version in Claude Code plugin manifest +pluginJson.version = version; + fs.writeFileSync(serverJsonPath, JSON.stringify(serverJson, null, 4) + '\n'); console.log(`Updated server.json to version ${version}`); + +fs.writeFileSync(pluginJsonPath, JSON.stringify(pluginJson, null, 4) + '\n'); +console.log(`Updated .claude-plugin/plugin.json to version ${version}`); From 1da66c50bc2c041c0a4075145658217538c0b02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Mon, 20 Apr 2026 10:00:12 +0200 Subject: [PATCH 05/10] rename sync script and update references --- .github/workflows/pipeline.yml | 4 ++-- packages/fiori-mcp-server/AGENTS.md | 2 +- .../{sync-mcp-server-json.js => sync-mcp-manifests.js} | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename packages/fiori-mcp-server/scripts/{sync-mcp-server-json.js => sync-mcp-manifests.js} (91%) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index b4f98ea8f46..b3bd495fa9f 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -149,9 +149,9 @@ jobs: run: | echo ::set-output name=changes::$(pnpm ci:version 2>&1 | grep -q 'No unreleased changesets found' && echo 'false' || echo 'true') git status - - name: Sync server.json version + - name: Sync MCP manifest versions if: steps.changesetVersion.outputs.changes == 'true' - run: node packages/fiori-mcp-server/scripts/sync-mcp-server-json.js + run: node packages/fiori-mcp-server/scripts/sync-mcp-manifests.js - name: Commit and push changes if: steps.changesetVersion.outputs.changes == 'true' run: | diff --git a/packages/fiori-mcp-server/AGENTS.md b/packages/fiori-mcp-server/AGENTS.md index 4f33867b90e..3f6e1d0ee69 100644 --- a/packages/fiori-mcp-server/AGENTS.md +++ b/packages/fiori-mcp-server/AGENTS.md @@ -15,7 +15,7 @@ Key fields: - `version` — Must be kept in sync with `package.json` - `packages[].environmentVariables` — Documents environment variables users can configure (e.g., `LOG_LEVEL`, `SAP_UX_FIORI_TOOLS_DISABLE_TELEMETRY`) -> **Important:** Do not manually update `version` in `server.json` or `.claude-plugin/plugin.json`. The `scripts/sync-mcp-server-json.js` script runs automatically in the CI/CD pipeline (`version` job in `pipeline.yml`) after changesets bump `package.json`, and keeps all three files in sync. +> **Important:** Do not manually update `version` in `server.json` or `.claude-plugin/plugin.json`. The `scripts/sync-mcp-manifests.js` script runs automatically in the CI/CD pipeline (`version` job in `pipeline.yml`) after changesets bump `package.json`, and keeps all three files in sync. ### `.claude-plugin/plugin.json` diff --git a/packages/fiori-mcp-server/scripts/sync-mcp-server-json.js b/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js similarity index 91% rename from packages/fiori-mcp-server/scripts/sync-mcp-server-json.js rename to packages/fiori-mcp-server/scripts/sync-mcp-manifests.js index 7f918a56355..d16c5bf1ee0 100644 --- a/packages/fiori-mcp-server/scripts/sync-mcp-server-json.js +++ b/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -// Syncs the version in packages/fiori-mcp-server/server.json and .claude-plugin/plugin.json with its package.json. +// Syncs the version in server.json and .claude-plugin/plugin.json with package.json. // Called from the version job in pipeline.yml after `changeset version` bumps package.json. 'use strict'; From 2ad7bd2ec4727eb6e47bd4420958c7146af67682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Mon, 20 Apr 2026 10:22:25 +0200 Subject: [PATCH 06/10] feat: add robust JSON reading & error handling --- .../scripts/sync-mcp-manifests.js | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js b/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js index d16c5bf1ee0..e32aa53401b 100644 --- a/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js +++ b/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js @@ -11,25 +11,47 @@ const pkgPath = path.join(__dirname, '..', 'package.json'); const serverJsonPath = path.join(__dirname, '..', 'server.json'); const pluginJsonPath = path.join(__dirname, '..', '.claude-plugin', 'plugin.json'); -const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); -const serverJson = JSON.parse(fs.readFileSync(serverJsonPath, 'utf8')); -const pluginJson = JSON.parse(fs.readFileSync(pluginJsonPath, 'utf8')); +/** + * Reads and parses a JSON file, throwing a clear error if the file is missing or contains invalid JSON. + * @param {string} filePath + * @returns {object} + */ +function readJson(filePath) { + if (!fs.existsSync(filePath)) { + throw new Error(`File not found: ${filePath}`); + } + const content = fs.readFileSync(filePath, 'utf8'); + try { + return JSON.parse(content); + } catch (e) { + throw new Error(`Invalid JSON in ${filePath}: ${e.message}`); + } +} -const { version } = pkg; +try { + const pkg = readJson(pkgPath); + const serverJson = readJson(serverJsonPath); + const pluginJson = readJson(pluginJsonPath); -// Update top-level version -serverJson.version = version; + const { version } = pkg; -// Update version inside packages[0] (npm package entry) -if (Array.isArray(serverJson.packages) && serverJson.packages.length > 0) { - serverJson.packages[0].version = version; -} + // Update top-level version + serverJson.version = version; -// Update version in Claude Code plugin manifest -pluginJson.version = version; + // Update version inside packages[0] (npm package entry) + if (Array.isArray(serverJson.packages) && serverJson.packages.length > 0) { + serverJson.packages[0].version = version; + } -fs.writeFileSync(serverJsonPath, JSON.stringify(serverJson, null, 4) + '\n'); -console.log(`Updated server.json to version ${version}`); + // Update version in Claude Code plugin manifest + pluginJson.version = version; -fs.writeFileSync(pluginJsonPath, JSON.stringify(pluginJson, null, 4) + '\n'); -console.log(`Updated .claude-plugin/plugin.json to version ${version}`); + fs.writeFileSync(serverJsonPath, JSON.stringify(serverJson, null, 4) + '\n'); + console.log(`Updated server.json to version ${version}`); + + fs.writeFileSync(pluginJsonPath, JSON.stringify(pluginJson, null, 4) + '\n'); + console.log(`Updated .claude-plugin/plugin.json to version ${version}`); +} catch (e) { + console.error(`Error: ${e.message}`); + process.exit(1); +} From abd119948b64650d548db6542645118af0f74312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Mon, 20 Apr 2026 10:23:50 +0200 Subject: [PATCH 07/10] chore: clarify homepage field in AGENTS.md --- packages/fiori-mcp-server/AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fiori-mcp-server/AGENTS.md b/packages/fiori-mcp-server/AGENTS.md index 3f6e1d0ee69..e042221f3bd 100644 --- a/packages/fiori-mcp-server/AGENTS.md +++ b/packages/fiori-mcp-server/AGENTS.md @@ -25,7 +25,7 @@ Key fields: - `name` — Plugin identifier shown in the Claude Code registry - `description` — Brief explanation of what the plugin does (shown to users in registry) - `author` — Organization name and URL -- `homepage` — URL to the package README (documentation) +- `homepage` — URL to the package folder (documentation and README) - `repository` — URL to the source code repository root - `license` — SPDX license identifier - `keywords` — Discovery tags used for search in the registry From 8f69cbec1e5ed5cc7c17f97d17a8886a909b9b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Mon, 20 Apr 2026 10:26:52 +0200 Subject: [PATCH 08/10] chore: add changeset --- .changeset/shaggy-pots-kneel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/shaggy-pots-kneel.md diff --git a/.changeset/shaggy-pots-kneel.md b/.changeset/shaggy-pots-kneel.md new file mode 100644 index 00000000000..fa03c397aec --- /dev/null +++ b/.changeset/shaggy-pots-kneel.md @@ -0,0 +1,5 @@ +--- +'@sap-ux/fiori-mcp-server': patch +--- + +feat: add Claude Code plugin support From d292d383b497a460a3762ef8e6a9728ca62274ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Tue, 21 Apr 2026 08:54:08 +0200 Subject: [PATCH 09/10] refactor: update version for all package entries --- packages/fiori-mcp-server/scripts/sync-mcp-manifests.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js b/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js index e32aa53401b..81e120466ac 100644 --- a/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js +++ b/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js @@ -38,9 +38,11 @@ try { // Update top-level version serverJson.version = version; - // Update version inside packages[0] (npm package entry) - if (Array.isArray(serverJson.packages) && serverJson.packages.length > 0) { - serverJson.packages[0].version = version; + // Update version in all package entries + if (Array.isArray(serverJson.packages)) { + for (const pkg of serverJson.packages) { + pkg.version = version; + } } // Update version in Claude Code plugin manifest From 644542eeee32d235da873cad7c67fea659a9df94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Meng=C3=BCtay?= Date: Tue, 21 Apr 2026 11:02:02 +0200 Subject: [PATCH 10/10] refactor: rename package loop variable --- packages/fiori-mcp-server/scripts/sync-mcp-manifests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js b/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js index 81e120466ac..774a6951f49 100644 --- a/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js +++ b/packages/fiori-mcp-server/scripts/sync-mcp-manifests.js @@ -40,8 +40,8 @@ try { // Update version in all package entries if (Array.isArray(serverJson.packages)) { - for (const pkg of serverJson.packages) { - pkg.version = version; + for (const packageEntry of serverJson.packages) { + packageEntry.version = version; } }