在实际开发中,经常遇到这样的需求:将已有的工作流封装成一个MCP服务,然后集成到智能体里,让智能体具备调用这个服务的能力。具体怎么做?这篇文章就围绕阿里云百炼平台,完整走一遍从零开始的流程——包括代码编写、发布到npm、在百炼创建自定义MCP,最后在智能体中引用。下面先介绍其中一种实现方式。
整体步骤分为四个环节:
- 编写代码,将工作流封装成MCP服务
- 把封装好的服务发布到npm官方平台
- 在阿里云百炼中创建自定义MCP服务
- 在智能体中引用这个自定义MCP服务

一、搭建MCP服务
选用Node.js + TypeScript来实现,这也是目前比较主流的方式。
1. 创建Node.js项目
开始之前,确保已经安装了Node.js(如果还没装,可以去官方链接下载)。
本地创建一个文件夹,名称随意,比如这里命名为 bailian-mcp-workflow-server。用VSCode打开或者直接命令行进入都行。
1.1 初始化项目
在命令行中运行:
npm init -y
执行成功后自动生成 package.json,修改内容如下:
{
"name": "bailian-mcp-workflow-server",
"version": "0.0.1",
"description": "Bailian MCP server",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
"homepage": "https://modelcontextprotocol.io",
"bugs": "https://github.com/modelcontextprotocol/servers/issues",
"type": "module",
"bin": {
"mcp-server-bra ve-search": "dist/index.js"
},
"files": [
"dist"
],
"scripts": {
"build": "tsc && shx chmod +x dist/*.js",
"prepare": "npm run build",
"watch": "tsc --watch"
},
"dependencies": {
"@modelcontextprotocol/sdk": "1.0.1"
},
"devDependencies": {
"@types/node": "^22",
"shx": "^0.3.4",
"typescript": "^5.6.2"
}
}
1.2 创建 tsconfig.json
在 package.json 同级目录下创建:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"outDir": "./dist",
"rootDir": "."
},
"include": [
"./**/*.ts"
],
"exclude": [
"node_modules"
]
}
1.3 创建 index.ts
在同级目录下创建空文件即可,后续写入核心代码。
1.4 安装依赖
npm install
2. 将百炼智能体应用API封装为MCP
2.1 查看官方API文档
百炼应用调用的API参考文档:https://bailian.console.aliyun.com/?tab=api#/api/?type=app。官方示例调用方式如下:
curl -X POST https://dashscope.aliyuncs.com/api/v1/apps/YOUR_APP_ID/completion \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"input": {
"prompt": "你是谁?"
},
"parameters": {},
"debug": {}
}'
目标就是将这个API封装成MCP工具。
2.2 编写封装代码
在 index.ts 中写入以下内容:
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const MARKET_RESEARCH_ASSISTANT = {
name: "market_research_tool",
description: "This is an intelligent market research report generation assistant, specifically designed to efficiently and professionally build research plans.",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "Search query (max 400 chars, 50 words)"
}
},
required: ["query"],
},
};
// Server implementation
const server = new Server(
{
name: "bailian-mcp-workflow-server",
version: "0.1.0",
},
{
capabilities: {
tools: {},
},
}
);
// Check for API key
const DASHSCOPE_API_KEY = process.env.DASHSCOPE_API_KEY!;
if (!DASHSCOPE_API_KEY) {
console.error("Error: DASHSCOPE_API_KEY environment variable is required");
process.exit(1);
}
const APP_ID = process.env.APP_ID!;
if (!APP_ID) {
console.error("Error: APP_ID environment variable is required");
process.exit(1);
}
async function performWebMarketResearch(query: any){
const url = 'https://dashscope.aliyuncs.com/api/v1/apps/'+APP_ID+'/completion';
const requestBody = {
"input": {
"prompt": query
},
"parameters": {},
"debug": {}
};
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': "Bearer "+DASHSCOPE_API_KEY
},
body: JSON.stringify(requestBody)
});
if (!response.ok) {
throw new Error(`Bailian API error: ${response.status} ${response.statusText}\n${await response.text()}`);
}
const descriptionsData = await response.json();
const strjson = JSON.stringify(descriptionsData);
return strjson;
}
// Tool handlers
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [MARKET_RESEARCH_ASSISTANT],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const { name, arguments: args } = request.params;
if (!args) {
throw new Error("No arguments provided");
}
switch (name) {
case "market_research_tool": {
const { query } = args;
const results = await performWebMarketResearch(query);
return {
content: [{ type: "text", text: results }],
isError: false,
};
}
default:
return {
content: [{ type: "text", text: `Unknown tool: ${name}` }],
isError: true,
};
}
} catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
});
async function runServer(){
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Bailian Mcp Workflow Server running on stdio");
}
runServer().catch((error) => {
console.error("Fatal error running server:", error);
process.exit(1);
});
2.3 代码关键解读
核心功能:提供了一个名为 market_research_tool 的市场研究工具,基于用户输入的查询,调用阿里云 DashScope API 获取结果,并以 JSON 格式返回。
- 初始化Server:创建一个Server实例,指定名称和版本,同时声明支持tools能力。
- 环境变量检查:必须提供
DASHSCOPE_API_KEY和APP_ID,否则程序退出。 - 工具定义:
MARKET_RESEARCH_ASSISTANT对象定义了工具名称、描述以及输入参数的JSON Schema(要求用户提供query,限制400字符)。 - 注册工具列表:通过
ListToolsRequestSchema将工具信息返回给客户端。 - API封装:在
performWebMarketResearch中构造fetch请求调用百炼API,返回结果直接回传给MCP客户端。百炼会自动将返回的JSON转为Markdown格式展示。
如果想封装其他API接口,只需要修改 requestBody 和URL即可,整体结构保持一致。
2.4 本地联调测试(Cline)

配置 mcpServers:
{
"mcpServers": {
"bailian-mcp-workflow-server": {
"disabled": false,
"timeout": 300000,
"command": "cmd",
"args": [
"/c",
"node",
"D:\ProgramData\bailian-mcp-workflow-server\index.ts"
],
"env": {
"DASHSCOPE_API_KEY": "sk-212aeb2121213232",
"APP_ID": "3621da212127b272343411337e7"
},
"transportType": "stdio"
}
}
}
其中 DASHSCOPE_API_KEY 和 APP_ID 需要替换为自己的百炼API-KEY和应用ID。配置好后测试提问,结果如图。


二、将项目打包并发布到npm
1. 注册npm账号
去 npm官网 注册。
2. 本地登录npm
在项目终端运行:
npm login
输入用户名、密码、邮箱。登录成功后会有类似输出:
Logged in as on https://registry.npmjs.org/.
3. 检查包名唯一性
发布前到 npmjs.com 搜索包名,或直接尝试发布。如果名字被占用,需要修改 package.json 中的 name 字段。
4. 项目打包
在终端运行:
npm run build
成功后会在项目目录下自动创建 dist 文件夹。
5. 发布包
在项目根目录运行:
npm publish
发布成功后,包就正式上架到npm了。地址类似:https://www.npmjs.com/package/bailian-mcp-workflow-server
6. 通过npm包在Cline中再次测试
本地配置改为用 npx 方式执行:
Windows配置
{
"mcpServers": {
"bailian-mcp-workflow-server": {
"disabled": false,
"timeout": 300000,
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"bailian-mcp-workflow-server"
],
"env": {
"DASHSCOPE_API_KEY": "sk-212aeb2121213232",
"APP_ID": "3621da212127b272343411337e7"
},
"transportType": "stdio"
}
}
}
MacOS/Linux配置
{
"mcpServers": {
"bailian-mcp-workflow-server": {
"disabled": false,
"timeout": 300000,
"command": "npx",
"args": [
"-y",
"bailian-mcp-workflow-server"
],
"env": {
"DASHSCOPE_API_KEY": "sk-212aeb2121213232",
"APP_ID": "3621da212127b272343411337e7"
},
"transportType": "stdio"
}
}
}
再次启动Cline测试,验证通过。
三、集成到阿里云百炼的自定义MCP中
1. 创建自定义MCP服务
在阿里云百炼控制台,进入自定义MCP配置页面,填入MCP服务配置:
{
"mcpServers": {
"bailian-mcp-workflow-server": {
"disabled": false,
"timeout": 300000,
"command": "npx",
"args": [
"-y",
"bailian-mcp-workflow-server"
],
"env": {
"DASHSCOPE_API_KEY": "sk-212aeb2121213232",
"APP_ID": "3621da212127b272343411337e7"
},
"transportType": "stdio"
}
}
}
点击提交部署。
2. 测试工具
部署成功后,选择【工具】进行测试,返回正常结果即说明配置正确。
3. 创建智能体并添加MCP服务
在智能体配置中,添加自定义MCP服务,选择刚才部署的 bailian-mcp-workflow-server。
4. 运行测试
在智能体中提问,确认MCP服务能被正常调用。
百炼未来将提供更简便的配置方式,用户无需手动写代码,在平台中简单配置即可将工作流转化为MCP服务并引入智能体。不过目前这种方式已经相当实用,值得一试。
