0%

MCP服务入门:访问Postgres数据库

MCP(Model Context Protocol)是一种新兴的协议,允许AI助手与外部系统进行深度集成。对于初学者来说,理解和构建一个MCP服务可能会有些挑战。本文将通过分析一个实际的企业风险监测MCP服务项目,为您详细介绍如何构建自己的MCP服务。

什么是MCP?

MCP(Model Context Protocol)是专为AI助手设计的开放协议,它允许AI助手与外部系统进行交互,获取实时数据、执行操作或访问资源。通过MCP,AI助手可以突破其训练数据的限制,访问企业内部系统、数据库或其他服务,从而提供更加准确和实用的信息。

项目概述

我们分析的项目是一个企业风险监测系统,它通过MCP协议为AI助手提供访问数据库的能力,并利用LLM(大语言模型)实现智能交互。该系统主要包含以下功能:

  1. 访问企业数据库,查询企业信息
  2. 查询风险监测数据
  3. 获取告诫信、检查记录等监管信息
  4. 利用LLM将用户自然语言查询转换为结构化数据库查询
  5. 使用LLM将数据库查询结果转换为自然语言回答
  6. 借助LLM进行数据分析和业务洞察生成

项目架构分析

1. 多层架构设计

该项目采用了多层架构设计,包含以下几个核心组件:

  • Express API服务:提供RESTful API接口,用于传统的Web应用访问
  • MCP服务适配器:实现MCP协议,为AI助手提供专用接口
  • 数据库访问层:封装数据库操作,提供统一的数据访问接口
  • 自然语言处理模块:将用户自然语言查询转换为结构化查询

2. MCP服务实现方式

项目提供了三种不同的MCP服务实现:

HTTP版本(mcp-server.js)

这是最常用的实现方式,通过HTTP协议提供MCP服务。它具有以下特点:

  • 使用Express框架构建
  • 提供标准的HTTP端点(如/mcp/tools/call)
  • 支持WebSocket连接,实现实时通信
  • 与现有的Express服务共享数据库连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// MCP服务核心类
class MCPSixService {
constructor() {
this.app = express();
this.server = createServer(this.app);
this.io = new Server(this.server, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});

// 初始化数据库连接
this.sixDbPool = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST ,
database: process.env.DB_NAME,
password: process.env.DB_PASSWORD,
port: parseInt(process.env.DB_PORT)
});
}
}

Stdio版本(mcp-stdio.js)

通过标准输入输出(stdio)进行通信,适用于与本地AI助手的深度集成。这种方式具有以下优势:

  • 无需网络通信,性能更好
  • 更适合桌面应用集成
  • 实现了完整的JSON-RPC协议

Direct版本(mcp-direct.js)

直接连接数据库,不依赖Express服务。适用于轻量级部署场景。

3. 核心功能模块

工具系统(Tools)

MCP服务通过”工具”概念为AI助手提供功能。项目中实现了多个工具:

  • query_risk_data:查询风险监测数据
  • query_company_info:查询企业信息
  • query_warning_data:查询告诫信数据
  • query_check_records:查询检查记录
  • query_form_data:查询表单数据

每个工具都有明确的输入参数定义和功能描述,便于AI助手理解和使用。

1
2
3
4
5
6
7
8
9
10
11
12
{
name: 'query_company_info',
description: 'Query company information from the six database',
inputSchema: {
type: 'object',
properties: {
company_name: { type: 'string', description: 'Company name to search for' },
county: { type: 'string', description: 'County filter' }
},
required: ['company_name']
}
}

资源系统(Resources)

资源系统允许AI助手访问特定的数据资源:

  • 企业信息资源
  • 风险监测数据资源
  • 告诫信数据资源
  • 检查记录资源

提示系统(Prompts)

提示系统为AI助手提供预定义的交互模板:

  • 风险分析报告提示
  • 企业档案报告提示

4. 数据库集成

项目集成了两个PostgreSQL数据库:

  1. six数据库:存储企业基本信息、风险监测数据、告诫信、检查记录等
  2. form2025数据库:存储各类表单数据

通过Node.js的pg库建立连接池,确保高效的数据库访问:

1
2
3
4
5
6
7
const sixDbPool = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_NAME,
password: process.env.B_PASSWORD,
port: parseInt(process.env.DB_PORT)
});

5. LLM在MCP服务中的核心作用

在该项目中,LLM(大语言模型)扮演着至关重要的角色,它不仅是自然语言处理的工具,更是连接用户意图与系统功能的桥梁。LLM在MCP服务中主要有以下几个关键作用:

5.1 自然语言到结构化查询的转换

LLM的核心功能之一是将用户的自然语言查询转换为系统可以理解和执行的结构化查询。在风险监测系统中,当用户询问”查询2025年以来风险监测发现哪些企业存在什么风险?”时,LLM会分析这句话的语义,识别出关键信息(时间范围、查询对象、查询目的),然后生成相应的数据库查询语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// NLP服务中的核心方法
async getToolCallFromQuery(query) {
const prompt = this.createToolCallPrompt(query);
const response = await this.ollama.generate({ prompt });
return this.parseToolCall(response);
}

// 提示工程:指导LLM如何生成工具调用
private createToolCallPrompt(query: string): string {
return `
Based on the user query: "${query}", identify the correct tool and arguments.

Available tools are:
- six.query(sql: string)
- form2025.query(sql: string)

Important database tables:
- six_company: contains company information
- six_risk: contains risk information
- six_warn: contains warning information
- six_checkrecord: contains check records

You must respond with ONLY a single JSON object in this exact format:
{"tool": "six.query", "args": {"sql": "SELECT c.name, w.reason, w.ddate FROM six_warn w JOIN six_company c ON w.company_id = c.id WHERE w.ddate >= '2025-01-01'"}}

Do not include any other text or explanation.
`;
}

5.2 数据到自然语言回答的转换

LLM的另一个重要作用是将数据库查询结果转换为自然语言回答。当系统从数据库中获取到结构化的数据后,LLM会根据这些数据生成易于理解的自然语言描述,使用户能够轻松理解查询结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 根据查询结果生成自然语言回答
private createFinalAnswerPrompt(query, context) {
return `
Please answer the user's original query based on the provided data.
Original Query: "${query}"
Data:
${JSON.stringify(context, null, 2)}

Generate a comprehensive, natural language answer in Chinese with the following structure:
1. 总体概述(发现多少条记录,涉及多少家企业)
2. 详细分析(按需要分类,如按企业、时间等)
3. 重要发现和建议

Please ensure the answer is clear, professional, and use appropriate emoji icons to improve readability.
`;
}

5.3 智能数据分析与洞察生成

LLM不仅能够进行语言转换,还能对数据进行深度分析,发现潜在的模式和趋势,并生成有价值的业务洞察。例如,当查询风险监测数据时,LLM可以分析不同企业的风险等级分布、风险类型趋势等,并提供针对性的建议。

5.4 复杂查询的理解与处理

对于复杂的自然语言查询,LLM能够理解其中的逻辑关系和约束条件,并生成相应的复杂SQL查询。例如,当用户询问”查找在2025年收到告诫信且风险等级为严重的企业”时,LLM能够理解这种复合条件,并生成包含JOIN操作和复杂WHERE条件的SQL语句。

5.5 上下文理解与对话管理

在与AI助手的交互中,LLM还负责维护对话上下文,理解用户的连续询问,并提供连贯的回答。这使得用户可以进行多轮对话,逐步深入了解所需信息。

通过LLM的这些能力,MCP服务能够实现真正的智能交互,让用户可以用自然语言与企业系统进行对话,而无需了解复杂的数据库结构或查询语法。

关键技术点解析

1. MCP协议实现

MCP协议基于JSON-RPC 2.0,主要包含以下方法:

  • initialize:初始化连接
  • tools/list:列出可用工具
  • tools/call:调用工具
  • resources/list:列出可用资源
  • prompts/list:列出可用提示

2. 数据库查询优化

项目通过参数化查询防止SQL注入,并使用连接池提高性能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
async queryCompanyInfo(args) {
let query = 'SELECT * FROM six_company';
const params = [];
let paramIndex = 1;

if (args.company_name) {
query += ` WHERE name ILIKE $${paramIndex}`;
params.push(`%${args.company_name}%`);
paramIndex++;
}

const result = await this.sixDbPool.query(query, params);
return result.rows;
}

3. 错误处理机制

完善的错误处理机制确保服务的稳定性:

1
2
3
4
5
6
try {
const result = await this.sixDbPool.query(query, params);
return result.rows;
} catch (error) {
throw new Error(`Failed to query company info: ${error.message}`);
}

部署和管理

项目提供了完整的部署和管理方案:

1. 环境配置

通过.env文件管理环境变量:

1
2
3
4
5
PORT=3000
B_USER=
DB_HOST=localhost
DB_NAME=
DB_PASSWORD=

2. 服务管理脚本

提供了bash脚本用于服务管理:

1
2
3
4
5
6
7
8
# 启动所有服务
./manage.sh start

# 停止所有服务
./manage.sh stop

# 检查服务状态
./manage.sh status

3. 系统服务集成

通过plist文件支持macOS系统服务集成:

1
2
3
4
5
6
7
<key>Label</key>
<string>com.mcp.six.mcp</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/node</string>
<string>/path/to/mcp-server.js</string>
</array>

构建自己的MCP服务

基于这个项目的经验,构建自己的MCP服务可以遵循以下步骤:

1. 确定服务功能

首先明确你的MCP服务要提供什么功能,比如:

  • 访问特定数据库
  • 集成企业内部系统
  • 提供特定领域的专业知识

2. 设计工具接口

为每个功能设计清晰的工具接口,包括:

  • 工具名称
  • 功能描述
  • 输入参数定义
  • 返回数据结构

3. 实现核心逻辑

根据功能需求实现核心业务逻辑:

1
2
3
4
5
6
7
8
9
10
11
class MyMCPService {
async handleToolCall(params) {
const { name, arguments: args } = params;

switch (name) {
case 'my_tool':
return await this.myToolImplementation(args);
// 其他工具...
}
}
}

4. 集成MCP协议

实现MCP协议的核心方法:

  • 工具列表
  • 工具调用
  • 资源访问
  • 提示管理

5. 添加AI能力(可选)

如果需要自然语言处理能力,可以集成大语言模型服务:

  • Ollama
  • OpenAI API
  • 其他本地或云端模型服务

6. 部署和测试

完成开发后,进行部署和测试:

  • 配置环境变量
  • 设置数据库连接
  • 测试各项功能
  • 验证与AI助手的集成效果

总结

通过分析这个企业风险监测MCP服务项目,我们可以看到一个完整的MCP服务应该具备以下特点:

  1. 清晰的架构设计:分离核心业务逻辑与协议实现
  2. 完整的协议支持:正确实现MCP协议的各项功能
  3. 良好的扩展性:易于添加新工具和功能
  4. 完善的错误处理:确保服务的稳定性
  5. 便捷的部署管理:提供简单易用的部署和管理方案
  6. 强大的LLM集成:利用大语言模型实现智能交互

LLM在MCP服务中发挥着至关重要的作用,它不仅是自然语言处理的工具,更是连接用户与企业系统的智能桥梁。通过LLM,用户可以用自然语言与复杂的数据库系统进行交互,而无需了解技术细节。这大大降低了用户使用企业系统的门槛,提升了用户体验。

对于MCP初学者来说,可以从简单的功能开始,逐步扩展和完善服务功能。随着对MCP协议理解的深入,可以构建更加复杂和强大的AI助手集成服务。

通过MCP协议和LLM的结合,我们可以让AI助手真正成为企业数据和知识的门户,为用户提供更加准确、智能和实用的信息服务。