CDS pluginCDS plugintypeInstalls into a CAP project and extends the runtime. CAP loads it through cds.requires or the plugin hook.See every one →What this type is →independently maintainedindependently maintainedoriginPublished by one person or a small company outside SAP. Says nothing about quality; the readings say that.See every one →

cap-mcp-plugin

Generates an MCP server from a CDS model: annotated entities become MCP resources, functions and actions become tools, and services can expose reusable prompt templates. A fork of @gavdi/cap-mcp that adds an OAuth proxy, IAS client registration and draft-lifecycle tools.

An agent that needs to reach a CAP service has nothing to talk to: the model is in CDS, and giving an MCP client access otherwise means writing and maintaining a second server that restates the entities, their query options and their actions by hand. This plugin derives that server from the CDS model — entities carrying an @mcp annotation become MCP resources that accept OData v4 query options such as $filter, $orderby, $top, $skip and $select, and annotated functions and actions become tools whose parameter schemas come from their signatures. Draft-enabled entities additionally get the draft lifecycle as tools, and @UI.* annotations already on the model render as Fiori list and object pages served back as interactive resources. It is a fork of @gavdi/cap-mcp that adds OAuth per RFC 9728, IAS and approuter deployment, and persists sessions in a CAP entity so multiple instances can serve the same endpoint.

Facts

Last pushLicenceApache-2.0

Where it sits

Lives in
Provides
Serve your application over MCPCAPServe your application over MCPcapabilityExposing selected application data and business operations to an AI agent through the Model Context Protocol. An application may also integrate remote services through [service integration](capability:service-integration), connecting its exposed contract with [agent access to your systems](capability:agent-systems-access). Development assistance belongs to [agent access to your code](capability:agent-code-access).
Flavors
Node.jsfrom its runtime

Who is behind it

Sören LeibachSören LeibachPersonMaintains this
In the atlas: maintains 6, contributes to 5, wrote 1
@sleibach
maintainer

Before choosing this

Conditions

LicenceSAP Developer License Agreement 3.2 CAP§ 1, 2, 3A cds-plugin is used with SAP CAP materials, or an artifact is explicitly identified as a CAP plugin or application.
  • § 1 License. Productive customer applications are limited to SAP BTP or another SAP-licensed platform, and mass extraction to a non-SAP product is restricted except where solely required for SAP interoperability.
  • § 2 Intellectual Property. The agreement retains SAP's rights in the covered materials and limits making APIs, tools or software available to third parties, while preserving ownership of customer applications subject to SAP's underlying rights.
  • § 3 Artificial Intelligence Training. The agreement prohibits use of the covered materials and customer applications for training artificial-intelligence models or systems.
SAP Developer License Agreement 3.2 CAP →

Also, from Serve your application over MCP§ 1, 3: The CAP developer agreement can apply alongside the API Policy. Ordinary agent inference is not automatically AI training; section 3 becomes relevant when covered materials or applications are used to train, develop or refine a model or system.

PracticalFunctional boundary

Not published to npm. Install from source.

PolicySAP API Policy 4.2026a§ 1.1, 1.2, 2.2.2from Serve your application over MCPAn MCP server exposes an SAP API, or 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
CDS plugin
Origin
Independently maintained
Runtime
Node.js

As a CDS plugin

Distributed through
npm

For serve your application over MCP

Exposure source
CAP service contract
Exposed operations
Queries, bound/unbound operations, configured CRUD and draft lifecycle; draft roots reject direct active-row writes unless bypass is enabled
Context delivery
MCP resourcesMCP promptsSchema hintsInteractive UI resourcesServer instructions
Execution path
CAP service calls
Exposure control
Entity/operation annotationsWrapper configurationOutput filtering

Tasks this contributes to9Beta

Access an external system through an application MCP serviceAn AI agent queries external system data or invokes selected external operations through an application-owned service contract exposed over MCP.Node.js2 scopes
CAP Node.jsCovers, under conditions

Dated assessment history · last accepted 2026-10-12. Excluded from the current connected answer.

What it does

cap-mcp-plugin — The inspected source dispatches queries and operations through the CAP application service, leaving remote integration to its handlers.

Conditions

Install from source; the README requires Node.js 18+, @sap/cds 9+ and Express 4+.; Annotate the application contract and configure authentication, deployment and session storage.; @mcp.omit filters output only; omitted fields remain queryable in the underlying service and can still be supplied to writes.; Implement outbound handlers and backend authorization; the server does not configure remote APIs.

Remaining work

Implement and test the application and remote handlers, enforce client/backend permissions and confirm target-specific use.

All options on the Serve your application over MCP page →
CAP Node.jsAssessed, not known

Dated assessment history · last accepted 2026-10-12. Excluded from the current connected answer.

What it does

cap-mcp-plugin — The documented CAP service dispatch/custom-tool mechanism is relevant, but the captured evidence does not establish this implementation as a supported bridge to the selected SAP Application API.

Conditions

Install from source; the README requires Node.js 18+, @sap/cds 9+ and Express 4+.; Annotate the application contract and configure authentication, deployment and session storage.; @mcp.omit filters output only; omitted fields remain queryable in the underlying service and can still be supplied to writes.; Implement outbound handlers and backend authorization; the server does not configure remote APIs.; No SAP Application API agent-access endorsement or deployment-specific permission was established by these sources.

Remaining work

Implement and test the application and remote handlers, enforce client/backend permissions and confirm target-specific use.

All options on the Serve your application over MCP page →
Change application records from an agentCreate or update application records through an MCP client.Node.jsCovers, under conditionsentity wrapper adapter
What it does

cap-mcp-plugin exposes configured active-record create, update and delete wrapper tools.

Conditions

Install cap-mcp-plugin from its GitHub source into a CAP Node.js application; no npm package is declared.; Configure the MCP endpoint and the model annotations.; Enable the required wrapper modes; draft roots require the separately documented draft lifecycle unless draft bypass is configured.; The README requires Node.js 18+, @sap/cds 9+ and Express 4+.

Remaining work

Own application validation, permissions and deployment; @mcp.omit filters output only.

All options on the Serve your application over MCP page →
Edit and activate draft records from an agentCreate or edit a draft record and activate or discard the pending change through MCP.Node.jsCovers, under conditionsdraft lifecycle adapter
What it does

cap-mcp-plugin exposes draft-new, draft-edit, draft-patch, draft-activate and draft-discard tools for draft-enabled roots.

Conditions

Install cap-mcp-plugin from its GitHub source into a CAP Node.js application; no npm package is declared.; Configure the MCP endpoint and the model annotations.; Use draft-enabled roots and a consistent authenticated principal across draft calls.

Remaining work

Implement application validation and authorization and account for draft locking and activation failures.

All options on the Serve your application over MCP page →
Expose an application service to an AI agentLet an MCP client discover and query application data and invoke selected business operations.Node.jsCovers, under conditionsapplication plugin

Dated assessment history · last accepted 2026-10-12. Excluded from the current connected answer.

What it does

cap-mcp-plugin derives MCP resources and tools from annotated CDS entities and operations.

Conditions

Install cap-mcp-plugin from its GitHub source into a CAP Node.js application; no npm package is declared.; Configure the MCP endpoint and the model annotations.; The README requires Node.js 18+, @sap/cds 9+ and Express 4+.

Remaining work

Choose annotations, configure authorization and session handling and validate the selected application operations.

All options on the Serve your application over MCP page →
Invoke a business operation from an agentInvoke a selected application business operation through an MCP tool.Node.jsCovers, under conditionsmodel-derived tool adapter
What it does

cap-mcp-plugin turns annotated application functions and actions into tools.

Conditions

Install cap-mcp-plugin from its GitHub source into a CAP Node.js application; no npm package is declared.; Configure the MCP endpoint and the model annotations.; The README requires Node.js 18+, @sap/cds 9+ and Express 4+.

Remaining work

Implement and authorize the operation; elicitation is limited to direct tools, not entity wrappers.

All options on the Serve your application over MCP page →
Provide application context as MCP resourcesLet an MCP client retrieve application data or schema context through resource URIs.Node.jsCovers, under conditionsentity resource adapter
What it does

cap-mcp-plugin derives resources from annotated CDS entities.

Conditions

Install cap-mcp-plugin from its GitHub source into a CAP Node.js application; no npm package is declared.; Configure the MCP endpoint and the model annotations.; The README requires Node.js 18+, @sap/cds 9+ and Express 4+.; Dynamic resource queries must supply all declared query parameters because of the documented SDK limitation.

Remaining work

Choose the exposed data, fields and permissions; interactive UI resources are a separate task.

All options on the Serve your application over MCP page →
Publish reusable MCP promptsLet an MCP client discover and retrieve reusable, parameterized interaction templates.Node.jsCovers, under conditionsprompt template adapter
What it does

cap-mcp-plugin publishes reusable prompt templates declared on the service.

Conditions

Install cap-mcp-plugin from its GitHub source into a CAP Node.js application; no npm package is declared.; Configure the MCP endpoint and the model annotations.; The README requires Node.js 18+, @sap/cds 9+ and Express 4+.

Remaining work

Author template inputs and content and arrange client access.

All options on the Serve your application over MCP page →
Query application data from an agentRetrieve selected application records through MCP without changing those records.Node.jsCovers, under conditionsmodel-derived resource/tool adapter
What it does

cap-mcp-plugin exposes annotated entities as resources and query/get wrapper tools.

Conditions

Install cap-mcp-plugin from its GitHub source into a CAP Node.js application; no npm package is declared.; Configure the MCP endpoint and the model annotations.

Remaining work

Select the model surface and read modes, configure authorization and choose session handling.

All options on the Serve your application over MCP page →
Show an application view inside an MCP clientRender an interactive application list or detail view inside a supporting MCP client.Node.jsCovers, under conditionsMCP Apps resource adapter
What it does

cap-mcp-plugin registers interactive list/detail HTML resources for wrapped entities with Fiori UI annotations.

Conditions

Install cap-mcp-plugin from its GitHub source into a CAP Node.js application; no npm package is declared.; Configure the MCP endpoint and the model annotations.; Use an MCP host that supports the MCP Apps extension and annotate the entity with @mcp.wrap.tools and Fiori UI metadata.

Remaining work

Configure host rendering/CSP and permitted writes; read-only UI settings do not disable the underlying write tools.

All options on the Serve your application over MCP page →

Connections3

cap-mcp-plugin connectionscap-mcp-pluginFUNCTIONAL→ alternative to2alternative to authored@cap-js/mcpalternative to authored@gavdi/cap-mcp→ provides1provides stated Generates MCP entity resources and bound/unbound operation tools for CAP [Node.js](external:nodejs), with configured CRUD wrappers, a draft lifecycle and optional Fiori-derived MCP Apps. The README requires [Node.js](external:nodejs) 18+, CAP 9+ and Express 4+. Resource/tool annotations and wrapper modes select the exposed surface; resource reads and direct operation tools call CAP service transactions in the pinned implementation. Entity resources, prompt templates and @mcp.hint schemas supply context, instructions configures server instructions, and MCP Apps require @mcp.wrap.tools with Fiori annotations. @mcp.omit filters output only, and disabling app write buttons leaves tools callable. cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin sleibach/cap-mcp-plugin — resources.js at 5359398d0662f452d31529509c67634f8eb5406d: https://raw.githubusercontent.com/sleibach/cap-mcp-plugin/5359398d0662f452d31529509c67634f8eb5406d/lib/mcp/resources.js sleibach/cap-mcp-plugin — tools.js at 5359398d0662f452d31529509c67634f8eb5406d: https://raw.githubusercontent.com/sleibach/cap-mcp-plugin/5359398d0662f452d31529509c67634f8eb5406d/lib/mcp/tools.js cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-plugin cap-mcp-plugin — sleibach/cap-mcp-plugin README: https://github.com/sleibach/cap-mcp-pluginServe your application over MCP

README

quoted from sleibach/cap-mcp-plugin under Apache-2.0, read
sleibach/cap-mcp-plugin/README.mdOn GitHub

CAP MCP Plugin

License

A CAP (SAP Cloud Application Programming) plugin that generates a Model Context Protocol (MCP) server from your CDS model. Annotated entities become MCP resources, functions and actions become tools, and services can expose reusable prompt templates.

Credits

This plugin is based on the excellent @gavdi/cap-mcp plugin by Gavdi Labs. The annotation model, entity-to-resource generation, tool wrapping, and prompt templates all originate from that project. Full credit for the original design and implementation goes to the Gavdi Labs team and the contributors of the upstream repository.

This repository is an independent development line that extends the original with additional work around OAuth, IAS integration, approuter deployment, and related enterprise-auth concerns. Upstream and this fork are maintained separately; if you want the canonical, vendor-supported plugin, use the upstream.

This line is not intended for pull requests back into Gavdi’s repo. On GitHub the repository may still be registered as a fork, which causes compare/merge suggestions from the upstream network until you detach it (one-time, on github.com): Settings → General → scroll to Danger Zone → Leave fork network and confirm with the repository name. Your local clone should only list origin (git remote -v); do not add an upstream remote unless you explicitly want to track Gavdi’s branch.

For protocol details, see the MCP specification.

Features

  • Expose CDS entities as MCP resources with OData v4 query support ($filter, $orderby, $top, $skip, $select).
  • Expose CDS functions and actions as MCP tools — both unbound (service-level) and bound (entity-level).
  • Wrap entities as CRUD-style tools (query, get, optional create / update) for LLM tool-use.
  • Auto-generate MCP Apps — interactive SAP Fiori UIs (list & object page) from existing @UI.* annotations, with Create/Edit/Delete.
  • Declare reusable prompt templates.
  • Request user confirmation or parameter input before tool execution (elicitation).
  • Filter sensitive fields from MCP output via @mcp.omit.
  • Enrich schemas for AI agents via @mcp.hint on elements and parameters.
  • Auth modes: inherit (use CAP's configured auth — mocked, basic, jwt, xsuaa, ias) or none.
  • Built-in OAuth proxy with RFC 9728 protected-resource metadata and DCR emulation for IAS.

Requirements

  • Node.js 18+
  • @sap/cds 9+
  • express 4+

Install

There is no npm registry package yet. Install straight from GitHub:

npm install github:sleibach/cap-mcp-plugin

(Optionally pin a branch or tag: github:sleibach/cap-mcp-plugin#main or #v1.3.0 once you publish tags.)

The plugin follows CAP’s standard plugin architecture and is picked up automatically once it is listed in your app’s dependencies.

Configure

Add an mcp block under cds in package.json:

{
  "cds": {
    "mcp": {
      "name": "my-bookshop-mcp",
      "auth": "inherit",
      "wrap_entities_to_actions": false,
      "wrap_entity_modes": ["query", "get"],
      "instructions": "MCP server instructions for agents"
    }
  }
}

Annotate your services

// srv/catalog-service.cds
service CatalogService {

  @mcp: {
    name: 'books',
    description: 'Book catalog with search and filtering',
    resource: ['filter', 'orderby', 'select', 'top', 'skip']
  }
  entity Books as projection on my.Books;

  annotate CatalogService.Books with @mcp.wrap: {
    tools: true,
    modes: ['query', 'get'],
    hint: 'Use for read-only lookups of books'
  };

  @mcp: {
    name: 'get-book-recommendations',
    description: 'Get personalized book recommendations',
    tool: true
  }
  function getRecommendations(genre: String, limit: Integer) returns array of String;
}

Run

cds serve

Endpoints:

  • MCP: http://localhost:4004/mcp
  • Health: http://localhost:4004/mcp/health

Annotation reference

Resources (@mcp.resource)
service CatalogService {

  @readonly
  @mcp: {
    name       : 'books',
    description: 'Book data list',
    resource   : ['filter', 'orderby', 'select', 'skip', 'top']
  }
  entity Books as projection on my.Books;

  // Enable all OData query options
  @mcp: {
    name       : 'authors',
    description: 'Author data list',
    resource   : true
  }
  entity Authors as projection on my.Authors;

  // Static top-100 list (no query options)
  @mcp: {
    name       : 'genres',
    description: 'Book genre list',
    resource   : []
  }
  entity Genres as projection on my.Genres;
}
Entity wrappers (@mcp.wrap)

When wrap_entities_to_actions is enabled globally, or a specific entity is annotated with @mcp.wrap.tools: true, each entity is also exposed as a set of tools:

  • If the entity has @mcp.name on its resource block, wrapper tools use {name}_query, {name}_get, etc. (keeps IDs short—many MCP clients limit tool name to 64 characters; long service + entity names alone can exceed that).
  • Otherwise the legacy pattern: <Service>_<Entity>_query, <Service>_<Entity>_get, …
annotate CatalogService.Books with @mcp.wrap: {
  tools: true,
  modes: ['query', 'get', 'create', 'update'],
  hint : 'Use for read and write demo operations'
};

Available modes:

  • query — list/search rows (supports top, skip, select, where, orderby, q, expand, return, aggregate, explain).
  • get — read a single row by key(s).
  • create — insert a new active row.
  • update — patch an active row by key(s).
  • delete — remove a row by key(s).
  • draft-new — create a pending draft (registers automatically on @odata.draft.enabled / @fiori.draft.enabled roots).
  • draft-edit — start editing an existing active row (creates a draft copy).
  • draft-patch — apply field changes to an existing draft.
  • draft-activate — publish the pending draft to the active row.
  • draft-discard — drop the pending draft without touching the active row.
  • draft-upsert — one-shot: creates a draft and immediately activates it in a single transaction (use when all required fields are known up front).
Read bundling (read_bundle)

A model that wraps many entities produces a lot of tools — two per entity for reads alone (_query + _get). MCP clients that load tools on demand via semantic search struggle when dozens of near-identical read tools compete for the same matches. Read bundling (opt-in) collapses the per-entity query/get tools into a single consolidated read tool per group, so e.g. 30 mails-*_query/_get tools become one MailService_read. Write and draft tools stay per-entity (precise schemas, explicit dangerous surface).

Enable it globally:

{
  "cds": {
    "mcp": {
      "read_bundle": { "enabled": true, "group_by": "service" }
    }
  }
}

The consolidated tool takes a resource discriminator (an enum of the bundled resource names) plus mode (query | get) and generic params (filter, select, orderby, top, skip, expand, q, return, aggregate, IsActiveEntity). Its description enumerates every bundled resource with its keys and read modes; for a resource's exact fields and example payloads, the agent calls cap_describe_model with the resource name. The filter param is a standard OData $filter expression (e.g. stock gt 0 and price le 50, contains(title,'sql'), genre_ID in (1,2)), parsed via CAP's own OData parser — agents tend to be more fluent in OData filter syntax than CQL.

Grouping:

  • group_by: "service" (default) — one read tool per CAP service (<Service>_read). Zero extra annotation work.

  • group_by: "annotation" — group by @mcp.wrap.group on each entity, falling back to the service name when an entity has no group. Lets you split a large service into a few semantic bundles:

    annotate MailService.Mails with @mcp.wrap: { tools: true, modes: ['query', 'get'], group: 'mails' };

Notes:

  • Opt-in — with read_bundle.enabled: false (default) the per-entity query/get tools are registered exactly as before. Nothing changes until you turn it on.
  • Auth — a bundle lists when the caller can read at least one member; the specific resource is re-checked at call time (@requires / @restrict per entity is honored, returning FORBIDDEN for resources the caller can't read).
  • tool_suffix (default "read") controls the tool-name suffix: MailService_read.
Draft lifecycle

For draft-enabled roots (annotated with @odata.draft.enabled or @fiori.draft.enabled), the wrapper:

  • Auto-registers the five draft-* tools listed above alongside the CRUD tools — no need to list them explicitly in @mcp.wrap.modes.
  • Short-circuits active-row create, update, and delete with a DRAFT_REQUIRED error that names the relevant draft-new / draft-edit / draft-patch / draft-activate / draft-discard tools. This replaces the opaque CAP runtime error that surfaces when a caller tries to bypass the draft pipeline, and — crucially — it sidesteps synchronous @assert.target FK validation on create. The Fiori draft runtime defers those checks until activation, so an FK pointing at a remote / S/4 value-help source that can't be resolved synchronously still lets the draft land.
    • Exception: entities annotated with @odata.draft.bypass (or the whole service with cds.env.fiori.bypass_draft: true) continue to accept direct active-row create/update/delete, matching CAP's own bypass semantics. The draft-* tools remain available for callers that prefer the lifecycle.
  • Extends get and query with an optional IsActiveEntity parameter:
    • get defaults to true (reads the active row). Pass false to read the draft sibling.
    • query returns both active and draft rows when omitted; pass true or false to narrow the result.
  • Surfaces draft admin fields (HasActiveEntity, HasDraftEntity, DraftAdministrativeData) on read responses so the LLM can reason about locks and pending edits.

Typical round-trip:

// 1. Create a draft
tools/call { "name": "books_draft-new", "arguments": { "ID": 42, "title": "Draft Title" } }
// 2. Patch fields on the draft
tools/call { "name": "books_draft-patch", "arguments": { "ID": 42, "stock": 5 } }
// 3. Publish to the active row
tools/call { "name": "books_draft-activate", "arguments": { "ID": 42 } }

// Edit an existing active row:
tools/call { "name": "books_draft-edit", "arguments": { "ID": 42 } }
// ... then draft-patch + draft-activate, or draft-discard to throw away.

// One-shot create + activate (single transaction, single principal):
tools/call { "name": "books_draft-upsert", "arguments": { "ID": 43, "title": "Atomic Insert", "stock": 7 } }
draft-upsert: one-shot for stateless MCP callers

Each MCP tool call is a standalone HTTP request. If the authenticated principal drifts between the request that opened the draft (draft-new) and the request that publishes it (draft-activate) — for example because the MCP bearer token resolves to a different cds.context.user.id than the one that held the lock — the second call fails with DRAFT_LOCKED, even though the caller is the same human.

draft-upsert sidesteps this entirely: the NEW and SAVE events run on the same svc.tx({user}, …) callback, so the InProcessByUser written by NEW is guaranteed to match the principal at SAVE time. If SAVE fails (e.g. an un-filled @mandatory field), the transaction rolls back and no orphan draft is left behind.

Use it when:

  • The LLM already has all required fields up front (no iterative draft-patch needed).
  • You want a single atomic unit of work in the audit log.
  • You're running behind stateless MCP plumbing and want to rule out cross-call principal drift.

Use the discrete draft-new / draft-patch / draft-activate trio when the caller legitimately needs to inspect the pending draft between turns, or when draft-edit on an existing active row is the entry point.

Composite-key associations

Associations with more than one target key (e.g. technicalObject : Association to TechnicalObject where TechnicalObject is keyed on (TechnicalObject, ObjectType)) are surfaced as one flat parameter per generated FK column on create, update, draft-new, and draft-patch. The naming follows CAP's on-disk convention, {propName}_{targetKey}:

tools/call {
  "name": "change-requests_draft-new",
  "arguments": {
    "ID": "…",
    "title": "…",
    "technicalObject_TechnicalObject": "7500008",
    "technicalObject_ObjectType": "E"
  }
}

Single-key associations degenerate to the familiar {propName}_ID form. Supplying only a subset of the FK columns produces ASSERT_DATA_TYPE — the error now includes a hint pointing at the missing FK columns.

@mandatory and activation-time validation

@mandatory and @assert.* constraints on draft-enabled roots are deferred to activation: draft-new / draft-patch accept partial payloads, and the validation pipeline runs when draft-activate calls SAVE. A violation returns DRAFT_ACTIVATE_FAILED with the offending field name in the message; the draft row survives so the caller can draft-patch the fix and re-activate.

Locking semantics

CAP stores the draft holder in DraftAdministrativeData.InProcessByUser, scoped to the authenticated principal. When a second caller (different bearer token or mocked user) tries to draft-patch / draft-activate a draft that another user owns, the plugin returns DRAFT_LOCKED with the holder's id in the message. Locks expire after cds.env.drafts.cancellationTimeout minutes (default: 15); draft-discard by the holder releases them immediately. MCP clients sharing the same bearer token share the principal, so draft-new → draft-patch in the same session is always the same user.

Enable DEBUG=mcp cds watch to get a one-line trace per draft operation ([draft-<op>] entity=<x> keys=<y> user=<z>) for on-call diagnostics.

Diagnosing DRAFT_LOCKED when the holder isn't you:

  1. The error message already names both identities: (held by <holder>) (you are '<caller>'). If those two ids differ, you know immediately that CAP's lock check is working correctly — the human you expected isn't the principal CAP resolved.
  2. Call cap_whoami (always registered, no annotation needed) for a full principal snapshot: id, roles, tenant, is_privileged, is_anonymous, and a plain-English diagnosis line. This is the fastest way to confirm whether MCP is running as anonymous, system, or a different SSO account than the Fiori UI.
  3. For continuous tracing during a repro, run the server with DEBUG=mcp cds watch. Every tool invocation writes one line: [draft-<op>] caller id='…' privileged=… anonymous=… tenant='…' roles=[…], plus the per-operation [draft-<op>] entity=… keys=… user=… trace for full draft-path visibility.
Error-code reference
CodeWhen it's raisedNext step
DRAFT_REQUIREDActive-row create/update/delete on a non-bypass draft rootSwitch to the draft-* tool named in the error message.
DRAFT_LOCKEDAnother user currently holds the draftRetry as that user, wait for the lock to expire, or coordinate discard.
DRAFT_ALREADY_EXISTSdraft-new on a row that already has a draft siblingUse draft-edit / draft-patch on the existing draft.
DRAFT_VALIDATION_FAILED@assert.* violation during draft-new / draft-patchCorrect the field values and retry.
DRAFT_ACTIVATE_FAILED@mandatory / @assert.* violation during draft-activatedraft-patch the missing / invalid field, then activate again.
DRAFT_UPSERT_FAILEDNEW or SAVE failed inside draft-upsert (transaction rolled back)Fix the offending field named in the message and retry draft-upsert.
ASSERT_DATA_TYPEPayload shape mismatches CSN (e.g. missing composite-FK column)Check every generated FK column and structured element is supplied.

See the CAP Fiori draft handling docs for concept background.

Tools (@mcp.tool)

CDS operations annotated with @mcp.tool: true become MCP tools. Both unbound (service-level) and bound (entity-level) operations are supported, and the distinction between action and function is preserved — either kind can be exposed. Parameter schemas are derived automatically from the CDS signature; input/output types (scalars, structured types, array of ...) flow through unchanged, and @mcp.hint on parameters enriches the schema shown to the LLM.

// Service-level (unbound) function
@mcp: {
  name       : 'get-author',
  description: 'Gets the desired author',
  tool       : true
}
function getAuthor(input: String) returns String;

// Service-level (unbound) action with a structured return type
@mcp: {
  name       : 'submit-order',
  description: 'Submits a new order',
  tool       : true
}
action submitOrder(cart: ManyCartItems) returns Order;

// Entity-level (bound) function — invoked against a specific Books row
extend projection Books with actions {
  @mcp: {
    name       : 'get-stock',
    description: 'Retrieves stock from a given book',
    tool       : true
  }
  function getStock() returns Integer;

  // Entity-level (bound) action
  @mcp: {
    name       : 'reorder',
    description: 'Triggers a reorder for the given book',
    tool       : true
  }
  action reorder(quantity: Integer) returns Boolean;
}

Bound operations automatically receive the entity's key(s) as additional tool parameters so the caller can target a specific row. The plugin picks them up regardless of whether the parent entity itself carries @mcp annotations — a bound tool on an un-annotated entity is still registered.

Tools can request user interaction before execution via elicit:

@mcp: {
  name       : 'book-recommendation',
  description: 'Get a random book recommendation',
  tool       : true,
  elicit     : ['confirm']            // yes/no prompt
}
function getBookRecommendation() returns String;

@mcp: {
  name       : 'get-author',
  description: 'Gets the desired author',
  tool       : true,
  elicit     : ['input']              // parameter form
}
function getAuthor(id: String) returns String;

@mcp: {
  name       : 'books-by-author',
  description: 'Gets a list of books made by the author',
  tool       : true,
  elicit     : ['input', 'confirm']   // form + confirmation
}
function getBooksByAuthor(authorName: String) returns array of String;

Elicitation is only available for direct tools; entity-wrapper tools do not support it.

Field hints (@mcp.hint)

Attach descriptions to entity properties, action parameters, and complex-type fields to improve the schema seen by the LLM:

entity Books {
  key ID    : Integer @mcp.hint: 'Must be a unique number not already in the system';
      title : String;
      stock : Integer @mcp.hint: 'The amount of books currently on store shelves';
}

@mcp: {
  name: 'books-by-author', description: '...', tool: true
}
function getBooksByAuthor(
  authorName : String @mcp.hint: 'Full name of the author you want to get the books of'
) returns array of String;

Hints flow into:

  • Resource field descriptions
  • Parameter schemas of direct tools and entity wrappers
  • Array element descriptions (applied to items, not the array)

Good hints are specific: state constraints, formats, and business meaning rather than restating the field name.

Omitting fields (@mcp.omit)
entity Books {
  key ID            : Integer;
      title         : String;
      stock         : Integer;
      secretMessage : String  @mcp.omit;   // hidden from MCP output
}

@mcp.omit filters MCP output only. Omitted fields can still be supplied as inputs on create / update operations and remain queryable in the underlying CAP service. Combine with @Core.Computed to make a field neither output nor writable.

Expand & deep reads (@mcp.expand)

Query and get tools accept an OData v4 $expand parameter with subquery options ($select, $filter, $top, $skip, $orderby, nested $expand). Without an explicit expand, every Composition on the entity is included automatically, so the LLM sees "parts of me" in one call instead of a scalar-plus-FK skeleton.

// tools/call arguments for <Service>_<Entity>_query and _get
{
  "expand": "address,identifiers($top=5;$filter=scheme eq 'GLN')"
}
  • Pass "" (empty string) to opt out at call time — the response drops back to scalars + foreign keys only.
  • Pass a full OData $expand string to override what is returned. The parser is schema-aware: it rejects unknown navigation properties and $select columns that don't exist on the target.
  • Only Compositions are auto-included. Associations stay opt-in — they frequently lead to very large graphs and shouldn't be pulled implicitly.

Per-entity override with @mcp.expand (accepted values: 'compositions', 'none', 'all'):

// Large entity that you do NOT want auto-expanded
annotate AdminService.Orders with @mcp.expand: 'none';

// Entity where you want associations included too
annotate AdminService.PartnerProfiles with @mcp.expand: 'all';

Runtime-wide configuration (also settable via CDS_MCP_EXPAND_MAX_DEPTH / CDS_MCP_EXPAND_MAX_BREADTH env vars):

{
  "cds": {
    "mcp": {
      "expand": {
        "default": "compositions",
        "max_depth": 3,
        "max_breadth": 20
      }
    }
  }
}

max_depth caps how deeply nested $expand can go (e.g. nav($expand=child($expand=grandchild)) is depth 3). max_breadth caps how many sibling nav props may appear at any one level. Both are validated during parse, so an over-broad request fails before any SQL is generated.

Prompt templates (@mcp.prompts)
annotate CatalogService with @mcp.prompts: [{
  name       : 'give-me-book-abstract',
  title      : 'Book Abstract',
  description: 'Gives an abstract of a book based on the title',
  template   : 'Search the internet and give me an abstract of the book {{book-id}}',
  role       : 'user',
  inputs     : [{ key: 'book-id', type: 'String' }]
}];

MCP Apps (interactive Fiori UIs)

MCP Apps (spec 2026-01-26) let an MCP tool render an interactive HTML UI inside the host (Claude, ChatGPT, VS Code, …) instead of returning plain text. This plugin auto-generates those UIs from the SAP Fiori @UI.* annotations your services already carry — no extra annotations needed.

When an entity has @mcp.wrap.tools and Fiori UI annotations, the plugin registers two ui:// HTML resources and links them to the entity's query / get tools via _meta.ui.resourceUri:

  • List view (ui://query/<Service>_<Entity>) — a SAP Fiori List Report rendered with a real sap.m.Table (SAPUI5, Morning/Evening Horizon theme), driven by @UI.LineItem.
  • Object page (ui://detail/<Service>_<Entity>) — a Fiori Object Page driven by @UI.HeaderInfo, @UI.Facets / @UI.FieldGroup, and @UI.DataPoint.

The host fetches the UI resource when the tool is called and renders it in a sandboxed iframe; the plugin pushes the tool result into it. Nothing changes for hosts that don't support MCP Apps — they keep getting the normal text/JSON tool result.

What it renders

Driven entirely by standard Fiori annotations on the entity:

AnnotationEffect in the app
@UI.LineItemTable columns (incl. DataField, DataFieldWithUrl, DataFieldForAction), sorted by @UI.Importance
@UI.LineItem @UI.CriticalityPer-row colored highlight bar
Criticality on a columnCell rendered as a Fiori ObjectStatus (semantic color + icon)
@UI.HeaderInfoObject-page title / subtitle / image (TypeName, Title, Description, ImageUrl)
@UI.Facets / @UI.FieldGroupObject-page sections and field groups
@UI.DataPoint + @UI.HeaderFacetsKPI / status strip on the object page
@Common.Text + @Common.TextArrangementKey/FK columns show their descriptive text (e.g. author_ID → author name)
@UI.Hidden / @UI.MultiLineTextHidden fields are omitted; long text renders multi-line

Association columns such as genre.name or currency.symbol resolve when the query expands those associations — set @mcp.expand: 'all' (see Expand & deep reads) on the entity. Flattened projections (genre.name as genre) are resolved automatically.

Write actions (Create / Edit / Delete)

The apps can drive writes by calling the entity's existing write tools back through the host — every write goes through the host's own tool-call consent/audit prompt, so the user approves each change. Buttons appear only when @mcp.wrap.modes allows the action:

  • List → a Create button opens a form of the entity's writable fields.
  • Object page → Edit (form pre-filled from the record) and Delete.

Draft-enabled roots route create/edit through the one-shot draft-upsert tool; non-draft entities use create / update. Read-only entities (no create/update/delete in modes) render without write buttons.

Example
// Reuse the same @UI annotations a Fiori Elements app would use:
annotate AdminService.Books with @(UI: {
  HeaderInfo : { TypeName: 'Book', TypeNamePlural: 'Books', Title: { Value: title }, Description: { Value: author.name } },
  LineItem   : [ { Value: ID }, { Value: author_ID }, { Value: genre.name }, { Value: stock }, { Value: price } ],
  FieldGroup #Details : { Data: [ { Value: title }, { Value: descr }, { Value: stock }, { Value: price } ] }
});

annotate AdminService.Books with @mcp.wrap: { tools: true, modes: ['query','get','create','update','delete'] };
annotate AdminService.Books with @mcp.expand: 'all'; // so association columns resolve
Requirements & notes
  • Rendering engine: the list table loads SAPUI5 (sap.m) from https://ui5.sap.com as a progressive enhancement. The sandboxed iframe must be allowed to load it — the plugin declares the origin in the resource's _meta.ui.csp. If the CDN is blocked, the app falls back to a self-contained, dependency-free CSS table (it never blanks).
  • Shell title shows the server name (cds.mcp.name); the entity collection name appears in the table toolbar.
  • Theme follows the host (SAP Morning Horizon in light, Evening Horizon in dark).
Disabling & scoping

MCP Apps are fully optional and can be dialed back at any granularity if they cause trouble:

{
  "cds": {
    "mcp": {
      "apps": {
        "enabled": true,   // master switch — set false to turn the feature off entirely
        "write":   true,   // set false for read-only apps (no Create/Edit/Delete buttons)
        "ui5":     true     // set false to skip the SAPUI5 CDN and always use the CSS table
      }
    }
  }
}
  • Turn it off completely → apps.enabled: false. The plugin registers no ui:// resources and adds no _meta.ui to any tool; everything reverts to plain text/JSON tool results.

  • Keep the UI but block edits → apps.write: false. Renders read-only list/detail apps.

  • Avoid the external SAPUI5 load (locked-down network, CSP issues, or the framework misbehaving) → apps.ui5: false. The list view then uses the self-contained CSS table — no ui5.sap.com fetch.

  • Per-entity opt-out → annotate a single entity to exclude it while leaving the rest enabled:

    annotate AdminService.Genres with @mcp.apps: false;

Configuration reference

{
  "cds": {
    "mcp": {
      "name": "my-mcp-server",
      "version": "1.0.0",
      "auth": "inherit",
      "instructions": "MCP server instructions for agents",
      "capabilities": {
        "resources": { "listChanged": true, "subscribe": false },
        "tools":     { "listChanged": true },
        "prompts":   { "listChanged": true }
      }
    }
  }
}
OptionTypeDefaultDescription
namestringpackage.json nameMCP server name
versionstringpackage.json versionMCP server version
auth"inherit" | "none""inherit"Authentication mode
instructionsstringnullServer-level instructions surfaced to agents
public_urlstringderivedCanonical external base URL advertised in OAuth metadata. Set when running behind an approuter on a different FQDN.
base_pathstring"/mcp"Mount path exposed to MCP clients; used as resource in oauth-protected-resource metadata.
trusted_proxiesbooleanfalseHonor X-Forwarded-Host/Proto/Prefix when building absolute URLs. Enable when fronted by an approuter.
oauth.proxy"enabled" | "disabled""enabled"Expose /oauth/* and /.well-known/oauth-authorization-server on the CAP backend. Disable when an upstream approuter handles OAuth.
oauth.protected_resource"enabled" | "disabled""enabled"Register the RFC 9728 /.well-known/oauth-protected-resource metadata endpoint.
session_store.kind"db" | "memory" | "stateless""db" when a DB binding exists, else "memory"Where MCP session state lives. "db" persists session IDs in a CAP entity; "stateless" issues no session IDs and handles every POST with a fresh transport (multi-instance safe, zero persistence); "memory" uses a per-process Map. See Session store.
session_store.entitystring"cap.mcp.Sessions"CSN entity injected programmatically for "db" kind. Override only on name clashes.
session_store.local_cache_ttl_msnumber600000How long a rehydrated transport is kept in the per-instance cache before it is dropped and re-fetched from the DB on the next request.
capabilities.resources.listChangedbooleantrueResource list-change notifications
capabilities.resources.subscribebooleanfalseResource subscriptions
capabilities.tools.listChangedbooleantrueTool list-change notifications
capabilities.prompts.listChangedbooleantruePrompt list-change notifications
apps.enabledbooleantrueMaster switch for MCP Apps (interactive Fiori UIs from @UI.* annotations). Set false to disable the feature entirely.
apps.writebooleantrueWhen false, apps are read-only — no Create/Edit/Delete buttons (the write tools themselves are unaffected).
apps.ui5booleantrueWhen false, skip the SAPUI5 CDN bootstrap and always use the self-contained CSS table (use when the iframe can't reach ui5.sap.com).
read_bundle.enabledbooleanfalseCollapse per-entity query/get tools into one consolidated read tool per group. See Read bundling. Write/draft tools stay per-entity.
read_bundle.group_by"service" | "annotation""service"How read tools are grouped: one per CAP service, or by @mcp.wrap.group (falling back to service).
read_bundle.tool_suffixstring"read"Suffix for the consolidated tool name, e.g. MailService_read.

Session store

MCP is session-oriented: the client sends initialize, receives an Mcp-Session-Id, then sends every subsequent request with that header. Deployments with multiple app instances behind a round-robin load balancer need the session to be visible from every instance (initialize lands on instance A, a later tools/call lands on instance B → otherwise Invalid session ID).

The plugin persists sessions in a CAP entity by default. When a DB binding is configured, session_store.kind resolves to "db" automatically — no extra flag needed. The injected cap.mcp.Sessions entity is created by your app's normal cds deploy.

Requirements for the DB-backed store:

  • A database binding (cds.env.requires.db) — sqlite, HANA, Postgres, etc.
  • cds deploy (or your app's deploy step) is run so the injected cap.mcp.Sessions table is created. The entity is added programmatically on cds.on('loaded'); no .cds file changes needed.
  • MCP_ENABLE_JSON=true (the default). DB-backed sessions rely on JSON-response mode because SSE streams cannot be handed off between instances.

Behavior:

  • A fresh initialize inserts a row with the generated session ID.
  • Subsequent requests routed to an instance that hasn't seen the session rehydrate a transport locally (cheap; transport state is purely in-memory) and update last_access in the DB.
  • A global reaper on every instance deletes rows older than CDS_MCP_SESSION_TTL_MS (default 30 minutes).
  • DELETE /mcp removes the row so no instance can rehydrate a torn-down session.
Stateless mode (no DB, multi-instance safe)

When your MCP tools are pure CRUD/RPC and you don't need server-initiated notifications (notifications/tools/list_changed, subscriptions, progress updates, etc.), set session_store.kind = "stateless". The plugin then:

  • Configures the SDK transport with sessionIdGenerator: undefined — no Mcp-Session-Id is issued or expected.
  • Builds a fresh server+transport per POST, handles the request, and discards both.
  • Returns 400 on GET /mcp (SSE streams) and DELETE /mcp (nothing to close).

This matches the "tool-server without subscriptions" pattern: requests are independent, horizontal scaling is trivial, blue/green deployments and restarts carry no session risk. Stateless needs no DB binding, so it's a good choice when you run multiple instances without wanting to take on a DB dependency.

{
  "cds": {
    "mcp": {
      "session_store": { "kind": "stateless" }
    }
  }
}
Opting out: in-memory store

Set session_store.kind = "memory" to keep sessions in a per-process Map. This is appropriate for single-instance deployments, local development, or any topology with sticky routing. When no DB binding exists and the kind is unspecified, the plugin falls back to "memory" automatically.

{
  "cds": {
    "mcp": {
      "session_store": { "kind": "memory" }
    }
  }
}

Explicit kind: "db" without a DB binding is a configuration error and the plugin fails fast at startup. The same applies to kind: "stateless" with MCP_ENABLE_JSON=false, because SSE is incompatible with per-request transports.

Authentication

inherit (default)

Uses CAP's configured authentication — any of mocked, basic, jwt, xsuaa, or ias:

{
  "cds": {
    "mcp":      { "auth": "inherit" },
    "requires": { "auth": { "kind": "xsuaa" } }
  }
}

Flow for OAuth-backed deployments (XSUAA, IAS):

  1. Client connects to /mcp without a token.
  2. Backend returns 401 with WWW-Authenticate: Bearer resource_metadata=….
  3. Client fetches /.well-known/oauth-protected-resource, then the advertised oauth-authorization-server metadata.
  4. Client performs the OAuth authorization-code flow (DCR, authorize, token exchange). For IAS the plugin emulates DCR using the pre-bound clientid since IAS does not implement RFC 7591.
  5. Client re-issues the MCP request with Authorization: Bearer <token>.
none

Disables authentication. Use only in development:

{ "cds": { "mcp": { "auth": "none" } } }
Behind an approuter

See docs/approuter-integration.md for the full deployment recipe, including managed approuter route declarations, XSUAA + IAS coexistence, and multi-tenancy notes. The approuter-side architecture is covered in docs/approuter-architecture.md.

Development and testing

  • npm test — full Jest suite.
  • npm run test:unit / npm run test:integration — scoped runs.
  • npm run test:coverage — coverage report.
  • npm run mock — start the demo CAP app in test/demo/.
  • npm run inspect — launch the official MCP Inspector and connect it to http://localhost:4004/mcp.

The bruno/ directory contains a Bruno collection with HTTP requests for the MCP endpoint for manual exploration.

Enable verbose logs:

{ "cds": { "log": { "levels": { "mcp": "debug" } } } }

Further reading: docs/entity-tools.md.

Troubleshooting

SymptomLikely cause
cds serve starts but /mcp 404sPort conflict on 4004, or the plugin was not picked up — confirm cap-mcp-plugin is in dependencies.
401 on every MCP call with auth: "inherit"Upstream CAP auth is misconfigured or missing credentials. Check cds.requires.auth.
MCP client rejects auth server as "does not support dynamic client registration" (IAS)oauth.proxy is "disabled" — the client is being pointed straight at IAS, which does not support DCR. Set oauth.proxy: "enabled" so the plugin emulates DCR.
Annotations ignoredVerify spelling and casing (resource, tool, prompts) and that the annotated service is loaded.
Dynamic query parameters must all be suppliedKnown @modelcontextprotocol/sdk RFC template-string limitation; provide every declared parameter.

Limitations

  • Dynamic resource queries must supply all declared query parameters (SDK limitation).
  • Elicitation is supported for direct tools only, not entity wrappers.
  • Each MCP client opens its own session; monitor memory when running many concurrent clients.
  • MCP Apps need a host that supports the MCP Apps extension to render the UI; the list table's full SAPUI5 rendering also requires the iframe to load ui5.sap.com (otherwise it falls back to the CSS table). The object-page detail view is rendered with self-contained CSS (not SAPUI5).

Contributing

Issues and pull requests are welcome at sleibach/cap-mcp-plugin.

License

Apache-2.0. See LICENSE.md.

Apache-2.0, read
Declared alternatives
  1. @cap-js/mcpExposes CAP services as MCP servers for AI agents
  2. @gavdi/cap-mcpGenerates an MCP server from annotated CDS entities and actions
Serve your application over MCP
  1. abap-ai/mcpMCP server SDK written in ABAPfrom ABAP
  2. abap-ai/mcp2Stateless ABAP MCP server SDK for the 2026-07-28 protocol draftfrom ABAP
  3. abap-agent-runtimeABAP-native MCP endpoint that drives opted-in abap2UI5 appsfrom ABAP
  4. API ManagementAPI proxies with security and traffic policies and Developer Hubfrom BTP/BAIP
  5. com.sap.cds:cds-adapter-mcpMCP adapter turning a CAP Java service into an MCP serverfrom CAP
  6. @cap-js/mcpExposes CAP services as MCP servers for AI agentsfrom CAP
  7. @gavdi/cap-mcpGenerates an MCP server from annotated CDS entities and actionsfrom CAP
  8. btp-cf-mcpMCP server for SAP BTP and Cloud Foundry acting as the logged-in userfrom BTP/BAIP
  9. MarkWuRY168/SAP_MCPMCP server publishing SAP functions as tools from config tablesfrom ABAP
  10. @neoimpulse/cap-js-mcpMCP server inside a CAP application with model and query toolsfrom CAP
  11. @odatano/core-mcpMCP server exposing the ODATANO Cardano-to-OData bridge as toolsfrom CAP
  12. @odatano/nightgate-mcpMCP server exposing the NIGHTGATE Midnight attestation layerfrom CAP
  13. @shahid.la/cds-db-nlquery-mcpMCP server answering plain-English questions against a CDS schemafrom CAP
  14. Skybuffer AI MCP serverABAP add-on serving business data and transactions as MCP toolsfrom ABAP

Details

Connected knowledge — wider context3

Source connections explain where this sits. Implementation claims remain in their exact task assessment.

Expose an application service to an AI agent · Expose an application service to an AI agent

Editorially accepted assessment · assessed . No Atlas runtime testing.

Evidence changed · needs review · evidence captured 2026-10-12, 2026-10-26

Supporting evidence changed; this accepted claim needs review.

Evidence status not tracked

Evidence observations do not cover this accepted claim; it is retained as dated history.

Related knowledge

Model Context Protocol Adapter | capire

@cap-js/mcp exposes an annotated custom service for model discovery, querying and invocation of unbound actions and functions.

Why included: Dated assessment history; supporting evidence needs review.

Evidence status not tracked

Evidence observations do not cover this accepted claim; it is retained as dated history.

CAP MCP Plugin — gavdilabs/cap-mcp-plugin README

@gavdi/cap-mcp exposes annotated entities as resources and functions/actions as tools.

Why included: Dated assessment history; supporting evidence needs review.

Evidence status not tracked

Evidence observations do not cover this accepted claim; it is retained as dated history.

SanoberRehman/cap-mcp-bridge — README

cap-mcp-bridge queries a custom application OData V4 endpoint and invokes its exposed operations.

Why included: Dated assessment history; supporting evidence needs review.

Evidence status not tracked

Evidence observations do not cover this accepted claim; it is retained as dated history.

Add MCP capabilities to a CAP service

A fifteen-minute walkthrough of turning a plain CAP service into an MCP server: annotate the service with @mcp, install @cap-js/mcp, and it is served alongside OData at /mcp/<path>. The part worth reading it for is what happens next — cds watch writes the endpoint into the local agent's own configuration file, so OpenCode or Claude Code can call the service without anyone editing JSON by hand. It is built on the tiny-sample facet, so there is nothing to prepare, and it shows the protocol traffic rather than only the result. Written while the adapter was in beta, and it says so.

Why included: CAP Node.js setup, @mcp service exposure, local client discovery and querying through the official adapter.

Examine the details of the Model Context Protocol on startup

What the MCP adapter actually does when a CAP server boots, watched rather than described — the companion to the tutorial that switches it on.

Why included: CAP Node.js startup, tool discovery and query flow; the tutorial sample contains no actions or functions.

Model Context Protocol Adapter — CAP guide

Documents @cap-js/mcp and com.sap.cds:cds-adapter-mcp, service annotations, generated describe/query/call tools and local client setup. The guide records Java doc-comment configuration, unbound-action-based data changes, incomplete XSUAA PKCE support and the adapter’s governance boundaries.

Why included: CAP Node.js and Java adapter installation, service exposure, model context, tools and documented limitations.

CAP OData V4 Service Development

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

JSON-RPC Protocol

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

MCP (Model Context Protocol) Adapter for CAP

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

Connecting with AI Coding Agents

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

CAP Annotations

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

CAP Local Development Loop

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

MCP Servers

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

CAP for Node.js

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

MCP Inspector TUI Client

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

MCP Tools and Autonomous Multi-Step Workflows

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: Native relationship in the retained Developers snapshot; no runtime claim is inferred. · SAP Developers

Why this assessment is relevant
  1. Expose an application service to an AI agent → Expose an application service to an AI agent
Relationships and evidence (36)
  • @cap-js/mcp → provides → Serve your application over MCP

    Exposes an @mcp-annotated CAP Node.js application service through generated describe, query and unbound-action/function tools. The query and call tools invoke the exposed service without direct CRUD tools; data changes require application-defined unbound actions. The describe tool returns model descriptions, and the adapter sends generic and custom server instructions to clients. Whole-service opt-in with @mcp can be narrowed through a dedicated service with selected projections and actions.

    Basis: atlas-record

    Model Context Protocol Adapter | capire · checked 2026-10-12Simply add the @mcp annotation to a service definition to expose it via MCP.

    Model Context Protocol Adapter | capire · checked 2026-10-12This tool is used to read data from the service.

    Model Context Protocol Adapter | capire · checked 2026-10-12This tool is used to call unbound actions or functions.

    Model Context Protocol Adapter | capire · checked 2026-10-12while any data changes need to be implemented via unbound actions for now.

    Model Context Protocol Adapter | capire · checked 2026-10-12The CAP MCP adapter must not be used as a gateway or proxy for SAP Application APIs.

    Model Context Protocol Adapter | capire · checked 2026-10-12The adapter is not an SAP-endorsed architecture, data service, or service-specific pathway under section 2.2.2 of the SAP API Policy and is not an endorsed mechanism for exposing, proxying, or providing agentic access to SAP Application APIs.

    Model Context Protocol Adapter | capire · checked 2026-10-12The CAP MCP adapter is intended only for exposing custom CAP application services.

    Model Context Protocol Adapter | capire · checked 2026-10-12This information is included in the output of the describe tool

    Model Context Protocol Adapter | capire · checked 2026-10-12The MCP Adapter automatically sends MCP instructions to MCP clients to help models understand how to interact with your services effectively.

    Model Context Protocol Adapter | capire · checked 2026-10-12Use the @mcp.instructions annotation on service level, entity level, or action level to specify such custom instructions.

    Model Context Protocol Adapter | capire · checked 2026-10-12Instead of annotating an existing service with @mcp and exposing all its entities and actions, simply create a dedicated service specifically for MCP.

    Model Context Protocol Adapter | capire · checked 2026-10-12Within your project root run this to add the @cap-js/mcp plugin for Node.js projects

  • @gavdi/cap-mcp → provides → Serve your application over MCP

    Generates MCP resources and operation tools from annotated CAP Node.js services, with configured entity wrappers for query/get and optional create/update. The README requires Node.js 18+, CAP 10+ and Express 5+; resource reads and direct tools use service transactions in the pinned implementation. Output omission does not establish a field-access restriction. Annotations and wrapper modes select the exposed entities and operations. Entity resources, reusable prompt templates and @mcp.hint schema descriptions supply context; enable_model_description controls the model-description tool, and instructions configures server instructions. @mcp.omit filters output only: omitted fields remain queryable and can be supplied as write inputs.

    Basis: atlas-record

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12- **Node.js**: Version 18 or higher

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12- **SAP CAP**: Version 10 or higher

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12- **Express**: Version 5 or higher

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Omitted fields remain queryable in the CAP service - only MCP responses are filtered

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Annotate your CAP services with `@mcp` annotations:

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Convert CAP functions and actions into executable MCP tools

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Expose CAP entities as tools (`query`, `get`, and optionally `create`, `update`) for LLM tool use while keeping resources intact

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Define reusable prompt templates for AI interactions

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Hints are accessible in both resource queries and tool executions

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Expose CAP entities as MCP resources with OData v4 query capabilities

    gavdilabs/cap-mcp-plugin — resources.ts at 1f3a97e1c0733d97c0cabea53d6d31767508daed · checked 2026-10-12const response = await service.tx({ user: accessRights }).run(query);

    gavdilabs/cap-mcp-plugin — tools.ts at 1f3a97e1c0733d97c0cabea53d6d31767508daed · checked 2026-10-12const response = await service.tx({ user: accessRights }).send({

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Scans your CAP service definitions for `@mcp` annotations

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12When `wrap_entities_to_actions` is enabled (globally or via `@mcp.wrap.tools: true`)

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Omitted fields are **only excluded from outputs** - they can still be provided as inputs for create/update operations

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Determines whether the MCP server should include the model description tool

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12MCP server instructions for agents

  • cap-mcp-plugin → provides → Serve your application over MCP

    Generates MCP entity resources and bound/unbound operation tools for CAP Node.js, with configured CRUD wrappers, a draft lifecycle and optional Fiori-derived MCP Apps. The README requires Node.js 18+, CAP 9+ and Express 4+. Resource/tool annotations and wrapper modes select the exposed surface; resource reads and direct operation tools call CAP service transactions in the pinned implementation. Entity resources, prompt templates and @mcp.hint schemas supply context, instructions configures server instructions, and MCP Apps require @mcp.wrap.tools with Fiori annotations. @mcp.omit filters output only, and disabling app write buttons leaves tools callable.

    Basis: atlas-record

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12- Node.js 18+

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12- `@sap/cds` 9+

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12- `express` 4+

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12`@mcp.omit` filters MCP output only.

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12no Create/Edit/Delete buttons (the write tools themselves are unaffected)

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12Annotated entities become MCP resources, functions and actions become tools, and services can expose reusable prompt templates.

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12CDS operations annotated with `@mcp.tool: true` become MCP tools.

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12Both **unbound** (service-level) and **bound** (entity-level) operations are supported

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12- `delete` — remove a row by key(s).

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12- `draft-activate` — publish the pending draft to the active row.

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12**Short-circuits active-row `create`, `update`, and `delete`** with a `DRAFT_REQUIRED` error

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12entities annotated with `@odata.draft.bypass` (or the whole service with `cds.env.fiori.bypass_draft: true`) continue to accept direct active-row `create`/`update`/`delete`

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12Declare reusable prompt templates.

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12Enrich schemas for AI agents via `@mcp.hint` on elements and parameters.

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12When an entity has `@mcp.wrap.tools` **and** Fiori UI annotations, the plugin registers two `ui://` HTML resources

    sleibach/cap-mcp-plugin — resources.js at 5359398d0662f452d31529509c67634f8eb5406d · checked 2026-10-12const response = await service.tx({ user: accessRights }).run(query);

    sleibach/cap-mcp-plugin — tools.js at 5359398d0662f452d31529509c67634f8eb5406d · checked 2026-10-12service.tx({ user: accessRights }).send({

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12modes: ['query', 'get', 'create', 'update']

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12Omitted fields can still be supplied as inputs on create / update operations and remain queryable in the underlying CAP service.

    cap-mcp-plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12Server-level instructions surfaced to agents

  • Model Context Protocol Adapter — CAP guide → explains → Serve your application over MCP

    CAP Node.js and Java adapter installation, service exposure, model context, tools and documented limitations.

    Basis: atlas-record

  • Model Context Protocol Adapter — CAP guide → explains → @cap-js/mcp

    Node.js installation, service annotations, querying and unbound action/function invocation.

    Basis: atlas-record

  • Add MCP capabilities to a CAP service → explains → Serve your application over MCP

    CAP Node.js setup, @mcp service exposure, local client discovery and querying through the official adapter.

    Basis: atlas-record

  • Add MCP capabilities to a CAP service → explains → @cap-js/mcp

    Canonical Atlas relevance assertion.

    Basis: atlas-record

  • Examine the details of the Model Context Protocol on startup → explains → Serve your application over MCP

    CAP Node.js startup, tool discovery and query flow; the tutorial sample contains no actions or functions.

    Basis: atlas-record

  • Examine the details of the Model Context Protocol on startup → explains → @cap-js/mcp

    Canonical Atlas relevance assertion.

    Basis: atlas-record

  • Add MCP capabilities to a CAP service → teaches → CAP OData V4 Service Development

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Add MCP capabilities to a CAP service → teaches → JSON-RPC Protocol

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Add MCP capabilities to a CAP service → teaches → MCP (Model Context Protocol) Adapter for CAP

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Add MCP capabilities to a CAP service → teaches → Connecting with AI Coding Agents

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Add MCP capabilities to a CAP service → teaches → CAP Annotations

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Add MCP capabilities to a CAP service → teaches → CAP Local Development Loop

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Add MCP capabilities to a CAP service → teaches → MCP Servers

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Examine the details of the Model Context Protocol on startup → teaches → JSON-RPC Protocol

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Examine the details of the Model Context Protocol on startup → teaches → CAP for Node.js

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Examine the details of the Model Context Protocol on startup → teaches → MCP (Model Context Protocol) Adapter for CAP

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Examine the details of the Model Context Protocol on startup → teaches → MCP Inspector TUI Client

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Examine the details of the Model Context Protocol on startup → teaches → MCP Servers

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Examine the details of the Model Context Protocol on startup → teaches → MCP Tools and Autonomous Multi-Step Workflows

    Native relationship in the retained Developers snapshot; no runtime claim is inferred.

    Basis: source-graph

    SAP Developers graph snapshot · checked 2026-10-05T00:55:43.720Z

  • Expose an application service to an AI agent → associatedWith → Serve your application over MCP

    Primary capability recorded by the accepted task.

    Basis: atlas-assessment

  • MCP (Model Context Protocol) Adapter for CAP → addressesPartOf → Expose an application service to an AI agent

    The retained source graph says the CAP tutorial teaches this adapter subject. The tutorial exposes a CAP Node.js service through @cap-js/mcp, which addresses the official-adapter part of this assessment.

    Basis: atlas-mapping

    Mapping: partial · accepted · Reviewed canonical mapping · checked 2026-10-12

    Evidence matches captured sources · evidence captured 2026-10-12

    Add MCP capabilities to a CAP service · checked 2026-10-12the implementation of MCP capabilities is provided by the MCP adapter plugin @cap-js/mcp

    Add MCP capabilities to a CAP service · checked 2026-10-12You will need a development environment for CAP Node.js.

  • MCP Servers → contextualizes → Serve your application over MCP

    The retained source graph says the CAP tutorial teaches MCP Servers. In CAP Node.js that tutorial supplies service-exposure context for Serve your application over MCP; this does not classify every tutorial under the broad source subject.

    Basis: atlas-mapping

    Mapping: about · accepted · Reviewed canonical mapping · checked 2026-10-12

    Evidence matches captured sources · evidence captured 2026-10-12

    Add MCP capabilities to a CAP service · checked 2026-10-12the implementation of MCP capabilities is provided by the MCP adapter plugin @cap-js/mcp

    Add MCP capabilities to a CAP service · checked 2026-10-12You will need a development environment for CAP Node.js.

  • Expose an application service to an AI agent → assesses → Expose an application service to an AI agent

    One shared outcome, one scoped assessment.

    Basis: atlas-assessment

  • @cap-js/mcp → previouslyContributedTo → Expose an application service to an AI agent

    Last accepted assessment (2026-10-12): @cap-js/mcp exposes an annotated custom service for model discovery, querying and invocation of unbound actions and functions.

    Basis: atlas-assessment · dated relationship; evidence needs review

    Evidence status not tracked

    Evidence observations do not cover this accepted claim; it is retained as dated history.

    Model Context Protocol Adapter | capire · checked 2026-10-12Simply add the @mcp annotation to a service definition to expose it via MCP.

    Model Context Protocol Adapter | capire · checked 2026-10-12This tool is used to read data from the service.

    Model Context Protocol Adapter | capire · checked 2026-10-12This tool is used to call unbound actions or functions.

    Model Context Protocol Adapter | capire · checked 2026-10-12there is no automatic rate limiting, no specific audit logging of agent actions, no approval workflows for sensitive operations, and no policy enforcement layer.

    Model Context Protocol Adapter | capire · checked 2026-10-12out-of-the-box support for authorization with XSUAA, with PKCE, but it is not fully implemented yet.

    Model Context Protocol Adapter | capire · checked 2026-10-12This information is included in the output of the describe tool

    Model Context Protocol Adapter | capire · checked 2026-10-12npm add @cap-js/mcp

    Model Context Protocol Adapter | capire · checked 2026-10-12For any deployment ensure you use infrastructure and practices that mitigate prompt injection risks and connect only to trusted MCP agents (e.g., Joule).

    Model Context Protocol Adapter | capire · checked 2026-10-12Tools are meant to be used by LLMs and AI agents and do not constitute a stable API.

    Model Context Protocol Adapter | capire · checked 2026-10-12The CAP MCP adapter must not be used as a gateway or proxy for SAP Application APIs.

    Model Context Protocol Adapter | capire · checked 2026-10-12Instead of annotating an existing service with @mcp and exposing all its entities and actions, simply create a dedicated service specifically for MCP.

  • @gavdi/cap-mcp → previouslyContributedTo → Expose an application service to an AI agent

    Last accepted assessment (2026-10-12): @gavdi/cap-mcp exposes annotated entities as resources and functions/actions as tools.

    Basis: atlas-assessment · dated relationship; evidence needs review

    Evidence status not tracked

    Evidence observations do not cover this accepted claim; it is retained as dated history.

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Expose CAP entities as MCP resources with OData v4 query capabilities

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Convert CAP functions and actions into executable MCP tools

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12**Node.js**: Version 18 or higher

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12**SAP CAP**: Version 10 or higher

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12**Express**: Version 5 or higher

  • cap-mcp-bridge → previouslyContributedTo → Expose an application service to an AI agent

    Last accepted assessment (2026-10-12): cap-mcp-bridge queries a custom application OData V4 endpoint and invokes its exposed operations.

    Basis: atlas-assessment · dated relationship; evidence needs review

    Evidence status not tracked

    Evidence observations do not cover this accepted claim; it is retained as dated history.

    SanoberRehman/cap-mcp-bridge — README · checked 2026-10-12| `query_entity` | The workhorse: filter, select, expand, orderBy, paging, `$count` |

    SanoberRehman/cap-mcp-bridge — README · checked 2026-10-12| `invoke_action` | Call an action. **Write mode only** |

    SanoberRehman/cap-mcp-bridge — README · checked 2026-10-12`cap-mcp-bridge` runs **outside** the service and consumes `$metadata` over HTTP.

    SanoberRehman/cap-mcp-bridge — README · checked 2026-10-12That starts an MCP server on stdio.

  • cap-mcp-plugin → previouslyContributedTo → Expose an application service to an AI agent

    Last accepted assessment (2026-10-12): cap-mcp-plugin derives MCP resources and tools from annotated CDS entities and operations.

    Basis: atlas-assessment · dated relationship; evidence needs review

    Evidence status not tracked

    Evidence observations do not cover this accepted claim; it is retained as dated history.

    CAP MCP Plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12Annotated entities become MCP resources, functions and actions become tools, and services can expose reusable prompt templates.

    CAP MCP Plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12Node.js 18+

    CAP MCP Plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12`@sap/cds` 9+

    CAP MCP Plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12`express` 4+

    CAP MCP Plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12There is **no npm registry package yet**. Install straight from GitHub:

    CAP MCP Plugin — sleibach/cap-mcp-plugin README · checked 2026-10-12- Node.js 18+ - `@sap/cds` 9+ - `express` 4+

  • Expose an application service to an AI agent → reading → Model Context Protocol Adapter | capire

    Curated supporting reading for this assessment.

    Basis: atlas-assessment · dated relationship; evidence needs review

    Evidence status not tracked

    Evidence observations do not cover this accepted claim; it is retained as dated history.

    Model Context Protocol Adapter | capire · checked 2026-10-12Simply add the @mcp annotation to a service definition to expose it via MCP.

    Model Context Protocol Adapter | capire · checked 2026-10-12This tool is used to read data from the service.

    Model Context Protocol Adapter | capire · checked 2026-10-12This tool is used to call unbound actions or functions.

    Model Context Protocol Adapter | capire · checked 2026-10-12there is no automatic rate limiting, no specific audit logging of agent actions, no approval workflows for sensitive operations, and no policy enforcement layer.

    Model Context Protocol Adapter | capire · checked 2026-10-12out-of-the-box support for authorization with XSUAA, with PKCE, but it is not fully implemented yet.

    Model Context Protocol Adapter | capire · checked 2026-10-12This information is included in the output of the describe tool

    Model Context Protocol Adapter | capire · checked 2026-10-12npm add @cap-js/mcp

    Model Context Protocol Adapter | capire · checked 2026-10-12For any deployment ensure you use infrastructure and practices that mitigate prompt injection risks and connect only to trusted MCP agents (e.g., Joule).

    Model Context Protocol Adapter | capire · checked 2026-10-12Tools are meant to be used by LLMs and AI agents and do not constitute a stable API.

    Model Context Protocol Adapter | capire · checked 2026-10-12The CAP MCP adapter must not be used as a gateway or proxy for SAP Application APIs.

    Model Context Protocol Adapter | capire · checked 2026-10-12Instead of annotating an existing service with @mcp and exposing all its entities and actions, simply create a dedicated service specifically for MCP.

  • Expose an application service to an AI agent → reading → CAP MCP Plugin — gavdilabs/cap-mcp-plugin README

    Curated supporting reading for this assessment.

    Basis: atlas-assessment · dated relationship; evidence needs review

    Evidence status not tracked

    Evidence observations do not cover this accepted claim; it is retained as dated history.

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Expose CAP entities as MCP resources with OData v4 query capabilities

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12Convert CAP functions and actions into executable MCP tools

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12**Node.js**: Version 18 or higher

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12**SAP CAP**: Version 10 or higher

    CAP MCP Plugin — gavdilabs/cap-mcp-plugin README · checked 2026-10-12**Express**: Version 5 or higher

  • Expose an application service to an AI agent → reading → SanoberRehman/cap-mcp-bridge — README

    Curated supporting reading for this assessment.

    Basis: atlas-assessment · dated relationship; evidence needs review

    Evidence status not tracked

    Evidence observations do not cover this accepted claim; it is retained as dated history.

    SanoberRehman/cap-mcp-bridge — README · checked 2026-10-12| `query_entity` | The workhorse: filter, select, expand, orderBy, paging, `$count` |

    SanoberRehman/cap-mcp-bridge — README · checked 2026-10-12| `invoke_action` | Call an action. **Write mode only** |

    SanoberRehman/cap-mcp-bridge — README · checked 2026-10-12`cap-mcp-bridge` runs **outside** the service and consumes `$metadata` over HTTP.

    SanoberRehman/cap-mcp-bridge — README · checked 2026-10-12That starts an MCP server on stdio.

  • Expose an application service to an AI agent → reading → Add MCP capabilities to a CAP service

    Curated supporting reading for this assessment.

    Basis: atlas-assessment

  • Expose an application service to an AI agent → reading → Examine the details of the Model Context Protocol on startup

    Curated supporting reading for this assessment.

    Basis: atlas-assessment

  • Expose an application service to an AI agent → reading → Model Context Protocol Adapter — CAP guide

    Curated supporting reading for this assessment.

    Basis: atlas-assessment

Shared resource identities

sap-developers:t:cap-add-mcp-capabilities → content:sap-tutorial-add-mcp-capabilities-to-a-cap-service

Same resource across graphs; this does not establish implementation compatibility.

Evidence matches captured sources · evidence captured 2026-10-12

sap-developers:t:cap-examine-mcp-startup → content:sap-tutorial-cap-examine-mcp-startup

Same resource across graphs; this does not establish implementation compatibility.

Evidence matches captured sources · evidence captured 2026-10-12

Gaps, source snapshot and retrieval limits
  • The four contributions are separate alternatives; no combined design is asserted or executed by the Atlas.
  • Other providers on this capability page remain unassessed for the complete service-exposure outcome.
  • Transport, authentication, tenancy and production behavior have not been tested by the Atlas.
  • CAP Java and BTP have separate proposed assessments; draft lifecycle, prompts, resources and interactive UI have outcome-specific assessments.
  • Evidence observations do not cover this accepted claim; it is retained as dated history.
  • Supporting evidence changed; this accepted claim needs review.
  • Retrieval uses at most four typed steps within a bounded source index. Source relationships do not establish compatibility.

Developers snapshot checked 2026-10-05 · 33 indexed records from a 9,023-node source snapshot. This is a bounded retrieval view; absence is not evidence that no solution exists. Source relationships and proximity do not establish runtime compatibility.

Mapping version: connected-tasks-2026-10-06-v4+mcp-records-b256b58cfb844590. Task and mapping evidence remain separate from implementation evidence.

Access an external system through an application MCP service · CAP Node.js application bridge for custom external APIs outside SAP Application APIs

Editorially accepted assessment · assessed . No Atlas runtime testing.

Evidence changed · needs review · evidence captured 2026-10-12, 2026-10-15, 2026-10-26

Supporting evidence changed; this accepted claim needs review.

Evidence status not tracked

Evidence observations do not cover this accepted claim; it is retained as dated history.

Related knowledge

CAP Framework (Cloud Application Programming Model)

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: The CAP framework subject is broader than the Node.js runtime. This is a route to context, not package identity or compatibility. · SAP Developers

Why this assessment is relevant
  1. Access an external system through an application MCP service → CAP Node.js application bridge for custom external APIs outside SAP Application APIs
Relationships and evidence (17)
Gaps, source snapshot and retrieval limits
  • The application integration and MCP contributions are assessed separately; no captured source shows these complete generic bridge paths working against a chosen external system.
  • The selected target API, client and backend permissions, tenant mapping and remote error behavior need a project-specific assessment.
  • A compatible component does not establish an endorsed architecture or permission to expose an SAP Application API.
  • Evidence observations do not cover this accepted claim; it is retained as dated history.
  • Supporting evidence changed; this accepted claim needs review.
  • Retrieval uses at most four typed steps within a bounded source index. Source relationships do not establish compatibility.

Developers snapshot checked 2026-10-05 · 33 indexed records from a 9,023-node source snapshot. This is a bounded retrieval view; absence is not evidence that no solution exists. Source relationships and proximity do not establish runtime compatibility.

Mapping version: connected-tasks-2026-10-06-v4+mcp-records-b256b58cfb844590. Task and mapping evidence remain separate from implementation evidence.

Access an external system through an application MCP service · CAP Node.js application bridge for SAP Application APIs

Editorially accepted assessment · assessed . No Atlas runtime testing.

Evidence changed · needs review · evidence captured 2026-10-12, 2026-10-15, 2026-10-26

Supporting evidence changed; this accepted claim needs review.

Evidence status not tracked

Evidence observations do not cover this accepted claim; it is retained as dated history.

Related knowledge

CAP Framework (Cloud Application Programming Model)

Source subject or learning resource; applicability is established separately by the scoped assessment.

Why included: The CAP framework subject is broader than the Node.js runtime. This is a route to context, not package identity or compatibility. · SAP Developers

Why this assessment is relevant
  1. Access an external system through an application MCP service → CAP Node.js application bridge for SAP Application APIs
Relationships and evidence (17)
Gaps, source snapshot and retrieval limits
  • The application integration and MCP contributions are assessed separately; no captured source shows these complete generic bridge paths working against a chosen external system.
  • The selected target API, client and backend permissions, tenant mapping and remote error behavior need a project-specific assessment.
  • A compatible component does not establish an endorsed architecture or permission to expose an SAP Application API.
  • The official CAP MCP adapter is explicitly unsupported for this target scope. The community MCP implementations remain unknown for the complete SAP Application API bridge; their general service exposure does not establish that result.
  • Evidence observations do not cover this accepted claim; it is retained as dated history.
  • Supporting evidence changed; this accepted claim needs review.
  • Retrieval uses at most four typed steps within a bounded source index. Source relationships do not establish compatibility.

Developers snapshot checked 2026-10-05 · 33 indexed records from a 9,023-node source snapshot. This is a bounded retrieval view; absence is not evidence that no solution exists. Source relationships and proximity do not establish runtime compatibility.

Mapping version: connected-tasks-2026-10-06-v4+mcp-records-b256b58cfb844590. Task and mapping evidence remain separate from implementation evidence.

Sources3
GitHub APIdiscovered here, sleibachchecked
github.com/sleibach/cap-mcp-plugintree, pushes, contributors, CIchecked
README.mdquoted, and what the entry declareschecked

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
runtimesnode
discovered viaGitHub API · sleibach
first seen in the atlas
ecosystem and domaincap, ai-and-agents
History in the atlas7
  1. [{"key":"mcp_exposure_source","value":"Annotated CDS entities and bound/unbound operations in a CAP application"},{"key":"mcp_operations","value":"Queries, bound/unbound operations, configured CRUD and draft lifecycle; draft roots reject direct active-row writes unless bypass is enabled"},{"key":"mcp_context","value":"Entity resources, prompt templates, @mcp.hint schemas and optional MCP Apps from Fiori annotations"},{"key":"mcp_execution_path","value":"Resource reads and direct operation tools call CAP service transactions (pinned implementation)"},{"key":"mcp_exposure_control","value":"Resource/tool annotations and wrapper modes select the surface; @mcp.omit filters output only; disabling app write buttons leaves tools callable"}]
  2. CAP service contract
  3. MCP resources; MCP prompts; Schema hints; Interactive UI resources; Server instructions
  4. CAP service calls
  5. Entity/operation annotations; Wrapper configuration; Output filtering
  6. Generates MCP entity resources and bound/unbound operation tools for CAP [Node.js](external:nodejs), with configured CRUD wrappers, a draft lifecycle and optional Fiori-derived MCP Apps. The README requires [Node.js](external:nodejs) 18+, CAP 9+ and Express 4+. Resource/tool annotations and wrapper modes select the exposed surface; resource reads and direct operation tools call CAP service transactions in the pinned implementation. Entity resources, prompt templates and @mcp.hint schemas supply context, instructions configures server instructions, and MCP Apps require @mcp.wrap.tools with Fiori annotations. @mcp.omit filters output only, and disabling app write buttons leaves tools callable.
  7. First seen.
For your agent
Ref
artifact:sleibach-cap-mcp-plugin
JSON
/artifacts/sleibach-cap-mcp-plugin.json
MCP
Connecting an agent