·

Google Sheets MCP với OpenCode

Cài đặt Google Sheets MCP trong OpenCode để AI agent có thể đọc và ghi dữ liệu bảng tính ngay trong trình soạn thảo.

OpenCode là client MCP mã nguồn mở, hỗ trợ cả stdio và remote (HTTP) transport, và điểm khác biệt lớn nhất so với Claude Code là cách nó phân tách config theo layer — project và global — với cú pháp JSON hơi khác. Với Google Sheets MCP, sự khác biệt này quan trọng: bạn cần quyết định service account credentials nằm ở cấp nào, và điều đó ảnh hưởng trực tiếp đến việc một agent chạy trong OpenCode có "thấy" được sheet bạn mong đợi hay không. Bài này đi qua cài đặt, workflow đọc/ghi thực tế, và một ví dụ ứng dụng cụ thể: xây một requirements traceability matrix (ma trận truy vết yêu cầu) hoàn toàn bằng agent.

Cài Đặt và Kết Nối Google Sheets MCP với OpenCode

OpenCode đọc định nghĩa MCP server từ opencode.json (project-level, đặt ở root repo) hoặc ~/.config/opencode/opencode.json (global). Cả hai transport đều được hỗ trợ, khớp với hai lựa chọn thực tế cho Sheets MCP: một server stdio chạy local giữ credentials trên máy bạn, hoặc một server hosted như của Zapier/Composio chạy qua HTTP.

Cài server local (dùng lại mcp-google-sheets, server Python cộng đồng đã dùng ở bài trước):

uvx --from mcp-google-sheets mcp-google-sheets --help

Cấu hình project-level trong opencode.json ở root repo:

{
  "mcp": {
    "sheets": {
      "type": "local",
      "command": ["uvx", "--from", "mcp-google-sheets", "mcp-google-sheets"],
      "environment": {
        "SERVICE_ACCOUNT_PATH": "{env:SHEETS_SA_PATH}"
      }
    }
  }
}

Chú ý cú pháp {env:SHEETS_SA_PATH} — OpenCode expand biến môi trường theo cú pháp này, khác với ${VAR} bạn quen dùng ở Claude Code hay shell thường. Đây là lỗi phổ biến nhất khi người dùng chuyển từ Claude Code sang OpenCode: copy config cũ, giữ nguyên ${SHEETS_SA_PATH}, và OpenCode âm thầm không resolve được biến, server start với env var rỗng.

Nếu bạn muốn Sheets MCP khả dụng ở mọi project (giống cách hầu hết người dùng thật sự muốn — không ai muốn re-auth Google mỗi lần mở repo mới), đặt cấu hình tương tự vào ~/.config/opencode/opencode.json thay vì file project.

opencode mcp list

Mẹo: Chạy trực tiếp câu lệnh trong mảng command của opencode.json ngay tại shell trước khi debug trong OpenCode — nó tách được lỗi "OpenCode parse config sai" ra khỏi lỗi "server thực sự không start được", hai loại lỗi có thông báo khá giống nhau trong log OpenCode.

Đọc và Cập Nhật Dữ Liệu Sheet Từ OpenCode

Workflow cơ bản giống mọi client khác: agent gọi tool đọc range, xử lý, rồi gọi tool ghi. Điểm cần lưu ý riêng cho OpenCode là cách nó hiển thị tool-call trong giao diện — mỗi lệnh gọi MCP tool hiện thành một block riêng có thể approve/deny từng cái, khác với Claude Code gộp theo session.

Đọc range "Backlog!A1:J300" trong spreadsheet ID 1XyzAbc...
Cột G là "priority" (P0/P1/P2/P3), cột H là "status".
Đếm số item theo từng cặp (priority, status), in bảng chéo (cross-tab) ra đây.

Khi ghi lại, OpenCode không có cơ chế "session-level tool trust" mạnh như Claude Code — mỗi lần gọi write_range mới đều có thể bị hỏi lại tùy theo cấu hình permission bạn đặt trong opencode.json. Đây thực ra là điểm cộng cho các thao tác ghi trên spreadsheet: bạn được xem trước chính xác range và giá trị sẽ ghi trước khi nó xảy ra.

{
  "permission": {
    "mcp": {
      "sheets_write_range": "ask",
      "sheets_read_range": "allow"
    }
  }
}

Với cấu hình trên, mọi lệnh đọc chạy tự động không hỏi, nhưng mọi lệnh ghi luôn dừng lại chờ bạn xác nhận — một thiết lập hợp lý mặc định cho hầu hết workflow làm việc với dữ liệu thật.

Mẹo: Set permission "ask" riêng cho tool ghi ngay từ ngày đầu cấu hình, đừng để mặc định "allow" toàn bộ chỉ vì muốn "chạy nhanh cho xong việc" — chi phí dừng lại xác nhận một request ghi luôn nhỏ hơn chi phí sửa lại một sheet bị ghi sai.

Ví Dụ Thực Tế: Xây Requirements Traceability Matrix

Đây là một use case rất hợp với engineer: xây một ma trận truy vết yêu cầu (traceability matrix) nối các user story trong một tab với test case tương ứng trong tab khác, phát hiện story nào chưa có test case nào che phủ.

Giả sử bạn có tab User-Stories (cột A: ID, cột B: title) và tab Test-Cases (cột A: ID, cột B: title, cột C: linked_story_id). Prompt cho agent:

1. Đọc toàn bộ tab "User-Stories" (cột A, B) và tab "Test-Cases" (cột A, B, C)
   trong spreadsheet ID 1XyzAbc...
2. Với mỗi user story, tìm các test case có cột "linked_story_id" khớp ID story đó.
3. Tạo tab mới "Traceability-Matrix" với các cột:
   Story ID | Story Title | Số Test Case | Test Case IDs | Trạng thái
   Trạng thái = "Chưa có test" nếu số test case = 0, ngược lại "Đã che phủ".
4. Ghi kết quả vào tab mới đó, không sửa hai tab nguồn.

Đây là ví dụ tốt để thấy sức mạnh thật của Sheets MCP: việc join dữ liệu giữa hai tab, thứ mà làm bằng công thức VLOOKUP/QUERY tay sẽ khá cồng kềnh và dễ sai khi có ID trùng hoặc thiếu, agent xử lý bằng logic rõ ràng và bạn review được từng bước qua log tool-call.

Mẹo: Với bài toán join dữ liệu giữa nhiều tab, luôn yêu cầu agent in ra vài dòng mẫu của kết quả join trước khi ghi vào sheet — kiểm tra nhanh 3-5 dòng mẫu bằng mắt phát hiện được hầu hết lỗi logic join (ví dụ so khớp ID dạng số với ID dạng chuỗi mà không trim khoảng trắng).

Hạn Chế Đã Biết Của Google Sheets MCP Trong OpenCode

Vài điểm cần biết trước khi đưa vào workflow chính thức:

  • Không có cơ chế retry tích hợp cho rate limit. Google Sheets API giới hạn khoảng 60 request/phút/user cho hầu hết endpoint (con số chính xác tùy quota project của bạn) — nếu agent gọi nhiều request liên tiếp (ví dụ ghi từng dòng một thay vì batch), bạn dễ chạm rate limit và OpenCode không tự động backoff/retry cho bạn ở tầng orchestration.
  • Remote/HTTP transport (server hosted) đôi khi timeout lâu hơn config mặc định cho phép trên các thao tác xử lý sheet lớn — nên set timeout cụ thể, cao hơn mặc định, trong opencode.json cho server dùng transport HTTP.
  • Không phải mọi permission rule áp dụng đồng nhất giữa CLI và TUI của OpenCode ở một số version — luôn test lại rule permission trong đúng môi trường bạn dự định dùng hàng ngày, đừng giả định set một lần dùng chung mọi nơi.
{
  "mcp": {
    "sheets-hosted": {
      "type": "remote",
      "url": "https://your-hosted-sheets-mcp.example.com/mcp",
      "timeout": 60000
    }
  }
}

Mẹo: Nếu bạn thấy agent báo lỗi 429 (rate limit) khi ghi nhiều dòng liên tiếp, chuyển sang yêu cầu agent dùng batch_update (ghi nhiều range trong một request) thay vì gọi write_range lặp lại từng dòng — đây gần như luôn là cách xử lý đúng, không phải việc chờ lâu hơn giữa các request.

Tips

  • Nhớ cú pháp expand biến môi trường riêng của OpenCode ({env:VAR}), khác Claude Code.
  • Đặt permission "ask" cho mọi tool ghi ngay từ đầu, không mặc định "allow".
  • Ưu tiên batch_update thay vì ghi lặp từng dòng để tránh chạm rate limit của Google Sheets API.
  • Test lại rule permission trong đúng môi trường bạn dùng thật (CLI hay TUI), đừng giả định dùng chung.

Mẹo: Giữ một file opencode.json mẫu đã test kỹ trong repo dùng chung của team (không chứa credentials thật, chỉ chứa cấu trúc và biến môi trường tham chiếu) — nó tiết kiệm rất nhiều thời gian onboarding cho người mới thay vì để mỗi người tự dò cú pháp.