odata-mcp-proxy
A config-driven proxy that turns OData and REST endpoints into MCP tools from a JSON file — no code — and runs on BTP Cloud Foundry against BTP Destinations.
The engine three other servers in this corner are built from, and the reason they contain no application code at all. You describe the APIs and entity sets in one config file and it registers the tools: full CRUD where the API permits, OData V2 query support across $filter, $select, $expand, $orderby, $top, $skip and $inlinecount, dedicated tools for navigation properties so related entities are reachable, and category filtering so only the API groups you want are exposed. Tokens are refreshed transparently through the BTP Destination service. Streamable HTTP for a BTP deployment, stdio for a local client.
Facts
Where it sits
Who is behind it
In the atlas: maintains 25, contributes to 39, wrote 12@lemaiwomaintainerhakon7Contributes to this
In the atlas: contributes to 1@hakon7jizqugaContributes to this
In the atlas: contributes to 2@jizquga2 contributors
Before choosing this
Conditions
PracticalFunctional boundary
It fronts APIs you already have; nothing here reads a system's source or model, and a config file is only as good as the entity sets somebody wrote into it. OData V2 is the query surface it names.
PolicySAP API Policy 4.2026a§ 1.1, 1.2, 2.2.2from Agent access to your systemsAn MCP server uses SAP APIs to supply tools, resources or data to an agent.
- § 1.1 Published APIs. Published APIs are made available for the documented purposes identified by SAP, including integration, extensions and data exchange.
- § 1.2 Non-Published APIs. Customer and third-party applications must not access non-published APIs except where documentation permits it or SAP otherwise authorizes it.
- § 2.2.2 AI call sequences and data extraction. Outside SAP-endorsed architectures, data services or expressly identified pathways, the policy prohibits specified agentic API use and systematic or large-scale extraction.
MCP does not replace the API's documented-use boundary. Check that every endpoint is published for the intended use and whether the policy's AI-call or extraction provisions apply to the design.
SAP API Policy 4.2026a →What it declares
Every artifact
- Type
- MCP server
- Origin
- Independently maintained
- Runtime
- Node.js
- Runs on
- Cloud Foundrylocal
Connections
Giving an AI agent access to the systems you run over MCP
LangGraph agent and UI5 chat screen over four BTP MCP servers
Cloud Foundry V3 API on SAP BTP as MCP tools
LangGraph agent and UI5 chat screen over four BTP MCP servers
SAP AI Core APIs as MCP tools from one JSON config file
BTP Core Services as MCP tools with in-chat dashboards
SAP Cloud Integration OData APIs as MCP tools
Download
Install
npm add odata-mcp-proxyDerived from the package name. No recipe recorded; the README has the configuration.
Learn more
- BTP Audit Log MCP Server: Security Monitoring with AI AssistantsBTP Audit Log MCP Server: Security Monitoring with AI AssistantsWouter Lemaire builds an MCP server over SAP BTP's Audit Log Retrieval API using odata-mcp-proxy, with a single entity set and zero custom code, so an AI assistant can answer natural-language questions like "Were there any configuration changes yesterday?" by calling AuditLogRecords_list against a BTP destination authenticated with the Audit Log service's service key. It covers the destination setup, the entity-set configuration that maps the PascalCase entity name to a lowercase auditlogrecords path, and handling the API's 500-record pagination limit.published 2026-03-13Wouter Lemaire, SAP Community
README
quoted from lemaiwo/odata-mcp-proxy under MIT, readOData MCP Proxy
A config-driven MCP (Model Context Protocol) server that exposes OData and REST APIs as MCP tools. This enables AI assistants such as Claude to query, manage, and monitor SAP backends through natural language.
The server runs on SAP BTP Cloud Foundry and uses BTP Destinations for secure, token-managed connectivity to OData APIs.
Features
- 32 OData entity sets across 6 API categories, automatically registered as MCP tools
- Full CRUD support -- list, get, create, update, and delete operations where the API permits
- OData V2 query capabilities --
$filter,$select,$expand,$orderby,$top,$skip, and$inlinecount - Navigation property traversal -- dedicated tools for related entities (e.g., iFlow configurations, message attachments, error details)
- Category-based filtering -- enable only the API categories you need via configuration
- Dual transport modes -- Streamable HTTP for BTP deployment, stdio for local Claude Desktop use
- Automatic OAuth token management -- tokens are refreshed transparently via the BTP Destination Service
Architecture
Claude / AI Assistant
|
| MCP Protocol (stdio or HTTP)
v
OData MCP Proxy
|
| OData V2 + JSON
v
OData Client
|
| OAuth2 (via BTP Destination Service)
v
BTP Destination
|
v
SAP Cloud Integration
OData Admin APIs
The server resolves a BTP Destination at startup to obtain the Cloud Integration tenant URL and OAuth2 credentials. On each API call, the destination is re-resolved to ensure tokens remain valid. The OData client translates MCP tool invocations into OData V2 HTTP requests and returns structured JSON results to the AI assistant.
Prerequisites
- Node.js 20+ (18+ minimum, 20+ recommended)
- SAP BTP account with a Cloud Foundry environment
- SAP Integration Suite tenant (Cloud Integration capability)
- BTP Destination configured to point to your Cloud Integration tenant's OData API with OAuth2 authentication
- Cloud Foundry CLI (
cf) and MBT Build Tool (mbt) for BTP deployment
Quick Start (Local Development)
1. Clone and install
git clone <repository-url>
cd odata-mcp-proxy
npm install
2. Configure environment
cp .env.example .env
Edit .env and set at minimum:
SAP_DESTINATION_NAME=your_ci_destination_name
MCP_TRANSPORT=stdio
Note: For local development with stdio transport, you must have BTP Destination Service credentials available in your environment (e.g., via
VCAP_SERVICESor adefault-env.jsonfile).
3. Build and run
npm run build
npm run start:stdio
Or use the development watcher:
npm run dev
4. Connect from Claude Desktop
Add the server to your Claude Desktop MCP configuration (claude_desktop_config.json):
{
"mcpServers": {
"odata-mcp-proxy": {
"command": "node",
"args": ["dist/index.js"],
"cwd": "/path/to/odata-mcp-proxy",
"env": {
"SAP_DESTINATION_NAME": "your_ci_destination_name",
"MCP_TRANSPORT": "stdio"
}
}
}
}
Using as an npm Package
You can consume odata-mcp-proxy as a dependency in your own project -- similar to how the SAP Application Router works. No TypeScript compilation or build step required.
1. Create your project
mkdir my-mcp-server
cd my-mcp-server
npm init -y
npm install odata-mcp-proxy
2. Add a start script
In your package.json:
{
"scripts": {
"start": "odata-mcp-proxy"
},
"dependencies": {
"odata-mcp-proxy": "^1.0.0"
}
}
3. Add your API config
Create an api-config.json in your project root. The CLI automatically picks it up from the working directory. See the bundled config files for the full format.
{
"server": {
"name": "my-mcp-server",
"version": "1.0.0",
"description": "My custom MCP server"
},
"apis": [
{
"name": "my-api",
"destination": "MY_DESTINATION",
"pathPrefix": "/api/v1",
"csrfProtected": true,
"entitySets": [
{
"entitySet": "Products",
"description": "product entities",
"category": "master-data",
"keys": [{ "name": "Id", "type": "string" }],
"operations": { "list": true, "get": true, "create": false, "update": false, "delete": false }
}
]
}
]
}
You can also use a custom filename with the --config flag:
odata-mcp-proxy --config my-custom-config.json
Or set it via environment variable:
API_CONFIG_FILE=my-custom-config.json npm start
If no config file is found in the working directory, the bundled defaults (SAP Cloud Integration APIs) are used.
4. Configure credentials
For local development, create a .env file or default-env.json with your destination credentials. The env var prefix is derived from the destination field in your config -- uppercase it and replace non-alphanumeric characters with _.
For example, destination "MY_DESTINATION" maps to:
MY_DESTINATION_BASE_URL=https://my-api.example.com
MY_DESTINATION_TOKEN_URL=https://auth.example.com/oauth/token
MY_DESTINATION_CLIENT_ID=...
MY_DESTINATION_CLIENT_SECRET=...
On BTP, use the Destination Service instead (credentials are resolved automatically via VCAP_SERVICES).
5. Project structure
A complete consumer project looks like this:
my-mcp-server/
├── package.json # start script + dependency
├── api-config.json # your API configuration
├── default-env.json # local BTP credentials (gitignored)
├── .env # local env overrides (gitignored)
├── mta.yaml # BTP deployment descriptor
└── xs-security.json # XSUAA config (if using OAuth)
Deploying to BTP as a consumer project
Since there is no build step, the mta.yaml is straightforward -- just like the SAP Application Router:
_schema-version: "3.1"
ID: my-mcp-server
version: 1.0.0
parameters:
enable-parallel-deployments: true
modules:
- name: my-mcp-server
type: nodejs
path: .
parameters:
memory: 512M
disk-quota: 1G
buildpack: nodejs_buildpack
health-check-type: http
health-check-http-endpoint: /health
command: npm start
build-parameters:
builder: npm
ignore:
- .git/
- .env
- default-env.json
requires:
- name: my-destination
- name: my-connectivity
- name: my-xsuaa
resources:
- name: my-destination
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite
- name: my-connectivity
type: org.cloudfoundry.managed-service
parameters:
service: connectivity
service-plan: lite
- name: my-xsuaa
type: org.cloudfoundry.managed-service
parameters:
service: xsuaa
service-plan: application
path: xs-security.json
The key difference from a standalone deployment: builder: npm is all you need. MBT runs npm install --production, which installs the pre-built odata-mcp-proxy package from the registry. No TypeScript, no custom build commands.
Deploy with:
mbt build && cf deploy mta_archives/my-mcp-server_1.0.0.mtar
Interactive UI Views (mcp-ui)
Beyond plain data tools, the config file can declare interactive UI views: read-only MCP tools that fetch data through the shared OData clients and return a self-contained HTML page as an mcp-ui embedded resource (with the MCP Apps adapter enabled, so the same widget works on MCP Apps hosts like Claude and on classic mcp-ui hosts).
Add a top-level ui array to your API config:
{
"server": { "name": "my-mcp-server", "version": "1.0.0", "description": "..." },
"apis": [ ... ],
"ui": [
{
"tool": "UI_SubaccountsOverview",
"description": "Interactive overview of all subaccounts",
"uri": "ui://my-server/subaccounts-overview",
"template": "ui/subaccounts-overview.html",
"inputs": {
"subaccountGUID": { "type": "string", "required": true, "description": "GUID of the subaccount" }
},
"data": {
"subaccounts": { "api": "cis-accounts", "path": "subaccounts" },
"assignments": { "api": "cis-entitlements", "path": "assignments?subaccountGUID={subaccountGUID}", "optional": true }
},
"partials": {
"/*__SHARED_CSS__*/": "ui/_shared.css",
"/*__SHARED_JS__*/": "ui/_shared.js"
},
"frameSize": ["100%", "760px"]
}
]
}
Per entry:
| Field | Required | Description |
|---|---|---|
tool | yes | MCP tool name. Registered read-only (annotations.readOnlyHint: true) with _meta["ui/resourceUri"] pointing at uri. |
description | yes | Tool description for the LLM. |
uri | yes | ui:// resource URI. The template is also registered as an MCP resource at this URI (with null data), so MCP Apps hosts that pre-fetch templates can use render-data delivery. |
template | yes | HTML template file, path relative to the config file. File reads are cached. |
inputs | no | Tool parameters: { "name": { "type": "string"|"number"|"boolean", "required": bool, "default": val, "min": n, "max": n, "description": "..." } }. Compiled into the tool's input schema. A default is applied during parsing, so placeholders referencing that parameter always resolve; min/max bound number inputs. |
data | no | Named data sources, fetched concurrently on invocation through the shared OData client of the referenced api (the caller's JWT is forwarded, exactly like the generated entity tools). Placeholders in path are substituted with URL-encoded values (see below). "optional": true entries fail soft to null; a failure in any other entry returns an isError tool result. Each source also accepts paginate and select. |
partials | no | Literal token → file map. Each file (path relative to the config file) is inlined into the template before data injection — useful for shared CSS/JS. |
frameSize | no | Overrides the mcp-ui preferred-frame-size (default ["100%", "760px"]). |
Path placeholders
{param} expands to a validated tool argument. {$...} expands to a fixed, closed vocabulary of derived values — enough for reporting windows and paging without a templating language (there is no eval and no user-defined function):
| Placeholder | Expands to |
|---|---|
{$now:FMT} | The current UTC time. |
{$monthsAgo(N):FMT} | The first of the month, N months back — so a yyyymm window is stable no matter which day the tool runs. |
{$daysAgo(N):FMT} | N days back. |
{$offset} / {$pageSize} | Page position. Only valid on a source with a paginate block. |
FMT is yyyymm (202608), date (2026-08-11), or iso (default). N is an integer, the name of a tool input, or that name with one integer offset (months-1) — the offset form exists so an inclusive window ("the last 6 months, including this one") is expressible, and it is the only arithmetic supported.
"usage": { "api": "uas", "path": "monthlyUsage?fromDate={$monthsAgo(months-1):yyyymm}&toDate={$now:yyyymm}" }
Because dates resolve at call time, a view using them is not a pure function of its arguments — expected for reporting windows, worth knowing when caching.
Pagination
paginate repeats the request until the collection is exhausted, a short page arrives, or maxItems is hit:
"users": {
"api": "xsuaa-scim",
"path": "Users?startIndex={$offset}&count={$pageSize}",
"paginate": { "strategy": "offset", "pageSize": 100, "maxItems": 500,
"itemsPath": "resources", "totalPath": "totalResults" }
}
| Field | Description |
|---|---|
strategy | offset (1-based, SCIM startIndex) or skiptop (0-based, OData $skip). |
pageSize | Items per request, exposed as {$pageSize} (default 100). |
maxItems | Hard cap on accumulated items (default 1000). |
itemsPath | Dotted path to the item array. Auto-detected (value, resources, results, content, d.results) when omitted. |
totalPath | Dotted path to the backend's total count, when it reports one. |
A paginated source returns a normalized { items, total, truncated, pages } object rather than the raw response — so templates read .items, and truncated tells them the view is showing a capped subset instead of silently under-reporting.
Trimming the payload
The payload is baked into the template and returned as structuredContent, so raw responses reach the model. select keeps only the listed dotted paths of each item, preserving the surrounding envelope:
"subaccounts": { "api": "cis-accounts", "path": "subaccounts",
"select": ["guid", "displayName", "region", "state"] }
Templates are full, self-contained HTML/JS pages. The server replaces the token "__DATA__" with the JSON payload:
<script>
const DATA = "__DATA__"; // becomes { view, params, data: { subaccounts: [...], ... } } — or null in the ui:// template resource
</script>
< is escaped as \u003c in the JSON, so user-controlled strings can never close the script tag. Aggregation and reshaping are the template's job — the server side stays declarative (there is deliberately no templating language or server-side aggregation DSL).
The tool result contains a short text summary (tool name + item counts per data entry), the rendered page as an embedded ui:// resource, and the payload as structuredContent for hosts using render-data delivery.
The UI machinery (and its @mcp-ui/server dependency) is loaded lazily — configs without a ui section skip it entirely.
Progressive Tool Discovery
By default every operation of every entity set becomes its own MCP tool. That is the right thing for a handful of entity sets and the wrong thing at scale: 32 entity sets produce over 100 tools, and the MCP client best practices recommend switching to progressive discovery once tool definitions occupy 1–5% of the context window. Some clients also cap tool counts outright.
Add a top-level discovery block and the entity tools collapse into two stable meta-tools:
{
"server": { ... },
"apis": [ ... ],
"discovery": {
"mode": "hybrid",
"alwaysRegister": ["Subaccounts", "cis-entitlements:Assignments"],
"maxResults": 25,
"maxFullResults": 5
}
}
Omit the block and nothing changes — registration behaves exactly as before.
| Field | Required | Description |
|---|---|---|
mode | yes | search replaces all entity tools with the meta-tools. hybrid does the same but keeps alwaysRegister entity sets as individual tools. |
alwaysRegister | no | Entity sets kept as individual tools in hybrid mode. Accepts EntitySet or api:EntitySet to disambiguate. Unknown names fail at startup rather than silently not pinning. |
maxResults | no | Cap for a brief search (default 25). |
maxFullResults | no | Cap for a full search (default 5) — full schemas are verbose, so narrow first. |
The two tools
search_operations(query, api?, category?, detail?, limit?) — catalog and inspect in one call. detail: "brief" (default) returns name, category, available operations and description; detail: "full" adds keys, navigation/filterable/selectable properties, per-operation method requirements, and concrete path examples.
Two levels rather than the more common three-tool discover → describe → execute split, for two reasons: the spec's own guidance is to "offer multiple detail levels" on the catalog tool, and it saves a round trip when the model already knows what it wants.
An empty or unmatched query returns the whole catalog rather than nothing, with matched: false and a note saying so — a dead end is worse for the model than a list it can narrow. Search is keyword-based with field weighting (exact name ≫ name prefix ≫ category ≫ description), and splits camelCase so sub accounts finds Subaccounts. Embeddings were deliberately not used: it would pull a model dependency into a package that has none.
execute_operation(api, entitySet, operation, path?, navProperty?, body?, headers?) — routes to the same ODataClient, method and path construction as the generated tools, including requiredScope enforcement (the check is shared, not reimplemented).
Because a generic executor has no per-tool schema to reject bad input, it validates routing itself and every failure names the valid options:
execute_operation({ api: "cis-accounts", entitySet: "Subaccounts", operation: "get" })
→ Operation "get" on Subaccounts needs a key expression in "path".
Keys: subaccountGUID (string). Example path: ('<subaccountGUID>').
Unknown entity sets suggest the API that does have them; unavailable operations list what is available and why; create/update without a body and unknown navigation properties are rejected before the backend is touched.
Schema resources
Discovery also registers one odata://{api}/{entitySet} resource per entity set, returning the same full schema. Hosts that pre-fetch and cache resources can read a schema with no tool round-trip and no context cost until it is read — the 2026-07-28 spec added ttlMs/cacheScope hints to resources/read for exactly this.
Why the tool list never changes
A tempting alternative is registering concrete tools on demand and firing notifications/tools/list_changed. This implementation deliberately does not, for two reasons from the spec: adding or removing tool definitions mid-conversation invalidates the model's prompt cache (the guidance is to "route every call through a single stable meta-tool so the array never changes"), and the 2026-07-28 revision removed protocol sessions so that tools/list no longer varies per-connection. A fixed tool surface is now the conformant design.
Interactive ui views are always registered and never hidden behind discovery — they are few, and they are the entry points the model should prefer.
Programmatic API
The package root exports a start() function, so you can embed the server in your own entry point instead of using the CLI:
// server.mjs
import { start } from 'odata-mcp-proxy';
await start(); // identical to running `odata-mcp-proxy`
To register extra tools or resources on every MCP session, pass registerExtras. It runs inside the per-session factory, after the generated entity tools, API doc resources, and config-driven UI views:
import { start } from 'odata-mcp-proxy';
await start({
registerExtras(server, ctx) {
// server: the session's McpServer
// ctx.clientsByApi: shared ODataClient instances keyed by API name
// ctx.apiConfig: the loaded API config file
// ctx.config: the environment-derived app config
server.registerTool('My_CustomTool', { description: '...', inputSchema: {} }, async (args, extra) => {
const result = await ctx.clientsByApi['my-api'].execute('GET', 'Products', undefined, undefined, extra.authInfo?.token);
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
});
},
});
ODataClient, resolveDestination, createMcpServer, registerAllTools, registerApiDocResources, and the config types are re-exported from the package root as well.
Migration note: if you previously forked the bootstrap (copying the transport/session wiring and deep-importing from odata-mcp-proxy/dist/... to add your own tools), you can delete that entry point: call start({ registerExtras }) for custom tools, and move interactive views into the config's ui section. Deep dist/ imports keep working via the package's exports map, but the root export is the supported surface.
BTP Deployment (Standalone)
When working with the source repository directly (not as an npm dependency), the project includes its own mta.yaml for deployment to SAP BTP Cloud Foundry. The MTA provisions the required service instances (Destination, Connectivity, XSUAA) and deploys the server as a Node.js application using HTTP transport.
npm run build:btp # Build the MTA archive
npm run deploy:btp # Deploy to Cloud Foundry
For detailed deployment instructions, destination configuration, and XSUAA setup, see docs/DEPLOYMENT.md.
Configuration
All configuration is managed through environment variables. The server validates configuration at startup using Zod and fails fast on invalid values.
| Variable | Required | Default | Description |
|---|---|---|---|
SAP_DESTINATION_NAME | Yes | -- | BTP Destination name pointing to your Cloud Integration tenant |
MCP_TRANSPORT | No | http | Transport mode: http (BTP deployment) or stdio (Claude Desktop) |
PORT | No | 4004 | HTTP server port (only used when MCP_TRANSPORT=http) |
LOG_LEVEL | No | info | Logging level: error, warn, info, debug |
REQUEST_TIMEOUT | No | 60000 | HTTP request timeout in milliseconds |
ENABLED_API_CATEGORIES | No | all | Comma-separated list of API categories to enable (see below) |
MCP_READ_ONLY | No | false | true registers no create, update or delete tool, hides them from discovery, and refuses every request other than GET. For production tenants that agents should only read |
API Categories
Use ENABLED_API_CATEGORIES to restrict which tool groups are registered:
| Category | Description |
|---|---|
integration-content | Integration packages, iFlows, value/message mappings, script collections, custom tags, deploy status |
message-processing-logs | Message processing logs, ID mappings, idempotent repository |
message-stores | Data stores, variables, number ranges, message stores, JMS brokers and queues |
log-files | System log files and log file archives |
security-content | Keystores, certificates, SSH keys, credentials, OAuth2 clients, secure parameters, access policies |
partner-directory | Partners, string/binary parameters, alternative partners, authorized users |
Set to all (the default) to enable every category.
Available Tools
Tools are dynamically generated from entity set definitions. Each entity set produces up to five tools (_list, _get, _create, _update, _delete) plus navigation property tools, depending on what the OData API supports.
Integration Content
| Tool | Operations |
|---|---|
IntegrationPackages | list, get, create, update, delete |
IntegrationDesigntimeArtifacts | list, get, create, update, delete + Resources, Configurations |
IntegrationRuntimeArtifacts | list, get |
ValueMappingDesigntimeArtifacts | list, get, create, update, delete + ValMapSchema |
MessageMappingDesigntimeArtifacts | list, get, create, update, delete |
ScriptCollectionDesigntimeArtifacts | list, get, create, update, delete |
CustomTagConfigurations | list, get, create, update, delete |
BuildAndDeployStatus | list, get |
Message Processing Logs
| Tool | Operations |
|---|---|
MessageProcessingLogs | list, get + Attachments, ErrorInformations, AdapterAttributes, CustomHeaderProperties, MessageStoreEntries |
IdMapFromId2s | list |
IdempotentRepositoryEntries | list |
Message Stores
| Tool | Operations |
|---|---|
DataStoreEntries | list, get, delete |
Variables | list, get |
NumberRanges | list, get |
MessageStoreEntries | list, get |
JmsBrokers | list, get |
JmsResources | list |
Log Files
| Tool | Operations |
|---|---|
LogFiles | list, get |
LogFileArchives | list, get |
Security Content
| Tool | Operations |
|---|---|
KeystoreEntries | list, get, delete |
CertificateResources | list, get |
SSHKeyResources | list, get |
UserCredentials | list, get, create, update, delete |
OAuth2ClientCredentials | list, get, create, update, delete |
SecureParameters | list, get, create, update, delete |
CertificateUserMappings | list, get, create, update, delete |
AccessPolicies | list, get, create, update, delete + ArtifactReferences |
Partner Directory
| Tool | Operations |
|---|---|
Partners | list, get, create, update, delete |
StringParameters | list, get, create, update, delete |
BinaryParameters | list, get, create, update, delete |
AlternativePartners | list, get, create, update, delete |
AuthorizedUsers | list, get, create, update, delete |
Tool Naming Convention
Tools follow the pattern {EntitySet}_{operation}:
IntegrationPackages_list
IntegrationPackages_get
IntegrationPackages_create
IntegrationDesigntimeArtifacts_Configurations_list
MessageProcessingLogs_ErrorInformations_list
OData Query Parameters
All _list tools accept standard OData V2 query options:
$filter-- e.g.,"Status eq 'FAILED'"$select-- e.g.,"Id,Name,Status"$expand-- e.g.,"Configurations"$orderby-- e.g.,"Name asc"$top-- e.g.,10$skip-- e.g.,20
Response Bodies
Tool results are decoded from the raw response bytes:
- JSON content types (
application/json,*+json) are returned parsed. - Any other body that is valid UTF-8 is returned as text, e.g. a Groovy script from
.../Resources(...)/$value. - Anything else, such as an iflow zip from
IntegrationDesigntimeArtifacts(Id='...',Version='active')/$value, is returned losslessly as a base64 envelope:
{ "contentType": "application/zip", "encoding": "base64", "size": 21605, "data": "UEsDBBQACAgI..." }
The data value can be passed unchanged as base64 content (e.g. ArtifactContent) to a _create or _update call, which is how an artifact is copied.
Transport Modes
HTTP (Streamable HTTP)
Used for BTP Cloud Foundry deployment. The server exposes an /mcp endpoint supporting the MCP Streamable HTTP transport with session management, plus a /health endpoint for CF health checks.
MCP_TRANSPORT=http PORT=4004 npm start
stdio
Used for local development and direct integration with Claude Desktop. Communication happens over standard input/output streams.
MCP_TRANSPORT=stdio npm start
Tech Stack
- Runtime: Node.js 20+ with ES Modules
- Language: TypeScript 5.7+
- MCP SDK:
@modelcontextprotocol/sdk1.17+ - SAP Cloud SDK:
@sap-cloud-sdk/connectivityand@sap-cloud-sdk/http-client4.x for destination resolution and HTTP calls - Validation: Zod for configuration and input validation
- HTTP Framework: Express 4.x (HTTP transport only)
- Logging: Winston
License
MIT
History
Others providing
Compare all 39 on the Agent access to your systems page →- mcp-integration-suitemcp-integration-suiteAn experimental Node MCP server covering the general CPI functions of the Integration Suite, which its author recommends running alongside the TPM server for Trading Partner Management.independent, btpMCP server for the general Integration Suite functionsfrom BTP/BAIP
- mcp-is-tpmmcp-is-tpmA Java MCP server for Trading Partner Management in the Integration Suite, where trading partners, their agreements and their B2B configuration live, paired by its author with the general server.independent, btpJava MCP server for Integration Suite Trading Partner Managementfrom BTP/BAIP
- @abap2ui5/mcp-server@abap2ui5/mcp-serverAn MCP server that puts the abap2UI5 development loop on the machine an agent runs on: check the view the ABAP builds, photograph it, deploy the class into a sandbox, boot the app headless and read the errors.community org, abapMCP server for the abap2UI5 check, deploy and run loopfrom ABAP
- abap2UI5 for VS Codeabap2UI5 for VS CodeA VS Code extension for abap2UI5 apps: F9 starts the app class in a preview beside the source, Ctrl+F3 activates the class and reloads it, and the abap2UI5 linter runs in the editor while you type.community org, abapVS Code extension to preview, activate and lint abap2UI5 appsfrom ABAP
- SF-MCPSF-MCPSixty-two purpose-built tools over SAP SuccessFactors' OData APIs — employee data, permissions, compliance reports and HR administration, asked for in plain language.independent, successfactorsMCP server with 62 tools over SAP SuccessFactors OData APIsfrom SAP SuccessFactors
- hybris-mcp-litehybris-mcp-liteA read-only MCP server that answers questions about a local SAP Commerce Cloud instance by calling HAC, so types, beans, configuration, cronjobs, logs and FlexibleSearch come back in the editor.independent, commerceRead-only MCP server over a local SAP Commerce Cloud's HACfrom SAP Commerce
- calmcpcalmcpAn MCP server in front of the SAP Cloud ALM APIs: four read tools over tasks, projects, features, documents, tests and analytics, run over stdio locally or Streamable HTTP on Cloud Foundry.independent, btpMCP server with read tools over the SAP Cloud ALM APIsfrom BTP/BAIP
- CostingGeek/sap-mcpCostingGeek/sap-mcpA Python server that fetches sales orders from SAP's business data graph and hands them to Claude Desktop — the only entry here pointed at that API rather than at one system's own services.independent, btpPython MCP server fetching sales orders from SAP's business data graphfrom BTP/BAIP
- mcp-sap-focusedrunmcp-sap-focusedrunSAP Focused Run's Landscape Management Database as MCP tools — hosts, systems, databases, cloud tenants, technical instances, ABAP clients, software components and product versions.independent, btpMCP tools over SAP Focused Run's Landscape Management Databasefrom BTP/BAIP
- abapsmithabapsmithAn MCP server that lets an LLM develop in ABAP on a live system over ADT, with writes off by default and every mutation recorded in a local journal that can undo it.independent, abapABAP MCP server over ADT with a local journal that can undo writesfrom ABAP
- cloud-alm-itsm-mcpcloud-alm-itsm-mcpQueries installations through SAP Cloud ALM's ITSM API — filtered by system type or customer number, with OAuth token handling and caching done for you.independent, btpMCP server querying installations via the SAP Cloud ALM ITSM APIfrom BTP/BAIP
- hana-mcp-serverhana-mcp-serverSchema discovery and guard-railed SQL against SAP HANA and HANA Cloud, with an optional layer of business metadata so an agent reads a coded column the way the business does.independent, btpMCP server for schema discovery and guarded SQL on SAP HANAfrom BTP/BAIP
- sap_analytics_cloud_mcpsap_analytics_cloud_mcpThe SAP Analytics Cloud REST API as ninety tools across eleven service areas — content, data import and export, user management, transport, scheduling and translation.independent, btpMCP server for the SAP Analytics Cloud REST APIfrom BTP/BAIP
- mcp-sap-cpimcp-sap-cpiThe runtime half of Cloud Integration: failed messages with their full processing logs and traces, artifact deployment, security material, and a health summary.independent, btpMCP server for Cloud Integration runtime: messages, logs, deploymentfrom BTP/BAIP
- AI Core MCP ServerAI Core MCP ServerAn MCP server that exposes SAP AI Core's APIs as tools, defined entirely in one JSON config file for a proxy, so deployments, configurations and scenarios are managed through an assistant.independent, btpSAP AI Core APIs as MCP tools from one JSON config filefrom BTP/BAIP
- BTP CF MCP ServerBTP CF MCP ServerThe Cloud Foundry V3 API on SAP BTP as MCP tools — apps, orgs, spaces, services, routes and quotas — declared in one JSON config file and run by odata-mcp-proxy.independent, btpCloud Foundry V3 API on SAP BTP as MCP toolsfrom BTP/BAIP
- BTP MCP ServerBTP MCP ServerBTP Core Services as MCP tools, and the only server in this corner that renders dashboards inside the chat — a subaccount overview with drill-down, a geomap of data-centre locations, consumption and users.independent, btpBTP Core Services as MCP tools with in-chat dashboardsfrom BTP/BAIP
- btp-sap-odata-to-mcp-serverbtp-sap-odata-to-mcp-serverExposes every OData service on an S/4HANA or ECC system as MCP tools, in three discovery levels so a large catalogue does not have to be loaded at once.independent, btpExposes S/4HANA or ECC OData services as MCP toolsfrom BTP/BAIP
- CI MCP ServerCI MCP ServerAn MCP server that exposes SAP Cloud Integration's OData APIs as tools, defined entirely in one JSON config file, so an assistant works integration content, logs and configurations in natural language.independent, btpSAP Cloud Integration OData APIs as MCP toolsfrom BTP/BAIP
- sap-pi-mcp-serversap-pi-mcp-serverThe only entry pointed at SAP PI and PO rather than at Cloud Integration — monitoring and Integration Directory metadata from the middleware that came before.independent, btpMCP server for SAP PI and PO monitoring and directory metadatafrom BTP/BAIP
- sap-bdc-mcp-serversap-bdc-mcp-serverAn MCP server over SAP's BDC Connect SDK that creates, validates, publishes and deletes Databricks Delta shares as data products in SAP Business Data Cloud.independent, btpMCP server managing Delta shares in SAP Business Data Cloudfrom BTP/BAIP
- @mariodefe/sap-datasphere-mcp@mariodefe/sap-datasphere-mcpForty-five tools across a Datasphere tenant — discovery, metadata, analytics, ETL extraction, database users, lineage and column profiling — with config-driven PII masking applied before anything reaches the model.independent, btpMCP server with forty-five tools across a Datasphere tenantfrom BTP/BAIP
- midasol/sap-mcp-servermidasol/sap-mcp-serverA Python MCP server for SAP Gateway with four read-only tools that authenticate, query, fetch one entity and list services, and one of the few here that publishes its test results.independent, btpPython MCP server for SAP Gateway OData operationsfrom BTP/BAIP
- odata_mcp_goodata_mcp_goA Go binary that bridges any OData v2 or v4 service to MCP — and can collapse the whole service into one tool when the generated tool list is too large to be usable.independent, btpGo binary bridging any OData v2 or v4 service to MCPfrom BTP/BAIP
- odata_mcpodata_mcpThe Python original: reads an OData v2 service's metadata and generates MCP tools from it, with the SAP-specific conversions the raw protocol leaves to you.independent, btpPython bridge generating MCP tools from OData v2 metadatafrom BTP/BAIP
- sap-bdc-mcpsap-bdc-mcpDiscovery and contract tooling for SAP Business Data Cloud — ORD discovery, CSN contract checks and non-executing share planning — behind redaction, policy gates and bounded output.independent, btpMCP tooling for SAP Business Data Cloud discovery and contractsfrom BTP/BAIP
- mcp-sap-datasphere-servermcp-sap-datasphere-serverThe read-only Datasphere server: explore spaces, list assets, preview rows, profile columns and summarise analytical models — and nothing that changes anything, by design.independent, btpRead-only MCP server for exploring SAP Dataspherefrom BTP/BAIP
- sap-mcp-serversap-mcp-serverReads SAP ECC and S/4HANA for an agent over Gateway OData and RFC, with a Node bridge that speaks the RFC protocol without the proprietary SAP NetWeaver RFC SDK.independent, abapReads SAP ECC and S/4HANA for an agent over Gateway OData and RFC, with a Node bridge that speaks the RFC protocol without the proprietary SAP NetWeaver RFC SDK.from ABAP
- cap-mcp-bridgecap-mcp-bridgePoints at a running CAP or OData V4 service, reads its $metadata, and turns what it finds into MCP tools — list, describe, query with validated filters, expand, and invoke functions and actions.independent, capMCP server generating tools from a CAP or OData V4 service's metadatafrom CAP
- MCP Server for SAP BTP AdministrationMCP Server for SAP BTP AdministrationSAP-hosted MCP endpoint that exposes BTP account administration — accounts, security, services and connectivity — as tools an AI client discovers and calls on your behalf.sap official, btpSAP-hosted MCP endpoint for BTP account administrationfrom BTP/BAIP
- SAP LeanIX MCP ServerSAP LeanIX MCP ServerHosted MCP endpoint onto an SAP LeanIX instance, exposing selected enterprise-architecture APIs as tools — fact sheets, applications, completeness and custom reports.sap official, btpHosted MCP endpoint onto an SAP LeanIX instancefrom BTP/BAIP
- SAP-samples/hana-cli-claude-pluginSAP-samples/hana-cli-claude-pluginA Claude Code plugin that registers the MCP server of hana-cli, so Claude Code can work on SAP HANA Cloud and on-premise SAP HANA databases.sap official, btpClaude Code plugin registering hana-cli's MCP serverfrom BTP/BAIP
- SAP-samples/hana-developer-cli-tool-exampleSAP-samples/hana-developer-cli-tool-exampleA developer-centric command line for SAP HANA, built for local development outside SAP tooling and connecting to a local, cloud or remote HANA instance the same way.sap official, btpDeveloper-centric command line for SAP HANAfrom BTP/BAIP
- Skybuffer AI MCP serverSkybuffer AI MCP serverAn ABAP add-on that serves SAP business data, transactions and development context as MCP tools from an ICF node inside SAP ECC and S/4HANA, each call running as the signed-in user under PFCG authorization checks.independent, abapABAP add-on serving business data and transactions as MCP toolsfrom ABAP
- sap-security-mcpsap-security-mcpAn entirely read-only security analysis surface: nineteen tools, five resources and eight prompts for audits, SOX and segregation-of-duties review, behind OAuth 2.0 with PKCE. The vendor hosts an endpoint, and the README documents running it yourself.independent, abapRead-only security analysis MCP server for SAP audits and SoD reviewfrom ABAP
- cpi-mcp-servercpi-mcp-serverA Go server over Cloud Integration's design-time content — integration packages and integration flows, listed and searched by id, version, name, vendor or mode.independent, btpGo MCP server over Cloud Integration packages and integration flowsfrom BTP/BAIP
- KlystronKlystronAn MCP server written in ABAP that runs inside the application server behind an ICF service and exposes typed tools for ABAP development, quality, transports, customizing, roles, Basis operations and integration, with a client-side plugin of SAP skills.independent, abapMCP server in ABAP inside the application server, with agent skillsfrom ABAP
- pyrfc-mcppyrfc-mcpAn MCP server for calling an SAP system's RFC-enabled function modules from an agent, built so that discovering a function does not authorise calling it: a read or a write is denied unless the function name matches an allowlist the server is configured with.independent, abapMCP server calling RFC-enabled function modules behind an allowlistfrom ABAP
Details
Sources
Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.
Compatibility and provenance
History in the atlas
- The tag came in with the entry on 2026-09-10 and nothing sourced it: the README describes a config-driven proxy on BTP Cloud Foundry and names no CAP stack. Removed with its sibling configs; the entry stays on BTP, its home.
- The concern it answers is reaching into an SAP system from outside, split out of MCP servers on this day; the sentence on the edge is unchanged.
- Triaged out of data/crawled/mcp-candidates.json, the sap-ai-mcp-servers sweep. Written from the repository's own README; the catalogue is credited as where it was found and its words are not reused.
- First seen.
For your agent
- Ref
artifact:lemaiwo-odata-mcp-proxy- JSON
- /artifacts/lemaiwo-odata-mcp-proxy.json
- MCP
- Connecting an agent