Cơ chế truyền tải (transport) stdio cho phép MCP server giao tiếp với client qua luồng standard input và standard output. Đây là transport được dùng phổ biến và được khuyến nghị nhất trong đặc tả MCP hiện tại, một cách đơn giản và hiệu quả để xây MCP server dễ tích hợp với nhiều ứng dụng client.
Tổng quan
Bài này hướng dẫn xây và dùng MCP server với transport stdio.
Mục tiêu học tập
Sau bài này, bạn sẽ có thể:
- Xây MCP server dùng transport stdio.
- Gỡ lỗi MCP server bằng Inspector.
- Dùng MCP server từ Visual Studio Code.
- Hiểu các cơ chế truyền tải MCP hiện tại và vì sao stdio được khuyến nghị.
Transport stdio hoạt động thế nào
Transport stdio là một trong hai transport chuẩn của đặc tả MCP 2026-07-28. Cách hoạt động:
- Giao tiếp đơn giản: server đọc thông điệp JSON-RPC từ standard input (
stdin) và gửi thông điệp ra standard output (stdout). - Dựa trên tiến trình: client khởi chạy MCP server như một tiến trình con.
- Định dạng thông điệp: mỗi thông điệp là một yêu cầu (request), thông báo (notification) hoặc phản hồi (response) JSON-RPC riêng, phân tách bằng ký tự xuống dòng.
- Ghi log: server CÓ THỂ ghi chuỗi UTF-8 ra standard error (
stderr) để ghi log.
Yêu cầu bắt buộc
- Thông điệp PHẢI được phân tách bằng ký tự xuống dòng và KHÔNG ĐƯỢC chứa ký tự xuống dòng bên trong.
- Server KHÔNG ĐƯỢC ghi ra
stdoutbất cứ thứ gì không phải thông điệp MCP hợp lệ. - Client KHÔNG ĐƯỢC ghi vào
stdincủa server bất cứ thứ gì không phải thông điệp MCP hợp lệ.
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server(
{
name: "example-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
runServer().catch(console.error);
Trong code trên:
- Ta import lớp
ServervàStdioServerTransporttừ MCP SDK. - Ta tạo một instance server với cấu hình và khả năng (capability) cơ bản.
- Ta tạo một instance
StdioServerTransportvà kết nối server với nó, cho phép giao tiếp qua stdin/stdout.
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
# Create server instance
server = Server("example-server")
@server.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
async def main():
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
Trong code trên, chúng ta:
- Tạo instance server bằng MCP SDK.
- Định nghĩa tool bằng decorator.
- Dùng context manager
stdio_serverđể xử lý transport.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithTools<Tools>();
builder.Services.AddLogging(logging => logging.AddConsole());
var app = builder.Build();
await app.RunAsync();
Khác biệt chính so với SSE là server stdio:
- Không cần thiết lập web server hay HTTP endpoint.
- Được client khởi chạy như tiến trình con.
- Giao tiếp qua luồng stdin/stdout.
- Đơn giản hơn để cài đặt và gỡ lỗi.
Bài thực hành: tạo MCP server stdio đơn giản
Trong bài thực hành này, ta tạo một MCP server đơn giản dùng transport stdio được khuyến nghị. Server cung cấp các tool mà client gọi được theo chuẩn Model Context Protocol.
Điều kiện cần
- Python 3.8 trở lên
- MCP Python SDK:
pip install mcp - Hiểu cơ bản về lập trình bất đồng bộ (async)
Hãy tạo MCP server stdio đầu tiên:
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Create the server
server = Server("example-stdio-server")
@server.tool()
def calculate_sum(a: int, b: int) -> int:
"""Calculate the sum of two numbers"""
return a + b
@server.tool()
def get_greeting(name: str) -> str:
"""Generate a personalized greeting"""
return f"Hello, {name}! Welcome to MCP stdio server."
async def main():
# Use stdio transport
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
Khác biệt chính so với cách SSE đã bị ngừng khuyến nghị
Transport stdio (chuẩn hiện tại):
- Mô hình tiến trình con đơn giản: client khởi chạy server như tiến trình con.
- Giao tiếp qua stdin/stdout bằng thông điệp JSON-RPC.
- Không cần thiết lập HTTP server.
- Hiệu năng và bảo mật tốt hơn.
- Gỡ lỗi và phát triển dễ hơn.
Transport SSE (ngừng khuyến nghị từ MCP 2025-06-18):
- Cần HTTP server với các endpoint SSE.
- Thiết lập phức tạp hơn với hạ tầng web server.
- Thêm các cân nhắc bảo mật cho HTTP endpoint.
- Nay được thay bằng Streamable HTTP cho các tình huống web.
Tạo server với transport stdio
Để tạo server stdio, ta cần:
- Import thư viện cần thiết: các thành phần MCP server và transport stdio.
- Tạo instance server: định nghĩa server cùng capability.
- Định nghĩa tool: thêm chức năng muốn cung cấp.
- Thiết lập transport: cấu hình giao tiếp stdio.
- Chạy server: khởi động server và xử lý thông điệp.
Hãy xây từng bước.
Bước 1: tạo server stdio cơ bản
import asyncio
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Create the server
server = Server("example-stdio-server")
@server.tool()
def get_greeting(name: str) -> str:
"""Generate a personalized greeting"""
return f"Hello, {name}! Welcome to MCP stdio server."
async def main():
async with stdio_server(server) as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())
Bước 2: thêm tool
@server.tool()
def calculate_sum(a: int, b: int) -> int:
"""Calculate the sum of two numbers"""
return a + b
@server.tool()
def calculate_product(a: int, b: int) -> int:
"""Calculate the product of two numbers"""
return a * b
@server.tool()
def get_server_info() -> dict:
"""Get information about this MCP server"""
return {
"server_name": "example-stdio-server",
"version": "1.0.0",
"transport": "stdio",
"capabilities": ["tools"]
}
Bước 3: chạy server
Lưu code thành server.py và chạy từ dòng lệnh:
python server.py
Server sẽ khởi động và chờ đầu vào từ stdin. Nó giao tiếp bằng thông điệp JSON-RPC qua transport stdio.
Bước 4: kiểm thử bằng Inspector
Bạn có thể kiểm thử server bằng MCP Inspector:
- Cài Inspector:
npx @modelcontextprotocol/inspector - Chạy Inspector và trỏ nó tới server của bạn
- Thử các tool đã tạo
Gỡ lỗi server stdio
Dùng MCP Inspector
MCP Inspector là công cụ giá trị để gỡ lỗi và kiểm thử MCP server. Cách dùng với server stdio:
-
Cài Inspector:
bashnpx @modelcontextprotocol/inspector -
Chạy Inspector:
bashnpx @modelcontextprotocol/inspector python server.py -
Kiểm thử server: Inspector cung cấp giao diện web, nơi bạn có thể xem capability của server, thử tool với nhiều tham số, theo dõi thông điệp JSON-RPC và gỡ lỗi kết nối.
Dùng VS Code
Bạn cũng có thể gỡ lỗi MCP server ngay trong VS Code:
-
Tạo cấu hình chạy trong
.vscode/launch.json:json{ "version": "0.2.0", "configurations": [ { "name": "Debug MCP Server", "type": "python", "request": "launch", "program": "server.py", "console": "integratedTerminal" } ] } -
Đặt breakpoint trong code server.
-
Chạy debugger và thử bằng Inspector.
Mẹo gỡ lỗi thường dùng
- Dùng
stderrđể ghi log; không bao giờ ghi rastdoutvì nó dành riêng cho thông điệp MCP. - Đảm bảo mọi thông điệp JSON-RPC được phân tách bằng ký tự xuống dòng.
- Thử với tool đơn giản trước khi thêm chức năng phức tạp.
- Dùng Inspector để kiểm tra định dạng thông điệp.
Dùng server stdio từ client
Khi đã xây xong MCP server stdio, bạn có thể tích hợp nó với VS Code để dùng cùng Claude hoặc các client tương thích MCP khác.
Cấu hình
-
Tạo file cấu hình MCP tại
%APPDATA%\Claude\claude_desktop_config.json(Windows) hoặc~/Library/Application Support/Claude/claude_desktop_config.json(Mac):json{ "mcpServers": { "example-stdio-server": { "command": "python", "args": ["path/to/your/server.py"] } } } -
Khởi động lại Claude: đóng và mở lại Claude để nạp cấu hình server mới.
-
Kiểm tra kết nối: bắt đầu một cuộc trò chuyện với Claude và thử dùng tool của server:
- "Can you greet me using the greeting tool?"
- "Calculate the sum of 15 and 27"
- "What's the server info?"
Ví dụ server stdio bằng TypeScript
Đây là ví dụ TypeScript hoàn chỉnh để tham khảo:
#!/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 server = new Server(
{
name: "example-stdio-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Add tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_greeting",
description: "Get a personalized greeting",
inputSchema: {
type: "object",
properties: {
name: {
type: "string",
description: "Name of the person to greet",
},
},
required: ["name"],
},
},
],
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "get_greeting") {
return {
content: [
{
type: "text",
text: `Hello, ${request.params.arguments?.name}! Welcome to MCP stdio server.`,
},
],
};
} else {
throw new Error(`Unknown tool: ${request.params.name}`);
}
});
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
runServer().catch(console.error);
Ví dụ server stdio bằng .NET
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using System.ComponentModel;
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithTools<Tools>();
var app = builder.Build();
await app.RunAsync();
[McpServerToolType]
public class Tools
{
[McpServerTool, Description("Get a personalized greeting")]
public string GetGreeting(string name)
{
return $"Hello, {name}! Welcome to MCP stdio server.";
}
[McpServerTool, Description("Calculate the sum of two numbers")]
public int CalculateSum(int a, int b)
{
return a + b;
}
}
Tóm tắt
Trong bài này, bạn đã học cách:
- Xây MCP server dùng transport stdio hiện tại (cách được khuyến nghị).
- Hiểu vì sao transport SSE bị ngừng khuyến nghị để nhường cho stdio và Streamable HTTP.
- Tạo tool mà MCP client gọi được.
- Gỡ lỗi server bằng MCP Inspector.
- Tích hợp server stdio với VS Code và Claude.
Transport stdio đơn giản hơn, an toàn hơn và hiệu năng tốt hơn so với cách SSE đã ngừng khuyến nghị. Đây là transport được khuyến nghị cho phần lớn MCP server theo đặc tả 2025-06-18.
Bài thực hành: kiểm thử server stdio
Đã xây xong server stdio, hãy kiểm thử để chắc nó hoạt động đúng.
Điều kiện cần
-
Đảm bảo đã cài MCP Inspector:
bashnpm install -g @modelcontextprotocol/inspector -
Code server đã được lưu (ví dụ
server.py).
Kiểm thử bằng Inspector
-
Khởi động Inspector cùng server:
bashnpx @modelcontextprotocol/inspector python server.py -
Mở giao diện web: Inspector mở cửa sổ trình duyệt hiển thị capability của server.
-
Thử các tool: thử
get_greetingvới nhiều tên khác nhau, thửcalculate_sumvới nhiều số, gọiget_server_infođể xem metadata của server. -
Theo dõi giao tiếp: Inspector hiển thị các thông điệp JSON-RPC trao đổi giữa client và server.
Kết quả mong đợi
Khi server khởi động đúng, bạn sẽ thấy:
- Capability của server được liệt kê trong Inspector
- Các tool sẵn sàng để thử
- Trao đổi thông điệp JSON-RPC thành công
- Phản hồi của tool hiển thị trên giao diện
Lỗi thường gặp và cách xử lý
Server không khởi động:
- Kiểm tra đã cài đủ dependency:
pip install mcp - Kiểm tra cú pháp và thụt lề Python
- Xem thông báo lỗi trên console
Tool không xuất hiện:
- Đảm bảo có decorator
@server.tool() - Kiểm tra các hàm tool được định nghĩa trước
main() - Kiểm tra server được cấu hình đúng
Lỗi kết nối:
- Đảm bảo server dùng transport stdio đúng cách
- Kiểm tra không có tiến trình nào khác gây nhiễu
- Kiểm tra cú pháp lệnh Inspector
Bài tập
Hãy mở rộng server với nhiều capability hơn. Ví dụ, xem trang này để thêm một tool gọi API. Bạn tự quyết server trông thế nào. Chúc vui!
Lời giải: solution, một lời giải khả dĩ với code chạy được.
Điểm chính
- Transport stdio là cơ chế được khuyến nghị cho MCP server local.
- Transport stdio cho phép MCP server và client giao tiếp liền mạch qua luồng standard input và output.
- Bạn có thể dùng cả Inspector lẫn Visual Studio Code để dùng trực tiếp server stdio, giúp gỡ lỗi và tích hợp dễ dàng.
Mẫu code
Bước tiếp theo
Đã biết xây MCP server với transport stdio, bạn có thể tìm hiểu các chủ đề nâng cao hơn:
- Tiếp theo: HTTP streaming với MCP (Streamable HTTP), cơ chế truyền tải được hỗ trợ còn lại cho remote server.
- Nâng cao: Best practice bảo mật MCP.
- Production: Chiến lược triển khai, triển khai (deploy) server cho môi trường production.
Tài liệu thêm
- SSE
- MCP Specification 2026-07-28: đặc tả hiện tại
- MCP SDK Documentation: tài liệu SDK cho mọi ngôn ngữ
- Community Examples: thêm ví dụ server từ cộng đồng
Nguồn
- Dịch và biên tập từ microsoft/mcp-for-beginners · 03-GettingStarted/05-stdio-server/README.md, giấy phép MIT.