Tracks
Model Context Protocol (MCP) là một tiêu chuẩn mở cho phép các mô hình ngôn ngữ lớn tương tác động với công cụ, cơ sở dữ liệu và API bên ngoài thông qua một giao diện tiêu chuẩn hóa.
Trong bài viết này, tôi sẽ hướng dẫn bạn xây dựng một máy chủ đánh giá PR chạy bằng MCP tích hợp với Claude Desktop. Máy chủ này sẽ:
- Lấy chi tiết PR và các tệp thay đổi từ GitHub
- Phân tích thay đổi mã bằng ứng dụng Claude Desktop
- Tạo tóm tắt và gợi ý đánh giá PR
- Lưu đánh giá vào Notion
Chúng ta sẽ sử dụng Model Context Protocol (MCP) để tiêu chuẩn hóa giao tiếp giữa máy chủ và Claude Desktop, giúp hệ thống mô-đun và có khả năng mở rộng.
Chúng tôi cập nhật cho độc giả những thông tin mới nhất về AI qua The Median, bản tin miễn phí mỗi thứ Sáu tóm lược các câu chuyện nổi bật trong tuần. Đăng ký để luôn nắm bắt chỉ trong vài phút mỗi tuần:
Model Context Protocol (MCP) là gì?
Model Context Protocol (MCP) là một tiêu chuẩn mở do Anthropic phát triển để cho phép tích hợp dễ dàng và tiêu chuẩn hóa giữa các mô hình AI và công cụ bên ngoài. Nó hoạt động như một bộ kết nối phổ quát, cho phép các mô hình ngôn ngữ lớn (LLM) tương tác động với API, cơ sở dữ liệu và các ứng dụng doanh nghiệp.
Ban đầu được xây dựng để cải thiện khả năng của Claude trong việc tương tác với hệ thống bên ngoài, Anthropic đã quyết định mở mã nguồn MCP vào đầu năm 2024 nhằm khuyến khích áp dụng rộng rãi trong ngành. Bằng cách công khai MCP, họ hướng tới việc tạo ra một khung giao tiếp tiêu chuẩn giữa AI và công cụ, giảm phụ thuộc vào tích hợp độc quyền và tăng tính mô-đun cũng như khả năng tương tác giữa các ứng dụng AI.
MCP tuân theo kiến trúc khách–máy chủ, trong đó:
- Các khách hàng MCP (ví dụ: Claude Desktop) yêu cầu thông tin và thực thi tác vụ.
- Máy chủ MCP cung cấp quyền truy cập vào công cụ và nguồn dữ liệu bên ngoài.
- Ứng dụng máy chủ lưu trữ dùng MCP để giao tiếp giữa mô hình và công cụ.

Nguồn: Model Context Protocol
Vì sao bạn nên dùng MCP cho dự án của mình:
- Tích hợp AI tiêu chuẩn hóa: MCP cung cấp một cách có cấu trúc để kết nối mô hình AI với công cụ.
- Linh hoạt: Cho phép chuyển đổi dễ dàng giữa các mô hình AI và nhà cung cấp khác nhau.
- Bảo mật: Giữ dữ liệu trong hạ tầng của bạn trong khi tương tác với AI.
- Khả năng mở rộng: MCP hỗ trợ nhiều phương thức truyền như stdio, WebSockets, HTTP SSE và UNIX sockets.
Tổng quan dự án demo MCP: Máy chủ đánh giá PR
Hệ thống đánh giá PR tự động hóa phân tích mã và ghi chép bằng Claude Desktop và Notion.
Quy trình tóm tắt như sau:
- Thiết lập môi trường: Nạp thông tin xác thực GitHub và Notion.
- Khởi tạo máy chủ: Khởi động máy chủ MCP để giao tiếp với Claude Desktop.
- Lấy dữ liệu PR: Truy xuất thay đổi và siêu dữ liệu PR từ GitHub.
- Phân tích mã: Claude Desktop trực tiếp phân tích thay đổi mã (không cần công cụ riêng).
- Ghi chép vào Notion: Lưu kết quả phân tích vào Notion để theo dõi.
Bước 1: Thiết lập môi trường
Trước khi bắt đầu, hãy đảm bảo bạn đã cài đặt Python 3.10+. Sau đó, chúng ta thiết lập môi trường và cài đặt trình quản lý gói uv. Trên Mac hoặc Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh # Mac/Linux
Trên Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Tiếp theo, tạo một thư mục dự án mới và khởi tạo bằng uv:
uv init pr_reviewer
cd pr_reviewer
Bây giờ chúng ta tạo và kích hoạt môi trường ảo. Trên Mac hoặc Linux:
uv venv
source .venv/bin/activate
Trên Windows:
.venv\Scripts\activate
Giờ hãy cài đặt các phụ thuộc cần thiết:
uv add "mcp[cli]" requests python-dotenv notion-client
Chúng ta sẽ dùng uv thay cho conda trong dự án này vì nó nhanh hơn, nhẹ hơn và tập trung vào quản lý gói Python. Tóm tắt những gì vừa làm:
- Thiết lập môi trường phát triển máy chủ MCP đánh giá PR GitHub bằng trình quản lý gói uv
- Khởi tạo thư mục dự án mới tên
pr_reviewervà chuyển vào đó. - Tạo môi trường ảo và kích hoạt để đảm bảo cài đặt gói được cách ly.
Bước 2: Cài đặt phụ thuộc
Sau khi thiết lập môi trường, chúng ta cấu hình phụ thuộc với khóa API và các yêu cầu khác. Tạo tệp requirements.txt và thêm các gói Python sau:
# Core dependencies for PR Analyzer
requests>=2.31.0 # For GitHub API calls
python-dotenv>=1.0.0 # For environment variables
mcp[cli]>=1.4.0 # For MCP server functionality
notion-client>=2.3.0 # For Notion integration
# Optional: Pin versions for stability
# requests==2.31.0
# python-dotenv==1.0.0
# mcp[cli]==1.4.0
# notion-client==2.3.0
Tệp requirements.txt chứa tất cả phụ thuộc cốt lõi cần cho dự án. Để cài đặt, chạy một trong các lệnh sau (ưu tiên dùng uv nếu bạn đã cài trước đó).
uv pip install -r requirements.txt
pip install -r requirements.txt
Giờ đây, môi trường của bạn đã có đầy đủ các phụ thuộc cần thiết.
Bước 3: Thiết lập biến môi trường
Tiếp theo, tạo tệp .env chứa tất cả khóa và token cần thiết cho dự án này.
Tạo token GitHub
Để tạo token GitHub:
- Đăng nhập tài khoản GitHub và vào phần cài đặt.
- Đi tới developer settings → Personal Access Tokens.
- Nhấp Generate New Token và chọn phiên bản classic.
- Đặt tên cho token và bật các quyền sau:
- read:org
- read:repo_hook
- repo
- Nhấp Generate để tạo token.
- Sao chép và lưu trữ token an toàn, vì nó sẽ được dùng để xác thực trong các yêu cầu API.
Tích hợp Notion
- Đăng nhập vào trang tích hợp của Notion.
- Tạo một tích hợp mới và điền biểu mẫu. Giữ “type” là Internal và thêm nó vào workspace của bạn.

- Lưu tích hợp và sao chép liên kết của tích hợp (phần UUID ở cuối URL là Mã định danh duy nhất toàn cầu mà bạn cần ghi lại và dùng làm Notion Page ID).
https://www.notion.so/profile/integrations/internal/UUID
- Sau khi tạo tích hợp, nhấp vào nó, và trong phần cấu hình, sao chép Internal Integration Secret, đây sẽ là khóa API Notion của bạn.
Tạo tệp .env
Giờ hãy tạo tệp .env và thêm nội dung sau cùng với khóa API và token đã tạo ở trên.
GITHUB_TOKEN=your_github_token
NOTION_API_KEY=your_notion_api_key
NOTION_PAGE_ID=your_notion_page_id
Bước 4: Tích hợp GitHub
Hãy cấu hình mô-đun tích hợp GitHub để quản lý và truy xuất các thay đổi PR từ một kho GitHub.
Tạo tệp github_integration.py và viết đoạn mã sau (chúng ta sẽ giải thích bên dưới).
import os
import requests
import traceback
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
def fetch_pr_changes(repo_owner: str, repo_name: str, pr_number: int) -> list:
"""Fetch changes from a GitHub pull request.
Args:
repo_owner: The owner of the GitHub repository
repo_name: The name of the GitHub repository
pr_number: The number of the pull request to analyze
Returns:
A list of file changes with detailed information about each change
"""
print(f" Fetching PR changes for {repo_owner}/{repo_name}#{pr_number}")
# Fetch PR details
pr_url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/pulls/{pr_number}"
files_url = f"{pr_url}/files"
headers = {'Authorization': f'token {GITHUB_TOKEN}'}
try:
# Get PR metadata
pr_response = requests.get(pr_url, headers=headers)
pr_response.raise_for_status()
pr_data = pr_response.json()
# Get file changes
files_response = requests.get(files_url, headers=headers)
files_response.raise_for_status()
files_data = files_response.json()
# Combine PR metadata with file changes
changes = []
for file in files_data:
change = {
'filename': file['filename'],
'status': file['status'], # added, modified, removed
'additions': file['additions'],
'deletions': file['deletions'],
'changes': file['changes'],
'patch': file.get('patch', ''), # The actual diff
'raw_url': file.get('raw_url', ''),
'contents_url': file.get('contents_url', '')
}
changes.append(change)
# Add PR metadata
pr_info = {
'title': pr_data['title'],
'description': pr_data['body'],
'author': pr_data['user']['login'],
'created_at': pr_data['created_at'],
'updated_at': pr_data['updated_at'],
'state': pr_data['state'],
'total_changes': len(changes),
'changes': changes
}
print(f"Successfully fetched {len(changes)} changes")
return pr_info
except Exception as e:
print(f"Error fetching PR changes: {str(e)}")
traceback.print_exc()
return None
# Example usage for debugging
# pr_data = fetch_pr_changes('owner', 'repo', 1)
# print(pr_data)
Hàm fetch_pr_changes() truy xuất và trả về các thay đổi từ một pull request trên GitHub. Nó nhận ba tham số là repo_owner, repo_name và pr_number, và trả về danh sách có cấu trúc các thay đổi tệp cùng siêu dữ liệu PR.
Mã sử dụng thư viện requests để gửi các yêu cầu HTTP GET có xác thực, lấy cả siêu dữ liệu PR tổng quát và thay đổi ở cấp độ tệp:
- Yêu cầu API đầu tiên truy xuất thông tin cấp cao của PR, bao gồm tiêu đề, mô tả, tác giả, dấu thời gian và trạng thái hiện tại.
- Yêu cầu API thứ hai lấy chi tiết về từng tệp thay đổi trong PR, như tên tệp, trạng thái sửa đổi, số dòng thêm/bớt và URL để truy cập nội dung tệp.
Khi dữ liệu đã được lấy về, hàm cấu trúc và kết hợp siêu dữ liệu PR với các thay đổi tệp vào một dictionary. Các thay đổi tệp được lưu trong danh sách, mỗi mục chứa thông tin chi tiết về một tệp. Cấu trúc dữ liệu cuối cùng bao gồm tiêu đề PR, mô tả, tác giả, dấu thời gian, trạng thái, tổng số tệp thay đổi và phân tích chi tiết các sửa đổi.
Bước 5: Triển khai máy chủ MCP
Sau khi đã có đầy đủ phụ thuộc và hàm bổ trợ, chúng ta thiết lập máy chủ MCP. Tạo tệp pr_analyzer.py, tệp này sẽ:
- Khởi tạo một máy chủ MCP.
- Định nghĩa các công cụ để lấy chi tiết PR, phân tích mã và lưu kết quả vào Notion.
- Công khai các công cụ này cho Claude Desktop để tóm tắt, đưa ra phương án và hơn thế nữa.
Hãy thêm mã trước rồi giải thích sau
import sys
import os
import traceback
from typing import Any, List, Dict
from mcp.server.fastmcp import FastMCP
from github_integration import fetch_pr_changes
from notion_client import Client
from dotenv import load_dotenv
class PRAnalyzer:
def __init__(self):
# Load environment variables
load_dotenv()
# Initialize MCP Server
self.mcp = FastMCP("github_pr_analysis")
print("MCP Server initialized", file=sys.stderr)
# Initialize Notion client
self._init_notion()
# Register MCP tools
self._register_tools()
def _init_notion(self):
"""Initialize the Notion client with API key and page ID."""
try:
self.notion_api_key = os.getenv("NOTION_API_KEY")
self.notion_page_id = os.getenv("NOTION_PAGE_ID")
if not self.notion_api_key or not self.notion_page_id:
raise ValueError("Missing Notion API key or page ID in environment variables")
self.notion = Client(auth=self.notion_api_key)
print(f"Notion client initialized successfully", file=sys.stderr)
print(f"Using Notion page ID: {self.notion_page_id}", file=sys.stderr)
except Exception as e:
print(f"Error initializing Notion client: {str(e)}", file=sys.stderr)
traceback.print_exc(file=sys.stderr)
sys.exit(1)
def _register_tools(self):
"""Register MCP tools for PR analysis."""
@self.mcp.tool()
async def fetch_pr(repo_owner: str, repo_name: str, pr_number: int) -> Dict[str, Any]:
"""Fetch changes from a GitHub pull request."""
print(f"Fetching PR #{pr_number} from {repo_owner}/{repo_name}", file=sys.stderr)
try:
pr_info = fetch_pr_changes(repo_owner, repo_name, pr_number)
if pr_info is None:
print("No changes returned from fetch_pr_changes", file=sys.stderr)
return {}
print(f"Successfully fetched PR information", file=sys.stderr)
return pr_info
except Exception as e:
print(f"Error fetching PR: {str(e)}", file=sys.stderr)
traceback.print_exc(file=sys.stderr)
return {}
@self.mcp.tool()
async def create_notion_page(title: str, content: str) -> str:
"""Create a Notion page with PR analysis."""
print(f"Creating Notion page: {title}", file=sys.stderr)
try:
self.notion.pages.create(
parent={"type": "page_id", "page_id": self.notion_page_id},
properties={"title": {"title": [{"text": {"content": title}}]}},
children=[{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [{
"type": "text",
"text": {"content": content}
}]
}
}]
)
print(f"Notion page '{title}' created successfully!", file=sys.stderr)
return f"Notion page '{title}' created successfully!"
except Exception as e:
error_msg = f"Error creating Notion page: {str(e)}"
print(error_msg, file=sys.stderr)
traceback.print_exc(file=sys.stderr)
return error_msg
def run(self):
"""Start the MCP server."""
try:
print("Running MCP Server for GitHub PR Analysis...", file=sys.stderr)
self.mcp.run(transport="stdio")
except Exception as e:
print(f"Fatal Error in MCP Server: {str(e)}", file=sys.stderr)
traceback.print_exc(file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
analyzer = PRAnalyzer()
analyzer.run()
Đoạn mã trên thiết lập một máy chủ MCP để lấy thay đổi PR trên GitHub và lưu kết quả phân tích vào Notion. Cùng điểm qua các thành phần chính:
- Thiết lập môi trường và khởi tạo
- Mô-đun
dotenvnạp biến môi trường, đảm bảo truy cập an toàn khóa API và thông tin xác thực. - Sau đó lớp
PRAnalyzerkhởi tạo máy chủ MCP bằng hàmFastMCP()với têngithub_pr_analysisvà cho phép tương tác với ứng dụng Claude Desktop. - Khách hàng Notion cũng được thiết lập bằng gói notion-client, sử dụng khóa API Notion và page ID lưu trong tệp
.env. - Công cụ MCP: lấy thay đổi PR
- Hàm
fetch_pr()truy xuất siêu dữ liệu pull request từ GitHub bằng phương thứcfetch_pr_changes()trong tệpgithub_integration.py. Nếu thành công, nó trả về một dictionary chứa chi tiết PR. - Bạn có thể tự động hóa quy trình này bằng thư viện Webhooks tích hợp trong GitHub để bất kỳ PR mới nào tạo trên kho của bạn sẽ được máy chủ tự động xử lý.
- Công cụ MCP: tạo trang Notion
- Hàm
create_notion_page()tạo một trang Notion chứa kết quả phân tích PR. - Nó sử dụng Notion API để tạo trang mới trong workspace Notion được chỉ định.
- Chạy máy chủ
- Phương thức
run()khởi động máy chủ MCP bằng mcp.run(transport="stdio"), cho phép tương tác giữa Claude Desktop và các công cụ đánh giá PR.
Bước 6: Chạy máy chủ MCP
Khi đã có đầy đủ các phần mã, hãy chạy máy chủ bằng lệnh sau trong terminal:
python pr_analyzer.py


Khi máy chủ đã chạy, mở ứng dụng Claude Desktop, bạn sẽ thấy biểu tượng phích cắm (🔌) trong hộp nhập văn bản. Biểu tượng này cho biết có MCP trong môi trường Claude. Trong cùng hộp, bạn sẽ thấy biểu tượng giống chiếc búa (🔨) hiển thị tất cả MCP khả dụng như hình bên dưới.

Bây giờ, đưa liên kết tới PR bạn muốn phân tích và Claude sẽ lo phần còn lại.

Claude sẽ phân tích PR trước rồi cung cấp tóm tắt và đánh giá. Công cụ sẽ hỏi người dùng có muốn tải thông tin lên trang Notion hay không. Dù bạn có thể tự động hóa bước này, mã hiện tại cho phép bạn xem lại bản tóm tắt trước khi tạo trang Notion mới.

Trang Notion đã cập nhật trông như sau:

Kết luận
Máy chủ đánh giá PR dựa trên MCP của chúng tôi cải thiện phân tích mã và ghi chép, giúp quy trình review hiệu quả và có tổ chức hơn. Bằng cách sử dụng MCP, GitHub API và tích hợp Notion, hệ thống này hỗ trợ phân tích PR tự động, cộng tác dễ dàng và lưu trữ tài liệu có cấu trúc. Với cấu hình này, nhà phát triển có thể nhanh chóng lấy chi tiết PR, phân tích thay đổi mã bằng Claude và lưu insight vào Notion để tham khảo sau.
Để khám phá thêm các công cụ AI gần đây, tôi gợi ý các bài viết sau:
Tôi là Chuyên gia Google Developers trong lĩnh vực ML (Gen AI), Chuyên gia Kaggle 3x và Đại sứ Women Techmakers với hơn 3 năm kinh nghiệm trong ngành công nghệ. Tôi đồng sáng lập một startup công nghệ y tế vào năm 2020 và hiện đang theo học thạc sĩ khoa học máy tính tại Georgia Tech, chuyên sâu về học máy.
