Xin chào, mình là Minh — một lập trình viên backend tại TP.HCM. Hôm nay mình muốn chia sẻ với các bạn một bài hướng dẫn thực chiến về cách sử dụng MCP (Model Context Protocol) để gọi công cụ bên ngoài từ Claude Code. Mình đã dành hơn 3 tháng để nghiên cứu và triển khai giải pháp này cho dự án AI của công ty, và trong quá trình đó đã gặp rất nhiều "坑" (lỗi vặt) mà mình sẽ chia sẻ chi tiết ngay sau đây.

Bài viết này dành cho:

MCP là gì? Tại sao cần dùng MCP?

Trước khi đi vào code, mình muốn giải thích đơn giản nhất có thể. Các bạn hình dung MCP giống như một "phiên dịch viên" giữa Claude và các công cụ bên ngoài như database, file system, hay API của bên thứ ba.

Vấn đề cũ: Claude chỉ có thể trả lời dựa trên kiến thức đã được train. Nếu bạn hỏi "Hôm nay trời mưa không?", Claude sẽ không biết vì nó không có internet.

Giải pháp MCP: Cho phép Claude "gọi điện" cho các công cụ bên ngoài để lấy thông tin thực tế, rồi trả lời bạn dựa trên dữ liệu đó.

Chuẩn bị môi trường

Bước 1: Đăng ký tài khoản HolySheep AI

Đầu tiên, các bạn cần có API key. Mình khuyên dùng HolySheep AI vì nhiều lý do:

Gợi ý ảnh: Chụp màn hình trang đăng ký HolySheep AI với phần hiển thị tín dụng miễn phí

Bước 2: Cài đặt Claude Code CLI

# Cài đặt qua npm (yêu cầu Node.js 18+)
npm install -g @anthropic-ai/claude-code

Kiểm tra phiên bản

claude --version

Đăng nhập với API key của bạn

claude login

Bước 3: Cài đặt SDK MCP

# Tạo thư mục project mới
mkdir mcp-tool-demo && cd mcp-tool-demo

Khởi tạo npm project

npm init -y

Cài đặt các dependency cần thiết

npm install @modelcontextprotocol/sdk axios dotenv

Triển khai MCP Server đơn giản

Bây giờ mình sẽ hướng dẫn các bạn tạo một MCP server cơ bản. Mình sẽ tạo một server đơn giản để demo cách Claude có thể gọi các công cụ.

Tạo file cấu hình MCP

Đầu tiên, tạo file mcp.json trong thư mục project:

{
  "mcpServers": {
    "weather-tool": {
      "command": "node",
      "args": ["./weather-server.js"],
      "env": {
        "API_KEY": "your-weather-api-key"
      }
    }
  }
}

Tạo MCP Server với HolySheep AI

Đây là phần quan trọng nhất. Mình sẽ tạo một server hoàn chỉnh sử dụng API của HolySheep AI:

// weather-server.js
const { Server } = require('@modelcontextprotocol/sdk');
const axios = require('axios');
require('dotenv').config();

// Khởi tạo MCP Server
const server = new Server(
  {
    name: 'weather-mcp-server',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {}, // Bật tính năng tool use
    },
  }
);

// Định nghĩa các công cụ (tools) có thể gọi
server.setRequestHandler('tools/list', async () => {
  return {
    tools: [
      {
        name: 'get_weather',
        description: 'Lấy thông tin thời tiết của một thành phố',
        inputSchema: {
          type: 'object',
          properties: {
            city: {
              type: 'string',
              description: 'Tên thành phố (VD: Hanoi, HoChiMinh)',
            },
            unit: {
              type: 'string',
              enum: ['celsius', 'fahrenheit'],
              description: 'Đơn vị nhiệt độ',
              default: 'celsius',
            },
          },
          required: ['city'],
        },
      },
      {
        name: 'analyze_weather_ai',
        description: 'Dùng AI để phân tích thời tiết và đưa ra lời khuyên',
        inputSchema: {
          type: 'object',
          properties: {
            weather_data: {
              type: 'string',
              description: 'Dữ liệu thời tiết JSON',
            },
            activity: {
              type: 'string',
              description: 'Hoạt động dự định (VD: picnic, leo núi)',
            },
          },
          required: ['weather_data'],
        },
      },
    ],
  };
});

// Xử lý khi Claude gọi tool
server.setRequestHandler('tools/call', async (request) => {
  const { name, arguments: args } = request.params;

  try {
    switch (name) {
      case 'get_weather':
        return await handleGetWeather(args);
      case 'analyze_weather_ai':
        return await handleAnalyzeWeather(args);
      default:
        throw new Error(Unknown tool: ${name});
    }
  } catch (error) {
    return {
      content: [
        {
          type: 'text',
          text: Lỗi: ${error.message},
        },
      ],
      isError: true,
    };
  }
});

// Hàm lấy thời tiết (mock API)
async function handleGetWeather(args) {
  // Trong thực tế, gọi API thời tiết ở đây
  const mockWeatherData = {
    city: args.city,
    temperature: 28,
    humidity: 75,
    condition: 'partly_cloudy',
    wind_speed: 15,
    timestamp: new Date().toISOString(),
  };

  return {
    content: [
      {
        type: 'text',
        text: JSON.stringify(mockWeatherData, null, 2),
      },
    ],
  };
}

// Hàm phân tích thời tiết bằng AI
async function handleAnalyzeWeather(args) {
  const HOLYSHEEP_API_KEY = process.env.HOLYSHEEP_API_KEY || 'YOUR_HOLYSHEEP_API_KEY';
  
  try {
    const response = await axios.post(
      'https://api.holysheep.ai/v1/chat/completions',
      {
        model: 'claude-sonnet-4-20250514',
        messages: [
          {
            role: 'system',
            content: 'Bạn là chuyên gia tư vấn hoạt động ngoài trời. Phân tích thời tiết và đưa ra lời khuyên cụ thể.',
          },
          {
            role: 'user',
            content: Phân tích thời tiết sau và đưa ra lời khuyên cho hoạt động "${args.activity}":\n${args.weather_data},
          },
        ],
        max_tokens: 500,
        temperature: 0.7,
      },
      {
        headers: {
          'Authorization': Bearer ${HOLYSHEEP_API_KEY},
          'Content-Type': 'application/json',
        },
      }
    );

    const advice = response.data.choices[0].message.content;

    return {
      content: [
        {
          type: 'text',
          text: advice,
        },
      ],
    };
  } catch (error) {
    // Xử lý lỗi chi tiết
    if (error.response) {
      console.error('HolySheep API Error:', error.response.data);
      throw new Error(API Error: ${error.response.data.error?.message || 'Unknown error'});
    }
    throw error;
  }
}

// Khởi chạy server
async function main() {
  const transport = await server.connect();
  console.log('MCP Weather Server đang chạy...');
}

main().catch(console.error);

Client Python kết nối Claude Code

Phần này mình sẽ hướng dẫn tạo một client Python để giao tiếp với Claude thông qua MCP:

# client_example.py
import asyncio
import json
from mcp import ClientSession, StdioServerParameters
from openai import OpenAI

Cấu hình HolySheep AI

HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Thay bằng key của bạn BASE_URL = "https://api.holysheep.ai/v1"

Khởi tạo client OpenAI-compatible

client = OpenAI( api_key=HOLYSHEEP_API_KEY, base_url=BASE_URL, )

Cấu hình MCP Server

server_params = StdioServerParameters( command="node", args=["./weather-server.js"], env={ "HOLYSHEEP_API_KEY": HOLYSHEEP_API_KEY, "NODE_ENV": "production" } ) async def main(): print("=" * 50) print("MCP Tool Use Demo - Claude Code Integration") print("=" * 50) # Kết nối đến MCP Server async with ClientSession(server_params) as session: # Khởi tạo kết nối await session.initialize() # Liệt kê các tools có sẵn print("\n📋 Các công cụ khả dụng:") tools = await session.list_tools() for i, tool in enumerate(tools.tools, 1): print(f" {i}. {tool.name}: {tool.description}") # Demo: Gọi tool get_weather print("\n🔍 Đang lấy thông tin thời tiết...") weather_result = await session.call_tool( "get_weather", {"city": "Ho Chi Minh City", "unit": "celsius"} ) weather_data = weather_result.content[0].text print(f"Kết quả: {weather_data}") # Demo: Gọi tool phân tích với AI print("\n🤖 Đang phân tích bằng AI...") analysis_result = await session.call_tool( "analyze_weather_ai", { "weather_data": weather_data, "activity": "chụp ảnh cảnh quan" } ) analysis = analysis_result.content[0].text print(f"Phân tích: {analysis}") if __name__ == "__main__": asyncio.run(main())

So sánh chi phí khi dùng HolySheep AI

Đây là phần mình rất quan tâm khi triển khai cho doanh nghiệp. Bảng so sánh chi phí 2026/MTok:

Với tỷ giá ¥1 = $1, HolySheep AI mang lại tiết kiệm 85%+ so với việc dùng API gốc từ OpenAI hay Anthropic. Đặc biệt, HolySheep còn hỗ trợ WeChat/Alipay — rất thuận tiện cho người dùng Việt Nam.

Xử lý Tool Call nâng cao

Trong thực tế, các bạn sẽ cần xử lý nhiều tool phức tạp hơn. Đây là pattern mình đã áp dụng thành công:

# advanced_client.py
import asyncio
import json
from typing import Any, Dict, List
from mcp import ClientSession, StdioServerParameters

class ToolManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.session = None
        self.tool_cache = {}
    
    async def connect(self, server_params: StdioServerParameters):
        """Kết nối đến MCP Server với retry logic"""
        max_retries = 3
        for attempt in range(max_retries):
            try:
                self.session = ClientSession(server_params)
                await self.session.initialize()
                # Cache tools sau khi kết nối thành công
                await self.refresh_tool_cache()
                print("✅ Kết nối MCP thành công")
                return True
            except Exception as e:
                print(f"⚠️ Lần thử {attempt + 1}/{max_retries} thất bại: {e}")
                if attempt == max_retries - 1:
                    raise
                await asyncio.sleep(2 ** attempt)  # Exponential backoff
    
    async def refresh_tool_cache(self):
        """Cập nhật cache các tool có sẵn"""
        tools = await self.session.list_tools()
        self.tool_cache = {
            tool.name: tool.inputSchema 
            for tool in tools.tools
        }
        print(f"📦 Đã cache {len(self.tool_cache)} tools")
    
    async def call_tool_safe(
        self, 
        tool_name: str, 
        arguments: Dict[str, Any],
        timeout: int = 30
    ) -> str:
        """Gọi tool với error handling và timeout"""
        if tool_name not in self.tool_cache:
            raise ValueError(f"Tool '{tool_name}' không tồn tại")
        
        try:
            # Thiết lập timeout
            result = await asyncio.wait_for(
                self.session.call_tool(tool_name, arguments),
                timeout=timeout
            )
            
            if hasattr(result, 'isError') and result.isError:
                raise RuntimeError(f"Tool trả về lỗi: {result.content}")
            
            return result.content[0].text
            
        except asyncio.TimeoutError:
            raise TimeoutError(f"Tool '{tool_name}' vượt quá timeout {timeout}s")
        except Exception as e:
            raise RuntimeError(f"Lỗi khi gọi tool '{tool_name}': {str(e)}")
    
    async def batch_call_tools(
        self, 
        calls: List[Dict[str, Any]]
    ) -> List[Dict[str, Any]]:
        """Gọi nhiều tool song song (parallel execution)"""
        tasks = [
            self.call_tool_safe(call['name'], call.get('arguments', {}))
            for call in calls
        ]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        return [
            {
                'tool': calls[i]['name'],
                'result': str(r) if isinstance(r, Exception) else r,
                'success': not isinstance(r, Exception)
            }
            for i, r in enumerate(results)
        ]

async def main():
    manager = ToolManager("YOUR_HOLYSHEEP_API_KEY")
    
    server_params = StdioServerParameters(
        command="node",
        args=["./weather-server.js"]
    )
    
    await manager.connect(server_params)
    
    # Demo gọi nhiều tool song song
    batch_results = await manager.batch_call_tools([
        {"name": "get_weather", "arguments": {"city": "Hanoi"}},
        {"name": "get_weather", "arguments": {"city": "Da Nang"}},
    ])
    
    print("\n📊 Kết quả batch call:")
    for result in batch_results:
        print(f"  {result['tool']}: {'✅' if result['success'] else '❌'}")

if __name__ == "__main__":
    asyncio.run(main())

Lỗi thường gặp và cách khắc phục

Trong quá trình triển khai, mình đã gặp rất nhiều lỗi. Sau đây là 5 lỗi phổ biến nhất và cách khắc phục:

1. Lỗi "Connection refused" khi khởi động MCP Server

Nguyên nhân: Server chưa được khởi chạy hoặc port bị chiếm dụng.

# Cách khắc phục:

1. Kiểm tra port đang sử dụng

lsof -i :3000

2. Kill process chiếm port (thay 3000 bằng port của bạn)

kill -9 $(lsof -t -i:3000)

3. Khởi động lại server

node weather-server.js

4. Hoặc sử dụng script khởi động an toàn

const checkAndStart = async () => { try { const response = await fetch('http://localhost:3000/health'); if (response.ok) { console.log('Server đã chạy, không cần khởi động lại'); } } catch { console.log('Khởi động server...'); // Thêm logic khởi động ở đây } };

2. Lỗi "401 Unauthorized" từ HolySheep API

Nguyên nhân: API key không đúng hoặc chưa được set đúng biến môi trường.

# Cách khắc phục:

1. Kiểm tra file .env

cat .env

2. Đảm bảo format đúng

HOLYSHEEP_API_KEY=sk-your-key-here

3. Load lại biến môi trường trong code

require('dotenv').config({ override: true }); // 4. Validate key trước khi sử dụng const validateApiKey = (key) => { if (!key || key === 'YOUR_HOLYSHEEP_API_KEY') { throw new Error('Vui lòng set HOLYSHEEP_API_KEY trong file .env'); } if (!key.startsWith('sk-')) { throw new Error('API key không hợp lệ. Key phải bắt đầu bằng "sk-"'); } return true; }; // 5. Sử dụng key với error handling const apiKey = process.env.HOLYSHEEP_API_KEY; validateApiKey(apiKey);

3. Lỗi "Tool timeout exceeded"

Nguyên nhân: Request mất quá lâu để xử lý, thường do network hoặc server bận.

# Cách khắc phục:

1. Thêm timeout và retry logic

const axios = require('axios'); const callWithRetry = async (url, data, options = {}) => { const { maxRetries = 3, timeout = 30000, retryDelay = 1000 } = options; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await axios.post(url, data, { timeout, headers: { 'Authorization': Bearer ${process.env.HOLYSHEEP_API_KEY} } }); return response.data; } catch (error) { console.log(Attempt ${attempt}/${maxRetries} failed: ${error.message}); if (attempt === maxRetries) { throw new Error(Failed after ${maxRetries} attempts: ${error.message}); } // Exponential backoff await new Promise(r => setTimeout(r, retryDelay * Math.pow(2, attempt - 1))); } } }; // 2. Sử dụng trong tool handler server.setRequestHandler('tools/call', async (request) => { try { return await callWithRetry( 'https://api.holysheep.ai/v1/chat/completions', { /* request data */ }, { timeout: 30000, maxRetries: 3 } ); } catch (error) { return { content: [{ type: 'text', text: Lỗi: ${error.message} }], isError: true }; } });

4. Lỗi "Invalid JSON schema" khi định nghĩa tool

Nguyên nhân: Schema không đúng format theo MCP specification.

# Cách khắc phục - Đảm bảo schema đúng format:
{
  "name": "correctly_defined_tool",
  "description": "Mô tả tool ngắn gọn",
  "inputSchema": {
    "type": "object",
    "properties": {
      "param_name": {
        "type": "string",  // string, number, boolean, array, object
        "description": "Mô tả tham số"
      },
      "optional_param": {
        "type": "integer",
        "description": "Tham số tùy chọn",
        "default": 10
      }
    },
    "required": ["param_name"]  // Chỉ tham số bắt buộc
  }
}

// Validation function
const validateToolSchema = (schema) => {
  if (!schema.inputSchema || schema.inputSchema.type !== 'object') {
    throw new Error('inputSchema phải có type: "object"');
  }
  if (!schema.inputSchema.properties) {
    throw new Error('inputSchema phải có properties');
  }
  return true;
};

5. Lỗi "CORS policy" khi test local

Nguyên nhân: Browser chặn request từ frontend đến API.

# Cách khắc phục:

1. Thêm CORS headers vào server

const cors = require('cors'); const server = new Server( { name: 'mcp-server', version: '1.0.0' }, { capabilities: { tools: {} } } ); // Middleware CORS đơn giản const corsMiddleware = async (req, res, next) => { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); if (req.method === 'OPTIONS') { return res.status(200).end(); } next(); }; // 2. Hoặc sử dụng proxy server // backend/proxy.js const express = require('express'); const axios = require('axios'); const app = express(); app.use(express.json()); app.use(cors()); app.post('/api/mcp', async (req, res) => { try { const response = await axios.post( 'https://api.holysheep.ai/v1/chat/completions', req.body, { headers: { 'Authorization': Bearer ${process.env.HOLYSHEEP_API_KEY}, 'Content-Type': 'application/json' } } ); res.json(response.data); } catch (error) { res.status(500).json({ error: error.message }); } }); app.listen(3001, () => console.log('Proxy chạy tại port 3001'));

Kết luận

Qua bài viết này, mình đã hướng dẫn các bạn:

MCP là một protocol rất mạnh mẽ và đang trở thành standard cho việc kết nối AI models với external tools. Mình khuyên các bạn nên bắt đầu với HolySheep AI để tiết kiệm chi phí (85%+ so với API gốc) trong khi vẫn đạt được hiệu suất cao với độ trễ <50ms.

Nếu các bạn có câu hỏi hoặc gặp lỗi khác, hãy để lại comment bên dưới nhé!

👉 Đăng ký HolySheep AI — nhận tín dụng miễn phí khi đăng ký