定义
MCP (Model Context Protocol) Server 是一种协议,允许大语言模型通过标准化的接口访问外部数据源和工具。MCP Server 作为中间层,为模型提供结构化的数据访问能力,比如文件系统操作、数据库查询、API调用等。
特点
- 接收AI模型的请求
- 将请求转换为对应工具/服务的API调用
- 把结果返回给AI模型
- 提供统一的安全和权限管理
实际应用举例
文件系统 MCP Server
arduino
用户:帮我分析一下项目文件夹里的代码结构
AI → MCP Server → 本地文件系统
MCP Server返回文件列表和内容给AI进行分析
画个图来更直观地展示这个架构:
MCP Server架构图

举例
接下来我们自己实现一个文件读取的 mcp server,功能是列出指定目录下的所有文件和文件夹。
我们以 nodejs 为例,可以直接让 AI 帮助我们生成代码即可:
package.json
js
{
"name": "file-browser-mcp-server",
"version": "0.1.0",
"description": "一个用于浏览文件系统的 MCP Server",
"type": "module",
"main": "server.js",
"bin": {
"file-browser-mcp": "./server.js"
},
"scripts": {
"start": "node server.js",
"dev": "node --inspect server.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.4.0"
},
"keywords": [
"mcp",
"model-context-protocol",
"file-browser",
"filesystem"
],
"author": "你的名字",
"license": "MIT"
}
server.js
js
#!/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'
import fs from 'fs/promises'
import path from 'path'
class FileBrowserServer {
constructor() {
this.server = new Server(
{
name: 'file-browser-server',
version: '0.1.0',
},
{
capabilities: {
tools: {},
},
},
)
this.setupToolHandlers()
}
setupToolHandlers() {
// 注册工具列表处理器
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'list_directory',
description: '列出指定目录下的所有文件和文件夹',
inputSchema: {
type: 'object',
properties: {
path: {
type: 'string',
description: '要浏览的目录路径',
},
},
required: ['path'],
},
},
{
name: 'get_file_info',
description: '获取文件或目录的详细信息',
inputSchema: {
type: 'object',
properties: {
path: {
type: 'string',
description: '文件或目录的路径',
},
},
required: ['path'],
},
},
],
}
})
// 注册工具调用处理器
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case 'list_directory':
return await this.listDirectory(request.params.arguments)
case 'get_file_info':
return await this.getFileInfo(request.params.arguments)
default:
throw new Error(`未知工具: ${request.params.name}`)
}
})
}
async listDirectory(args) {
try {
const dirPath = args.path
// 检查路径是否存在
await fs.access(dirPath)
// 读取目录内容
const items = await fs.readdir(dirPath)
const itemsWithInfo = []
for (const item of items) {
const itemPath = path.join(dirPath, item)
try {
const stats = await fs.stat(itemPath)
itemsWithInfo.push({
name: item,
type: stats.isDirectory() ? 'directory' : 'file',
size: stats.isFile() ? stats.size : null,
modified: stats.mtime.toISOString(),
path: itemPath,
})
} catch (error) {
// 如果无法获取文件信息,仍然列出文件名
itemsWithInfo.push({
name: item,
type: 'unknown',
error: '无法访问文件信息',
path: itemPath,
})
}
}
return {
content: [
{
type: 'text',
text: JSON.stringify(
{
directory: dirPath,
items: itemsWithInfo,
total: itemsWithInfo.length,
},
null,
2,
),
},
],
}
} catch (error) {
return {
content: [
{
type: 'text',
text: `错误: 无法读取目录 "${args.path}": ${error.message}`,
},
],
isError: true,
}
}
}
async getFileInfo(args) {
try {
const filePath = args.path
const stats = await fs.stat(filePath)
const fileInfo = {
path: filePath,
name: path.basename(filePath),
type: stats.isDirectory()
? 'directory'
: stats.isFile()
? 'file'
: stats.isSymbolicLink()
? 'symlink'
: 'other',
size: stats.size,
created: stats.birthtime.toISOString(),
modified: stats.mtime.toISOString(),
accessed: stats.atime.toISOString(),
permissions: stats.mode.toString(8),
isReadable: true, // 这里可以添加更详细的权限检查
isWritable: true,
}
// 如果是文件,尝试获取扩展名
if (stats.isFile()) {
fileInfo.extension = path.extname(filePath)
}
return {
content: [
{
type: 'text',
text: JSON.stringify(fileInfo, null, 2),
},
],
}
} catch (error) {
return {
content: [
{
type: 'text',
text: `错误: 无法获取 "${args.path}" 的信息: ${error.message}`,
},
],
isError: true,
}
}
}
async run() {
const transport = new StdioServerTransport()
await this.server.connect(transport)
console.error('文件浏览 MCP Server 已启动')
}
}
// 启动服务器
const server = new FileBrowserServer()
server.run().catch(console.error)
复制完代码执行:npm i 安装依赖即可
cline中使用
我们先以 cline 这个插件为例
在 cline 中配置 MCP Server
js
{
"mcpServers": {
"file-browser": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "node",
"args": ["D:/project_code/practice_project/mcp-test/server.js"],
"env": {}
}
}
}
可以看待右侧的 switch 为绿色就代表 mcp 安装成功了,一共有两个 tool,也就是刚刚代码里注册的list_directory 和 get_file_info。

直接提问:帮我"D:/project_code/practice_project/mcp-test/server.js"看下这个路径下有哪些文件,
可以看到大模型调用了我们写的 MCP Server,list_directory,并且成功的输出了出来,大家可以把代码复制进去自己试一试。

cursor中使用
同样找到cursor setting,添加刚刚那段代码即可



提问试试:帮我"D:/project_code/practice_project/mcp-test/server.js"看看这个文件的详细信息
可以看到大模型调用了我们写的 MCP Server,get_file_info,并且成功的输出了出来。

总结
MCP Server通常包含:
- 接口定义: 定义AI可以调用的功能
- 参数验证: 确保传入参数的安全性
- 权限检查: 控制哪些操作被允许
- 错误处理: 优雅地处理异常情况
- 日志记录: 追踪所有操作
比如一个简单的文件MCP Server可能提供这些接口:
scss
- read_file(path) - 读取文件内容
- list_directory(path) - 列出目录内容
- search_files(pattern) - 搜索文件
这样设计的好处是,AI 不需要直接访问你的文件系统,而是通过MCP Server这个受控的中介,既保证了功能性,又维护了安全性。
整个生态系统就像搭积木一样,你可以根据需要选择和组合不同的MCP Server,为AI构建出强大而安全的工具集。