模型上下文协议(MCP)提供了一种标准化的方式,使应用程序能够向LLMs提供上下文,将上下文提供与LLM交互分离。
此Apex SDK实现了MCP规范,使您能够:
<a name="安装链接"></a>
/packaging/installPackage.apexp?p0=04tN2000000mUAHIA2
<a name="如何公开服务器"></a>
要让访客用户访问服务器,请创建一个站点并启用访客用户的DemoServer类:
设置 > 用户界面 > 站点和域名 > 站点新建并输入站点标签和站点名称,然后点击保存激活,然后点击公共访问设置启用的Apex类访问部分,将DemoServer添加到启用的Apex类设置 > 用户界面 > 站点和域名 > 站点,找到新创建的站点,并复制其站点URL/services/apexrest/mcp附加到复制的站点URL以获取完整的MCP服务器URL[!注意] 如果您的组织有命名空间,URL将是
{站点URL}/services/apexrest/{命名空间}/mcp。
<a name="测试MCP服务器"></a>
要测试服务器,请使用MCP检查器工具。
https://{实例URL}/services/apexrest/mcp)成功连接后,您将看到可用资源、工具和提示的列表,如下图所示:

创建MCP服务器有几种方式:
ctx.Server server = new ctx.Server('1.0.0', 'autocare-plus-mcp-server');
String 版本 = '1.0.0';
String 服务器名称 = 'autocare-plus-mcp-server';
String 服务器标题 = 'AutoCare Plus MCP服务器';
String 指令 = 'AutoCare Plus汽车服务,提供可用服务列表和预约工具。';
ctx.Server server = new ctx.Server(版本, 服务器名称, 服务器标题, 指令);
ctx.Server server = new ctx.Server('1.0.0', 'autocare-plus-mcp-server')
.setInstructions(指令)
.setTitle(服务器标题);
public with sharing class GetAvailableCarServicesTool extends ctx.Tool {
public static final String 工具名称 = 'get-available-car-services-tool';
public static final String 工具描述 = '检索所有可用的汽车服务及其Salesforce记录ID。';
public GetAvailableCarServicesTool() {
super(工具名称, 工具描述);
}
//...
}
public with sharing class GetAvailableCarServicesTool extends ctx.Tool {
public static final String 工具名称 = 'get-available-car-services-tool';
public static final String 工具标题 = '获取可用汽车服务';
public static final String 工具描述 = '检索所有可用的汽车服务及其Salesforce记录ID。';
public GetAvailableCarServicesTool() {
super(工具名称, 工具标题, 工具描述);
}
//...
}
public with sharing class WeatherTool extends ctx.Tool {
public WeatherTool() {
super('get-weather-details', '获取特定城市的天气详情');
ctx.Tool.Property 城市名称 = new ctx.Tool.Property(
'城市名称', // 属性名
'string', // 属性类型
'城市的名称', // 属性描述
true // 如果属性是必需的,则为true,否则为false
);
this.addProperty(城市名称);
}
//...
}
public with sharing class WeatherTool extends ctx.Tool {
//...
public override String call(Map<String, Object> 输入) {
String 城市名称 = (String) 输入.get('城市名称');
// 在这里执行逻辑...
String 结果 = '在' + 城市名称 + '的天气非常完美!';
return 结果;
}
}
public with sharing class CarServiceResource extends ctx.Resource {
public static final String uri = '@server://services';
public static final String 资源名称 = 'service-catalog';
public CarServiceResource() {
super(uri, 资源名称);
}
// ...
}
public with sharing class CarServiceResource extends ctx.Resource {
public static final String uri = '@server://services';
public static final String 资源名称 = 'service-catalog';
public static final String 资源标题 = '服务目录';
public static final String 资源描述 = '所有可用汽车服务的列表';
public static final String 资源MimeType = 'application/json';
public static Long 资源大小 = 65536;
public CarServiceResource() {
super(uri, 资源名称, 资源标题, 资源描述, 资源MimeType, 资源大小);
}
// ...
}
public with sharing class CarServiceResource extends ctx.Resource {
public static final String uri = '@server://services';
public static final String 资源名称 = 'service-catalog';
public static final String 资源标题 = '服务目录';
public static final String 资源描述 = '所有可用汽车服务的列表';
public static final String 资源MimeType = 'application/json';
public static Long 资源大小 = 65536;
public CarServiceResource() {
super(uri, 资源名称);
this.setTitle(资源标题)
.setDescription(资源描述)
.setMimeType(资源MimeType)
.setSize(资源大小);
}
// ...
}
public with sharing class CarServiceResource extends ctx.Resource {
// ...
public override List<ctx.Resource.Content> read() {
// 此方法必须返回List<ctx.Resource.Content>
List<String> 服务 = new List<String>{ '更换机油', '电池检查' };
List<ctx.Resource.Content> 结果 = new List<ctx.Resource.Content>();
for (String 服务 : 服务) {
结果.add(new ctx.Resource.Content(this.uri, 服务));
}
return 结果;
}
}
ctx.Resource.Content 内容 = new ctx.Resource.Content('uri', '文本数据');
String uri = '@server://service/oil-change';
String 名称 = 'oil-change';
String 标题 = '更换机油';
String 文本 = '更换机油服务';
ctx.Resource.Content 内容 = new ctx.Resource.Content(uri, 名称, 标题, 文本);
String uri = '@server://service/oil-change';
String 名称 = 'oil-change';
String 标题 = '更换机油';
String 文本 = '更换机油服务';
ctx.Resource.Content 内容 = new ctx.Resource.Content(uri, 文本)
.setTitle(标题)
.setMimeType('text/plain')
.setText(文本);
String uri = '@file:///example.png';
String 名称 = 'example.png';
String 标题 = '示例图像';
ctx.Resource.Content 内容 = new ctx.Resource.Content(uri)
.setName(名称)
.setTitle(标题)
.setMimeType('image/png')
.setBlobData('base64编码的数据');
public with sharing class CarServiceResource extends ctx.Resource {
public static final String uri = '@server://services';
public static final String 资源名称 = 'service-catalog';
public CarServiceResource() {
super(uri, 资源名称);
List<String> 受众 = new List<String>{ '用户', '助手' }; // "用户"或"助手"或两者
Decimal 优先级 = 0.8; // 0到1之间的值
Datetime 最后修改时间 = System.now(); // ISO 8601格式的时间戳
ctx.Resource.Annotations 注释 = new ctx.Resource.Annotations(受众, 优先级, 最后修改时间);
this.setAnnotations(注释);
}
// ...
}
public with sharing class CodeReviewPrompt extends ctx.Prompt {
public CodeReviewPrompt() {
super('code-review');
}
// ...
}
public with sharing class CodeReviewPrompt extends ctx.Prompt {
public CodeReviewPrompt() {
super('code-review', '代码审查', '要求LLM分析代码质量并提出改进建议');
}
// ...
}
public with sharing class CodeReviewPrompt extends ctx.Prompt {
public CodeReviewPrompt() {
super('code-review');
this.setTitle('代码审查').setDescription('要求LLM分析代码质量并提出改进建议');
}
// ...
}
public with sharing class CodeReviewPrompt extends ctx.Prompt {
public CodeReviewPrompt() {
super('code-review', '代码审查', '要求LLM分析代码质量并提出改进建议');
ctx.Prompt.Argument 代码 = new ctx.Prompt.Argument('代码', '要审查的代码', true);
this.addArgument(代码);
}
// ...
}
public with sharing class CodeReviewPrompt extends ctx.Prompt {
// ...
public override List<ctx.Prompt.Message> get(Map<String, Object> 输入) {
String 代码 = (String) 输入.get('代码');
List<ctx.Prompt.Message> 消息 = new List<ctx.Prompt.Message>();
消息.add(new ctx.Prompt.Message('用户', '审查以下代码并提出改进建议:' + 代码));
return 消息;
}
}