Xây dựng máy chủ MCP cho trí nhớ AI dựa trên Git: Bài học từ ShadowGit
Giới thiệu
Trong thế giới phát triển phần mềm, việc quản lý mã nguồn là một thách thức lớn, đặc biệt khi làm việc với trí tuệ nhân tạo (AI). Mỗi lần bắt đầu một cuộc trò chuyện mới với Claude, bạn lại phải dán toàn bộ mã nguồn của mình. AI không nhớ những gì bạn đã làm hôm qua, các giải pháp đã thất bại, hay điều gì thực sự đã sửa được lỗi trong tuần trước. Để giải quyết vấn đề này, tôi đã xây dựng ShadowGit: một máy chủ MCP với các bản sao tự động của mã nguồn, cho phép AI truy cập lịch sử tìm kiếm. Dưới đây là những gì tôi đã học được.
Vấn đề
Khi bạn bắt đầu một dự án mới hoặc một cuộc trò chuyện mới với AI, việc nhập lại mã nguồn là không hiệu quả. Điều này không chỉ làm mất thời gian mà còn có thể dẫn đến việc AI không thể cung cấp giải pháp hợp lý do thiếu thông tin lịch sử.
Cách tiếp cận kỹ thuật
Hệ thống tự động cam kết
Máy chủ MCP sử dụng một bộ điều phối để kiểm tra sự thay đổi mỗi 5 giây (có thể cấu hình):
typescript
// Từ polling-orchestrator.ts
private pollingInterval: number = 5000; // Mặc định 5 giây
const scheduleNextPoll = async () => {
if (!this.isPollingInProgress) {
await this.pollAllRepositories();
}
this.pollingTimer = setTimeout(scheduleNextPoll, this.pollingInterval);
};
Điều này tạo ra một kho lưu trữ .shadowgit.git song song với kho chính của bạn - đây là một kho git thực sự, không chỉ là một thư mục:
typescript
// Tin nhắn cam kết thông minh, không chỉ là dấu thời gian
generateMessage(repoPath, shadowgitDir, changedFiles, totalLines, isAISession) {
const timestamp = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
if (isAISession) {
return `🤖 Thay đổi hỗ trợ AI @ ${timestamp}
🔧 Phiên làm việc AI được phát hiện
📝 Các loại: ${fileTypes.join(', ')}
📏 Tác động: ${totalLines} dòng đã thay đổi`;
}
// Các cam kết thông thường có định dạng khác
}
Triển khai máy chủ MCP
Máy chủ MCP cung cấp các thao tác git thông qua một giao thức rõ ràng:
typescript
{
name: 'git_command',
description: 'Thực hiện một lệnh git chỉ đọc trên kho ShadowGit',
inputSchema: {
type: 'object',
properties: {
repo: { type: 'string', description: 'Tên kho' },
command: { type: 'string', description: 'Lệnh git để thực hiện' }
},
required: ['repo', 'command']
}
}
Bây giờ Claude có thể chạy:
git_command({repo: "my-app", command: "diff HEAD~5"})- Xem các thay đổi gần đâygit_command({repo: "my-app", command: "log --grep='auth'"})- Tìm kiếm các cam kếtgit_command({repo: "my-app", command: "show HEAD~10:src/file.ts"})- Lấy các phiên bản cũ
Xác thực lệnh git
GitExecutor xác thực mỗi lệnh để đảm bảo an toàn:
typescript
// An ninh: Chỉ cho phép các lệnh chỉ đọc an toàn
private readonly ALLOWED_COMMANDS = [
'log', 'diff', 'show', 'status', 'ls-files', 'blame', 'shortlog'
];
private readonly BLOCKED_ARGS = [
'--git-dir', '--work-tree', '-C', // Ngăn chặn truy cập không hợp lệ
'push', 'pull', 'fetch', 'merge', 'rebase' // Không sửa đổi
];
Quản lý phiên làm việc
Khi AI làm việc với mã, bạn không muốn có các cam kết phân mảnh mỗi 5 giây. Hệ thống phiên làm việc rất tinh tế:
typescript
// Công cụ MCP cho quản lý phiên làm việc
{
name: 'start_session',
description: 'Bắt đầu một phiên làm việc. PHẢI được gọi TRƯỚC khi thực hiện thay đổi',
inputSchema: {
properties: {
repo: { type: 'string' },
description: { type: 'string' }
}
}
}
// Bộ xử lý phiên giao tiếp với ứng dụng ShadowGit
async startSession(args) {
const sessionId = await this.sessionClient.startSession({
repoPath,
aiTool: 'MCP Client',
description: args.description
});
// ShadowGit tạm dừng các cam kết tự động cho kho này
// Trả về ID phiên để sử dụng sau
return `Phiên làm việc đã bắt đầu: ${sessionId}`;
}
Quản lý phiên với SQLite
SessionManager theo dõi các phiên làm việc đang hoạt động:
typescript
// Lưu trữ phiên với thời gian hết hạn tự động
class SessionManager {
private readonly SESSION_EXPIRY_MS = 60 * 60 * 1000; // 1 giờ
async createSession(repoPath, tool, description) {
const session = {
id: uuidv4(),
repoPath,
tool,
startTime: Date.now(),
expiresAt: Date.now() + this.SESSION_EXPIRY_MS
};
// Lưu trữ trong SQLite để đảm bảo tính bền vững
}
}
Khám phá kiến trúc
Thiết kế hai thành phần
- Ứng dụng ShadowGit (Electron) - Xử lý theo dõi tệp, cam kết tự động, giao diện người dùng
- Máy chủ MCP (Node.js) - Cung cấp giao diện AI cho lịch sử git
Chúng giao tiếp qua một API HTTP cục bộ trên cổng 45682:
typescript
// API phiên chạy cục bộ
const SESSION_API_PORT = 45682;
// Máy chủ MCP kiểm tra xem API phiên có đang chạy không
const response = await fetch(`http://localhost:${SESSION_API_PORT}/api/health`);
Quyết định cam kết thông minh
Không phải tất cả các thay đổi tệp đều cần phải cam kết. CommitDecisionEngine rất tinh vi:
typescript
shouldCommit(repoPath: string, stats: ChangeStats): boolean {
const timeSinceLastCommit = Date.now() - this.lastCommitTime;
// Trong các phiên AI, áp dụng quy tắc khác nhau
if (this.hasActiveSession(repoPath)) {
return false; // Để AI kiểm soát các cam kết qua checkpoint()
}
// Nhóm thông minh cho công việc thông thường
if (stats.totalLines > 100 || timeSinceLastCommit > 30000) {
return true;
}
// Quy tắc theo loại tệp...
}
Kết quả
Triển khai kỹ thuật hoạt động rất tốt. Một số số liệu thực tế từ việc sử dụng:
- Giảm token: ít token hơn khi AI sử dụng
git diffso với việc đọc tệp - Tốc độ gỡ lỗi: Tìm các thay đổi gây lỗi mất vài giây, không cần nhiều lần nhắc
- Độ sâu lịch sử: Các kho điển hình tích lũy từ 200-500 cam kết mỗi ngày
Những gì tôi đã học được
Sự thật khó khăn về công cụ phát triển
-
Giá trị của mặc định đơn giản - Thời gian 5 giây cảm thấy tức thì, nhưng 15 giây lại cảm thấy chậm chạp. Cảm nhận của người dùng là tất cả.
-
Chiến lược mã nguồn mở - Phát hành máy chủ MCP mã nguồn mở. Điều này đã giết chết việc kiếm tiền trực tiếp nhưng tạo ra goodwill và sự chấp nhận.
-
Tích hợp AI là tương lai - Giao thức MCP rất mạnh mẽ. Mọi công cụ phát triển nên xem xét các giao diện ưu tiên AI.
Những hiểu biết kỹ thuật
Việc xây dựng này đã dạy tôi:
- Git như một cơ sở dữ liệu - Sử dụng git cho các truy vấn tạm thời là cực kỳ mạnh mẽ
- TypeScript ở khắp mọi nơi - Đảm bảo loại đầy đủ từ Electron đến MCP giúp việc tái cấu trúc trở nên dễ dàng
- Độ phức tạp của phiên - Quản lý trạng thái giữa hai quy trình (Electron + MCP) yêu cầu thiết kế cẩn thận
Những gì thực sự quan trọng
Sau khi xây dựng điều này, những bài học chính:
- Hiệu suất > Tính năng - Các cam kết 5 giây tốt hơn cam kết 15 giây với thông điệp tốt hơn
- An toàn là ưu tiên hàng đầu - Chặn các thao tác viết git là không thể thương lượng
- Chỉ cục bộ - Các nhà phát triển sẽ không tin tưởng các công cụ tải lên mã
Mã nguồn mở
Máy chủ MCP có sẵn tại: https://github.com/blade47/shadowgit-mcp
Triển khai thực tế là ~2000 dòng TypeScript trên nhiều mô-đun. Kiến trúc hỗ trợ:
- Nhiều kho lưu trữ
- Các phiên đồng thời
- Các thao tác git an toàn
- Dọn dẹp tự động
Tôi có xây dựng lại không?
Có, nhưng tôi sẽ:
- Bắt đầu chỉ với MCP - Ứng dụng Electron thêm độ phức tạp
- Tập trung vào số liệu - Theo dõi tiết kiệm token, giảm thời gian gỡ lỗi
Những điểm chính
- Giao thức MCP đã sẵn sàng cho sản xuất - Đủ mạnh mẽ cho các ứng dụng thực tế
- Git + AI là mạnh mẽ - Ngữ cảnh lịch sử cải thiện đáng kể hỗ trợ AI
- Độ phức tạp giết chết sự chấp nhận - Kiến trúc đơn giản hơn sẽ tốt hơn
- Ưu tiên cục bộ - Các nhà phát triển đánh giá cao sự riêng tư hơn là tính năng
Mã được cấp phép MIT. Đôi khi kết quả tốt nhất không phải là một doanh nghiệp, mà là một công cụ giúp cuộc sống của một vài nhà phát triển dễ dàng hơn.
Công nghệ sử dụng: TypeScript, Electron, MCP SDK, SQLite, Node.js
Thẻ: #mcp #claude #git #ai #typescript #electron