Vào cuối tháng 11 năm 2024, công ty Anthropic đã công bố giao thức MCP (Model Context Protocol) - một tiêu chuẩn mở giúp tích hợp liền mạch giữa các ứng dụng mô hình ngôn ngữ lớn (LLM) với nguồn dữ liệu và công cụ bên ngoài. Dù có thể áp dụng cho nhiều mục đích như phát triển môi trường phát triển IDE hỗ trợ AI, tăng cường giao diện trò chuyện hoặc xây dựng luồng công việc AI tùy chỉnh, MCP cung cấp cách tiếp cận chuẩn hóa để kết nối LLM với môi trường cần thiết.
Cơ chế hoạt động
Giao thức MCP hoạt động theo kiến trúc client-server, cho phép ứng dụng host kết nối với nhiều máy chủ:
- MCP Hosts: Ứng dụng desktop Claude, IDE hoặc công cụ AI truy cập tài nguyên qua MCP
- MCP Clients: Bộ phận giữ kết nối 1:1 với máy chủ theo giao thức
- MCP Servers: Chương trình nhẹ triển khai chức năng cụ thể qua giao thức chuẩn
- Tài nguyên cục bộ: Cơ sở dữ liệu, tập tin trên máy tính cá nhân
- Tài nguyên từ xa: Nguồn có thể truy cập qua internet (ví dụ API)
Đặc biệt, mặc dù mang tên "server", thành phần này nên triển khai cục bộ trên máy tính cá nhân nên có thể sử dụng các bản triển khai từ kho GitHub thay vì tự phát triển.
Quy trình phát triển
Demo dưới đây sử dụng TypeScript và Electron để xây dựng ứng dụng hỗ trợ MCP.
Thành phần chính
- Renderer: Hiển thị dữ liệu và chức năng từ các công cụ (tools) được mô hình ngôn ngữ tương tác
- Process chính: Giao tiếp giữa client và renderer thông qua IPC để đảm bảo luồng dữ liệu mượt mà
- Client: Kết nối và trao đổi dữ liệu giữa ứng dụng với server
Thiết lập kết nối
Hàm khởi tạo client:
async function setupServerConnection(name: string, settings: ServerSettings) {
const channel = new StdioTransport({
command: settings.command,
args: settings.parameters,
});
const connectionName = `${name}-connector`;
const connection = new Connection({
name: connectionName,
version: "1.0.0",
}, {
capabilities: {}
});
await connection.establish(channel);
console.log(`${connectionName} connected.`);
return connection;
}
Quản lý công cụ
Các hàm điều khiển danh sách và gọi công cụ:
async function enumerateTools(connection: Connection) {
const tools = await connection.invoke(
{ method: "tools/list" },
ToolListResponseSchema
);
console.log('Danh sách công cụ:', tools);
return tools;
}
async function executeTool(connection: Connection, parameters: any) {
const result = await connection.invoke(
{
method: "tools/call",
parameters: parameters
},
ToolExecutionResponseSchema
);
console.log('Kết quả công cụ:', result);
return result;
}
Kết nối đa server
Xử lý cấu hình và khởi tạo nhiều client:
async function configureConnections(): Promise {
const config = loadConfiguration(configPath);
if (config) {
console.log('Cấu hình đã tải:', config);
const connections = await Promise.all(
Object.entries(config.servers).map(async ([id, serverConfig]) => {
console.log(`Khởi tạo kết nối ${id} với cấu hình`, serverConfig);
const connection = await setupServerConnection(id, serverConfig);
console.log(`${id} đã khởi tạo.`);
return connection;
})
);
console.log('Tất cả kết nối đã sẵn sàng.');
return connections;
}
console.log('Không có kết nối nào được thiết lập.');
return [];
}
Xử lý IPC
ipcMain.handle('list-connections', () => {
return connections.map(conn => conn.name);
});
connections.forEach(conn => {
ipcMain.handle(`list-${conn.name}`, async () => {
return await enumerateTools(conn);
});
ipcMain.handle(`execute-${conn.name}`, async (event, params) => {
return await executeTool(conn, params);
});
});
Bridge giao diện
async function exposeServerAPIs() {
const serverList = await ipcRenderer.invoke('list-connections');
const api: ServerInterface = {};
serverList.forEach(server => {
api[server] = {
list: () => {
return ipcRenderer.invoke(`list-${server}`);
},
execute: (parameters: any) => {
return ipcRenderer.invoke(`execute-${server}`, parameters);
}
};
});
contextBridge.exposeInMainWorld('connectedServers', api);
}
Triển khai giao diện
async function fetchTools(resourceName: string) {
const serverApis = getServerAccess();
if (!serverApis) {
return null;
}
const serverKeys = Object.keys(serverApis);
const toolList = [];
await Promise.all(serverKeys.map(async (key) => {
const tools = await serverApis[key].list();
for (const tool of tools.tools) {
toolList.push({
type: 'function',
function: {
name: tool.name,
description: tool.description,
parameters: tool.inputSchema,
}
})
}
}));
return toolList;
}
Gọi mô hình
if (aiStore.mcpEnabled) {
body["tools"] = await mcpStore.fetchTools()
}
const request = {
headers: headers,
method: aiStore.requestMethod,
body: JSON.stringify(body),
};
const response = await fetch(
aiStore.baseURL + aiStore.endpoint,
request
);
Kết quả kiểm tra
- Kết nối cơ bản: Mỗi công cụ được định nghĩa rõ ràng tên, tham số và cấu trúc
- Truy cập tập tin: Server sẽ đổi tên thay vì xóa tập tin vì lý do an toàn
- Tra cứu web: Mô hình Qwen-turbo cho kết quả ổn định hơn trong các truy vấn địa phương
Đánh giá
Do MCP mới ra mắt nên ứng dụng vẫn còn hạn chế. Tuy nhiên, nhờ vào các máy chủ mở mã nguồn, việc xây dựng ứng dụng AI trở nên dễ dàng hơn nhiều cho lập trình viên TypeScript hoặc Python. Lưu ý rằng định dạng trả về chứa phương tiện (ảnh) chưa tương thích với OpenAPI hiện tại.
Mã nguồn hoàn chỉnh: GitHub - chat-mcp
Giao diện người dùng: GitHub - chat-ui
Cập nhật 9/2025: Dự án tích hợp MCP hoàn chỉnh