0
0
Lập trình
Admin Team
Admin Teamtechmely

Xây dựng máy chủ MCP cho trí nhớ AI dựa trên Git

Đăng vào 8 tháng trước

• 7 phút đọc

Chủ đề:

KungFuTech

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 Copy
// 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 Copy
// 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 Copy
{
  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 đây
  • git_command({repo: "my-app", command: "log --grep='auth'"}) - Tìm kiếm các cam kết
  • git_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 Copy
// 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 Copy
// 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 Copy
// 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

  1. Ứng dụng ShadowGit (Electron) - Xử lý theo dõi tệp, cam kết tự động, giao diện người dùng
  2. 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 Copy
// 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 Copy
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 diff so 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

  1. 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ả.

  2. 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.

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

  1. Bắt đầu chỉ với MCP - Ứng dụng Electron thêm độ phức tạp
  2. 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

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào