Bỏ qua tới nội dung
Bài 5/11 · MCP cho người mới bắt đầu (Microsoft)

Server dùng transport stdio

Cách transport stdio hoạt động, các yêu cầu bắt buộc, xây MCP server stdio bằng Python, TypeScript, .NET, gỡ lỗi bằng Inspector và kết nối từ client.

Cơ bản@shine190412 phút đọc

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 stdout bất cứ thứ gì không phải thông điệp MCP hợp lệ.
  • Client KHÔNG ĐƯỢC ghi vào stdin của server bất cứ thứ gì không phải thông điệp MCP hợp lệ.
typescript
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 Server và StdioServerTransport từ 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 StdioServerTransport và kết nối server với nó, cho phép giao tiếp qua stdin/stdout.

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:

python
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:

  1. Import thư viện cần thiết: các thành phần MCP server và transport stdio.
  2. Tạo instance server: định nghĩa server cùng capability.
  3. Định nghĩa tool: thêm chức năng muốn cung cấp.
  4. Thiết lập transport: cấu hình giao tiếp stdio.
  5. 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

python
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

python
@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:

bash
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:

  1. Cài Inspector: npx @modelcontextprotocol/inspector
  2. Chạy Inspector và trỏ nó tới server của bạn
  3. 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:

  1. Cài Inspector:

    bash
    npx @modelcontextprotocol/inspector
    
  2. Chạy Inspector:

    bash
    npx @modelcontextprotocol/inspector python server.py
    
  3. 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:

  1. 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"
        }
      ]
    }
    
  2. Đặt breakpoint trong code server.

  3. 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 ra stdout vì 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

  1. 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"]
        }
      }
    }
    
  2. Khởi động lại Claude: đóng và mở lại Claude để nạp cấu hình server mới.

  3. 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:

typescript
#!/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

csharp
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

  1. Đảm bảo đã cài MCP Inspector:

    bash
    npm install -g @modelcontextprotocol/inspector
    
  2. Code server đã được lưu (ví dụ server.py).

Kiểm thử bằng Inspector

  1. Khởi động Inspector cùng server:

    bash
    npx @modelcontextprotocol/inspector python server.py
    
  2. Mở giao diện web: Inspector mở cửa sổ trình duyệt hiển thị capability của server.

  3. Thử các tool: thử get_greeting với nhiều tên khác nhau, thử calculate_sum với nhiều số, gọi get_server_info để xem metadata của server.

  4. 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:

Tài liệu thêm

Nguồn