CAP MCP插件-轻松实现AI
该实现基于Anthropic提出的模型上下文协议(MCP)。 有关MCP的更多信息,请查看他们的 官方文件。
CAP-MCP插件
一个CAP(云应用程序编程)插件,使用简单的注释从CAP服务自动生成模型上下文协议(MCP)服务器。 用最少的配置将CAP OData服务转换为AI可访问的资源、工具和提示。
🚀 MCP在CAP应用中的强大功能
模型上下文协议弥合了企业数据和人工智能代理之间的差距。 通过将MCP与CAP应用程序集成,您可以解锁:
- AI原生数据访问:您的CAP服务可供Claude等启用MCP的AI代理直接访问,从而能够对您的业务数据进行自然语言查询
- 企业集成:将AI工具无缝连接到您的SAP系统、数据库和业务逻辑
- 智能自动化:通过组合多个CAP服务调用,使AI代理能够执行复杂的业务操作
- 开发人员生产力:允许AI助手帮助开发人员理解、查询和使用您的CAP数据模型
- 商业智能:将您的结构化业务数据转换为AI可查询的资源,以进行洞察和分析
🚀 快速设置
想阅读完整的文档吗? 在这里找到它
先决条件
- Node.js:版本18或更高版本
- 树液盖:版本9或更高版本
- 快速:版本4或更高版本
- TypeScript:可选,但推荐
步骤1:安装插件
npm install @gavdi/cap-mcp该插件遵循CAP的标准插件架构,安装后将自动与您的CAP应用程序集成。
步骤2:配置CAP应用程序
将MCP配置添加到您的 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"
}
}
}步骤3:添加MCP注释
为您的CAP服务添加注释 @mcp 注释:
// srv/catalog-service.cds
service CatalogService {
@mcp: {
name: 'books',
description: 'Book catalog with search and filtering',
resource: ['filter', 'orderby', 'select', 'top', 'skip', 'expand']
}
entity Books as projection on my.Books;
// Optionally expose Books as tools for LLMs (query/get enabled by default config)
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;
}备注:The@mcp.wrap.hint注释提供操作级别指导,同时@mcp.hint在单个元素上提供字段级描述。两者共同努力,为人工智能代理提供全面的背景。
步骤4:启动您的应用程序
cds serveMCP服务器将在以下地点提供:
- MCP端点:
http://localhost:4004/mcp - 健康检查:
http://localhost:4004/mcp/health
步骤5:使用MCP检查员进行测试
npx @modelcontextprotocol/inspector连接到 http://localhost:4004/mcp 探索您生成的MCP资源、工具和提示。
🎯 特性
此插件将带注释的CAP服务转换为功能齐全的MCP服务器,可供任何兼容MCP的AI客户端使用。
- 📊 资源:将CAP实体作为具有OData v4查询功能的MCP资源公开
- 🔧 工具:将CAP功能和操作转换为可执行的MCP工具
- 🧩 实体包装器(可选):将CAP实体作为工具公开(
query,get,并且可选create,update)用于LLM工具使用,同时保持资源完整 - 🔗 深度插入:使用以下命令在单个操作中创建父实体和子实体
@mcp.deepInsert注释 - 💡 提示:为AI交互定义可重用的提示模板
- ⚡ 引出:在执行工具之前请求用户确认或输入参数
- 🔄 自动生成:根据注释自动创建MCP服务器端点
- ⚙️ 灵活的配置:支持自定义参数集和描述
🧪 测试和检验员
- 运行测试:
npm test - 启动演示应用程序:
npm run mock - 检查员:
npx @modelcontextprotocol/inspector
布鲁诺收藏
这 bruno/ 文件夹包含MCP端点的HTTP请求(便于使用Bruno或任何HTTP客户端进行本地手动测试)。您可以添加以下呼叫 tools/list 和 tools/call 练习新的包装工具。
📝 用法
资源注释
将CAP实体转换为AI可查询资源:
service CatalogService {
@readonly
@mcp: {
name : 'books',
description: 'Book data list',
resource : [
'filter',
'orderby',
'select',
'skip',
'top',
'expand'
]
}
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;
// Or maybe you just want it as a static top 100 list of data?
@mcp: {
name : 'genres',
description: 'Book genre list',
resource : []
}
entity Genres as projection on my.Genres;
}生成的MCP资源能力:
- OData v4查询支持:
$filter,$orderby,$top,$skip,$select,$expand - 自然语言查询:“查找库存超过20本的Stephen King书籍”
- 动态过滤:使用OData语法的复杂筛选器表达式
- 灵活选择:选择特定字段和排序顺序
包装工具
当 wrap_entities_to_actions 已启用(全局或通过 @mcp.wrap.tools: true),您将看到名为的工具:
CatalogService_Books_queryCatalogService_Books_getCatalogService_Books_create(如果启用)CatalogService_Books_update(如果启用)
每个工具都包含一个带有字段和OData注释的描述,以指导模型。你可以添加 @mcp.wrap.hint 每个实体,以丰富LLM的描述。
例子:
// Wrap Books entity as tools for query/get/create/update (demo)
annotate CatalogService.Books with @mcp.wrap: {
tools: true,
modes: [
'query',
'get',
'create',
'update'
],
hint : 'Use for read and write demo operations'
};有关这些工具中的字段级描述,请参见 带有@mcp.hint的元素提示.
忽略敏感字段
通过使用从MCP响应中排除特定字段来保护敏感数据 @mcp.omit 注释:
namespace my.bookshop;
entity Books {
key ID : Integer;
title : String;
stock : Integer;
author : Association to Authors;
secretMessage : String @mcp.omit; // Hidden from all MCP responses
}
entity Users {
key ID : Integer;
username : String;
email : String;
darkestSecret : String @mcp.omit; // Never exposed to MCP clients
ssn : String @mcp.omit; // Protected sensitive data
lastLogin : DateTime;
}工作原理:
- 标记为的字段
@mcp.omit从所有MCP响应中自动过滤 - 适用于:
- 资源:字段不会出现在资源读取操作中 - 包装实体:省略适用于所有实体包装器操作
常见用例:
- 安全:隐藏对功能或业务运营敏感的信息
- 隐私:保护个人标识符
- 内部数据:排除内部注释、审核日志或仅系统字段
- 合规:通过隐藏敏感个人数据确保GDPR/CCPA合规性
重要提示:
- 省略的字段为 仅从输出中排除 -它们仍然可以作为创建/更新操作的输入提供
- 该注释与CAP标准注释一起工作
@Core.Computed用于综合现场控制 - 省略的字段在CAP服务中仍可查询,仅过滤MCP响应
带有多个注释的示例:
entity Products {
key ID : Integer;
name : String;
price : Decimal;
costPrice : Decimal @mcp.omit; // Hide internal pricing
createdAt : DateTime @Core.Computed; // Auto-generated, not writable
updatedAt : DateTime @Core.Computed; // Auto-generated, not writable
secretNote : String @mcp.omit; // Hide from MCP
}工具注释
将CAP功能和操作转换为可执行的AI工具:
// Service-level function
@mcp: {
name : 'get-author',
description: 'Gets the desired author',
tool : true
}
function getAuthor(input: String) returns String;
// Entity-level action
extend projection Books with actions {
@mcp: {
name : 'get-stock',
description: 'Retrieves stock from a given book',
tool : true
}
function getStock() returns Integer;
}工具启发
使用工具执行前请求用户确认或输入 elicit 财产:
// Request user confirmation before execution
@mcp: {
name : 'book-recommendation',
description: 'Get a random book recommendation',
tool : true,
elicit : ['confirm']
}
function getBookRecommendation() returns String;
// Request user input for parameters
@mcp: {
name : 'get-author',
description: 'Gets the desired author',
tool : true,
elicit : ['input']
}
function getAuthor(id: String) returns String;
// Request both input and confirmation
@mcp: {
name : 'books-by-author',
description: 'Gets a list of books made by the author',
tool : true,
elicit : ['input', 'confirm']
}
function getBooksByAuthor(authorName: String) returns array of String;注意:目前,Elicitation仅适用于直接工具。包装实体不在此范围内。
激励类型:
confirm:在执行工具之前,通过“是/否”提示请求用户确认input:提示用户提供工具参数的值- 组合的:两者都使用
['input', 'confirm']首先收集参数,然后请求确认
用户体验:
- 确认:“请确认您要执行‘获取随机书籍推荐’操作”
- 输入:“请填写所需参数”,并为每个参数填写表格
- 用户行为:接受、拒绝或取消诱导请求
- 提前退出:如果被拒绝或取消,工具会返回相应的消息
带有@mcp.hint的元素提示
使用提供单个属性和参数的上下文描述 @mcp.hint 注释。这些提示有助于AI代理更好地理解特定字段的目的、约束和预期值。
在哪里使用提示
资源实体属性
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';
}数组元素
entity Authors {
key ID : Integer;
name : String @mcp.hint: 'Full name of the author';
nominations : array of String @mcp.hint: 'Awards that the author has been nominated for';
}功能/动作参数
@mcp: {
name : 'books-by-author',
description: 'Gets a list of books made by the author',
tool : true
}
function getBooksByAuthor(
authorName : String @mcp.hint: 'Full name of the author you want to get the books of'
) returns array of String;复杂类型字段
type TValidQuantities {
positiveOnly : Integer @mcp.hint: 'Only takes in positive numbers, i.e. no negative values such as -1'
};如何使用提示
提示会自动合并到:
- 资源描述:实体包装工具中的字段级指导(查询/获取/创建/更新/删除)
- 工具参数模式:增强了AI代理可见的参数描述
- 输入验证:构建函数调用时AI代理的上下文
示例:增强工具体验
没有 @mcp.hint:
{
"tool": "CatalogService_Books_create",
"parameters": {
"ID": { "type": "integer" },
"stock": { "type": "integer" }
}
}随着 @mcp.hint:
{
"tool": "CatalogService_Books_create",
"parameters": {
"ID": {
"type": "integer",
"description": "Must be a unique number not already in the system"
},
"stock": {
"type": "integer",
"description": "The amount of books currently on store shelves"
}
}
}最佳实践
- 具体:提供具体的例子和制约因素
- ❌ 坏: @mcp.hint: 'Author name' - ✅ 好: @mcp.hint: 'Full name of the author (e.g., "Ernest Hemingway")'
- 包括约束:文档验证规则和业务逻辑
- ✅ @mcp.hint: 'Must be between 0 and 999, representing quantity in stock'
- 澄清外键:帮助AI代理理解关联
- ✅ @mcp.hint: 'Foreign key reference to Authors.ID'
- 解释业务背景:添加特定于域的信息
- ✅ @mcp.hint: 'ISBN-13 format, used for unique book identification'
- 避免冗余:不要重复从字段名称和类型中显而易见的内容
- ❌ 坏: stock: Integer @mcp.hint: 'Stock value' - ✅ 好: stock: Integer @mcp.hint: 'Current inventory count across all warehouses'
技术说明
- 提示在模型加载时解析并存储在
propertyHints地图 - 提示既适用于简单类型,也适用于复杂嵌套类型
- 在资源查询和工具执行中都可以访问提示
- 数组元素提示应用于数组项,而不是数组本身
提示模板
定义可重用的AI提示模板:
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'
}]
}];🔧 配置
插件配置
通过CAP应用程序配置MCP插件 package.json 或 .cdsrc 文件:
{
"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
}
}
}
}
}配置选项
| 选项 | 类型 | 默认值 | 描述 | |
|---|---|---|---|---|
name | string | package.json名称 | MCP服务器名称 | |
version | string | package.json版本 | MCP服务器版本 | |
auth | "inherit" | "none" | "inherit" | 身份验证模式 |
instructions | 字符串 | null | 代理的MCP服务器说明 | |
enable_model_description | 布尔值 | true | 确定MCP服务器是否应包含模型描述工具 | |
capabilities.resources.listChanged | 布尔值 | true | 启用资源列表更改通知 | |
capabilities.resources.subscribe | 布尔值 | false | 启用资源订阅 | |
capabilities.tools.listChanged | 布尔值 | true | 启用工具列表更改通知 | |
capabilities.prompts.listChanged | 布尔值 | true | 启用提示列表更改通知 |
验证配置
该插件支持两种身份验证模式:
"inherit" 模式(默认)
使用CAP应用程序的现有身份验证系统:
{
"cds": {
"mcp": {
"auth": "inherit"
},
"requires": {
"auth": {
"kind": "xsuaa"
}
}
}
}"none" 模式(开发/测试)
完全禁用身份验证:
{
"cds": {
"mcp": {
"auth": "none"
}
}
}⚠️ 安全警告:仅使用 "none" 开发环境中的模式。在没有正确身份验证的情况下,切勿部署到生产环境。
身份验证流程
- MCP客户端连接到
/mcp端点 - 如果使用的身份验证样式是OAuth,则将执行OAuth流
- CAP身份验证中间件验证凭据(如果
auth: "inherit") - 使用经过身份验证的用户上下文建立MCP会话
- 所有MCP操作(资源、工具、提示)都继承经过身份验证的用户的权限
自动功能
插件自动:
- 扫描CAP服务定义以查找
@mcp注释 - 生成适当的MCP资源、工具和提示
- 创建具有适当OData v4查询参数支持的ResourceTemplates
- 在以下位置设置HTTP端点
/mcp和/mcp/health - 管理MCP会话生命周期和清理
🌟 AI交互示例
配置后,AI代理可以自然地与您的CAP数据交互;让我们以标准CAP书店为例:
- “给我看看库存最高的5本书” → 使用查询图书资源
$orderby=stock desc&$top=5 - “查找名称中包含‘Smith’的作者” → Uses
$filter=contains(name,'Smith')关于作者资源 - “获取图书ID 123的当前库存” → 呼叫
get-stock指定书籍的工具 - “给我推荐一本书” → 执行
book-recommendation工具
虽然这展示了这个示例CDS注释的工作原理,但可能性是无限的,只有你和你的数据设定了界限。
📋 业务案例示例:工作流审批管理
设置
您的CAP服务包括一个与MCP集成的工作流管理系统:
service WorkflowService {
@mcp: {
name : 'get-my-pending-approval',
description: 'Fetches workflows awaiting approval by the specified user',
tool : true
}
function getPendingApproval(userId: String) returns array of Workflows;
}交互流程
1.用户查询
User: "Hey , do I have any workflows pending approval?"2.AI代理处理
- 代理将此识别为对待定批准信息的请求
- 识别
get-my-pending-approval工具作为适当的方法 - 根据上下文(会话、身份验证等)确定用户的ID
3.MCP工具执行
// Agent calls the MCP tool
{
"tool": "get-my-pending-approval",
"arguments": {
"userId": "john.doe@company.com"
}
}4.CAP服务处理
- 您的CAP服务收到工具调用
- 执行
getPendingApproval("john.doe@company.com") - 查询您的工作流数据库/系统
- 返回结构化工作流数据
5.人工智能响应
Agent: "You have 3 workflows pending your approval:
• **Purchase Order #PO-2024-001**
Submitted by: Sarah Johnson
Amount: $12,500
Submitted: 2 days ago
• **Budget Request - Marketing Q2**
Submitted by: Mike Chen
Amount: $45,000
Submitted: 1 day ago
• **New Employee Onboarding - Jane Smith**
Submitted by: HR Department
Start Date: Next Monday
Submitted: 4 hours ago
Would you like me to help you review any of these in detail?"商业价值
- 即刻进入:无需登录工作流系统或浏览复杂的UI
- 情境智能:人工智能可以根据紧急程度、金额或业务规则进行优先级排序
- 自然交互:用户可以用通俗易懂的语言提出后续问题
- 集成就绪:与现有的基于CAP的工作流系统配合使用
- 移动友好:从任何兼容MCP的AI客户端获取批准
🧰 开发与测试
测试您的MCP实现
如果你想在本地测试你在CAP应用程序上实现的MCP,你有两个选项(不涉及与AI Agent的直接集成)。
选项#1-MCP检查器
您可以通过使用官方 @modelcontextprotocol/inspector.
此检查器可以通过以下任一方式启动 npm run inspect 命令,或通过运行 npx @modelcontextprotocol/inspector.
对于您自己项目中的插件实现,建议将上述命令添加到您自己的脚本集合中。
有关检查员的更多信息,请 请参阅官方文件.
选项#2-布鲁诺系列
此存储库附带了一个Bruno集合,其中包括一些示例查询,您可以使用这些查询来验证您的MCP实现。这些可以在 bruno 目录。
选项3-自动测试
运行全面的测试套件来验证您的实现:
# Test specific components
npm test -- --testPathPattern=annotations # Test annotation parsing
npm test -- --testPathPattern=mcp # Test MCP functionality
npm test -- --testPathPattern=security # Test security boundaries
npm test -- --testPathPattern=auth # Test authentication
# Run with detailed output
npm test -- --verbose
# Run in watch mode for development
npm test -- --watch延伸阅读
- 实体工具和配置简短指南:
docs/entity-tools.md
🤝 贡献
欢迎投稿!这是一个开源项目,旨在将CAP应用程序与AI生态系统连接起来。
- 问题:报告错误和请求功能
- 拉取请求:提交改进和修复
- 文档:帮助改进示例和指南
- 测试:分享您的用例和边缘案例
📄 许可证
此项目根据Apache-2.0许可证获得许可-请参阅 许可证.md 文件以获取详细信息。
🔧 故障排除
常见问题
MCP服务器未启动
- 检查端口可用性:确保端口4004未被其他进程使用
- 验证CAP服务:确保您的CAP申请成功启动
cds serve - 身份验证问题:如果使用
auth: "inherit",确保正确配置了CAP身份验证
MCP客户端连接失败
# Check if MCP endpoint is accessible
curl http://localhost:4004/mcp/health
# Expected response:
# {"status": "healthy", "timestamp": "2025-01-XX..."}注释不起作用
- 语法检查:验证您的
@mcp注释语法与示例匹配 - 服务部署:确保正确部署带注释的实体/函数
- 区分大小写:检查注释属性是否使用正确的大小写(
resource,tool,prompts)
OData查询问题
- SDK Bug解决方法:由于已知
@modelcontextprotocol/sdkbug,使用动态查询时提供所有查询参数 - 参数验证:确保查询参数与OData v4语法匹配
性能问题
- 资源过滤:使用特定
resource数组而不是true对于大型数据集 - 查询优化:为频繁查询的字段实施适当的数据库索引
调试
启用调试日志记录
{
"cds": {
"log": {
"levels": {
"mcp": "debug"
}
}
}
}测试MCP实施
# Use MCP Inspector for interactive testing
npm run inspect
# Or run integration tests
npm test -- --testPathPattern=integration获取帮助
- GitHub 问题:报告错误 gavdillabs/cap mcp插件
- 文档:检查 MCP规范 有关协议详细信息
- CAP支持:请参阅 SAP CAP文档 针对CAP特定问题
🚨 性能和限制
已知限制
- SDK错误:由于以下原因,动态资源查询需要所有查询参数
@modelcontextprotocol/sdkRFC模板字符串问题
性能考量
- 大型数据集:使用
resource: ['top']或对具有许多记录的实体的类似约束 - 复杂查询:OData查询解析增加了开销-考虑对频繁访问的数据进行缓存
- 并发会话:每个MCP客户端都创建一个单独的会话-监控许多客户端的内存使用情况
规模建议
- 发展:无具体限制
- 生产:使用预期的并发MCP客户端计数进行测试
- 企业:考虑高可用性场景的负载平衡
🔗 资源
______________________________________________________________________
(c) Gavdi Labs 2025版权所有-保留所有权利
利用模型上下文协议的强大功能,将CAP应用程序转换为支持AI的系统。
