Pi Agent Platform
v1.2.17 docs · VI Commands

Server đến từ repo phải được duyệt

Clone một repo lạ rồi mở session không được phép cho tác giả repo đó một process trên máy mình. Quyết định lưu ngoài repo và pin theo digest.

Vấn đề

Repo mang theo được .mcp.json.pi/mcp.json. Clone một repo lạ rồi mở session không được phép cho tác giả repo đó một process trên máy mình, với credential của mình. Nên server ở hai scope này không dùng được cho tới khi có người trên máy này duyệt.

/piagent-mcp get internal        # đọc trước
/piagent-mcp approve internal    # hoặc reject, hoặc reset

Trong terminal thì bỏ dấu /: piagent-mcp get internal. Cùng một quyết định, cùng một file.

approve in ra định nghĩa trước khi ghi quyết định — duyệt mà không đọc chính là thứ gate này sinh ra để ngăn.

Ba tính chất

Quyết định nằm ngoài repo

Ghi vào ~/.pi/piagent-mcp-approvals.json. Repo tự duyệt được cho chính nó thì gate coi như không tồn tại. Fork, đổi tên, checkout thứ hai — tất cả bắt đầu lại từ pending.

Pin theo digest

Duyệt là đồng ý với thứ server đó chạy. Đổi command, URL hay args là một câu hỏi mới, state về approval-changed. Cùng cách tách consent với build mà capability lock đang dùng.

Enforce ở tool call

Guard đọc cả proxy (mcp với input.server) lẫn direct tool. Gate chỉ đọc proxy sẽ bị đi vòng bằng cách bật directTools.

Giới hạn

Không chặn được connection

Adapter sở hữu kết nối; extension không ngăn được việc một kết nối được mở. Cái bị chặn là mọi tool call, không phải bản thân kết nối. Phần rủi ro còn lại là chính kết nối đó, và việc server phía kia ghi log rằng có người kết nối tới.

Server ở globalpi-global không qua gate. Hai layer đó nằm ngoài mọi repo — không repo nào đặt được server vào đó — và bắt người dùng duyệt config của chính mình trên từng máy là vô nghĩa.

Server đến qua imports

Config MCP nhận thêm key imports, kéo định nghĩa server từ config của công cụ khác. Server vào session theo đường này không nằm trong bốn scope nào, nên nó là đường vòng thứ hai quanh gate — và không cần bật directTools.

Trong sáu kind, chỉ vscode trỏ vào đường dẫn trong project (.vscode/mcp.json). Clone repo là mang theo file đó, nên server của nó phải duyệt như mọi server repo khai báo thẳng.

Tình huốngXử lý
Layer bất kỳ import kind repo-relative Server phải duyệt, kể cả khi global khai báo — nội dung đọc lại vẫn nằm trong repo.
Repo scope import kind bất kỳ Server phải duyệt. Repo đang chọn hộ máy này chạy server nào.
Repo scope import kind không đọc được nội dung (codex, TOML) Chặn mọi tool call, khi file đó có thật trên máy. Từ chối ở dòng khai báo: liệt kê được server của năm kind kia không nói gì về kind thứ sáu. Khai một kind máy này không cài thì là config cần dọn, không phải session cần dừng.
remove / enable / disable trên server đến qua imports Từ chối, kèm tên file thật cần sửa. File được định vị là config của công cụ kia; ghi ngược bằng writer của platform sẽ viết lại file Cursor/VS Code của người dùng theo format chính công cụ đó không dùng.
directTools + toolPrefix: "none" trong config repo mang theo Chặn mọi tool call, không riêng lời gọi MCP. Không prefix thì tên tool không còn dấu vết server, không truy được để đối chiếu quyết định — mà chặn riêng proxy mcp thì đúng những cái tên trần cần chặn lại đi thẳng qua.

piagent-mcp doctor nêu tên file có imports và các kind của nó, nêu layer không parse được, và nêu cả import target có thật nhưng không đọc được — cả ba trạng thái trước đây đều đọc ra rỗng, không phân biệt được với “không khai server nào”.

Với hai trạng thái chặn-toàn-bộ ở trên, doctorlist in ra lý do và exit 1 — kể cả list --json, vốn trả servers: [] với exit 0 đúng lúc không gì chạy được. Exit code trả lời “MCP ở đây có chạy được không”, không phải “có in ra dòng nào không”. Cả ba surface — guard, /piagent-mcp, CLI — đọc một state chung, vì hai bên lệch nhau chính là cách một session bị chặn biến thành một session hỏng không rõ lý do.

Gate được cache theo project và tính lại khi signature trên các file phía sau nó đổi. Danh sách file đó lấy từ chính đường đi mà các reader dùng, kể cả file đang không tồn tại — imports: ["codex"] thành chặn đúng lúc file codex xuất hiện, và directTools thêm vào config global cá nhân là thứ guard đã load phải thấy ngay. Viết tay danh sách đó là cách nó lệch.

Adapter merge settings của cả bốn layer thành một block cho cả session. Nên directTools đặt ở file này và toolPrefix: "none" đặt ở file kia vẫn ra đúng tổ hợp làm gate mất chỗ bám, trong khi đọc riêng từng file thì không file nào có vấn đề. Settings được đọc sau merge, và báo cả hai file.

Cột SCOPE là layer khai báo imports, không phải nơi server được định nghĩa. Server import qua config global vẫn cần duyệt, vì file đọc lại nằm trong clone.

Bốn quyết định thiết kế

Quyết địnhVì sao
Chỉ gate server đến từ repo Chỉ .mcp.json.pi/mcp.json đi theo clone. Server người dùng tự đặt trên máy mình không cần ai duyệt.
Quyết định lưu ngoài repo ~/.pi/piagent-mcp-approvals.json. Nếu lưu trong repo thì repo tự duyệt cho chính nó — gate mất nghĩa ngay từ đầu.
Pin theo digest của định nghĩa Duyệt là duyệt đúng command và URL đó. Đổi command, đổi args, đổi URL thì server quay về pending chứ không kế thừa quyết định cũ.
Preview in ra bản đã merge, digest tính trên mảnh của repo Adapter merge server trùng tên theo từng key qua các layer, nên repo khai mỗi {"args": [...]} vẫn lấy command từ layer dưới. Preview phải là thứ sẽ chạy thật. Digest thì giữ trên phần repo kiểm soát — băm cả bản merge sẽ đẩy server về pending mỗi lần người dùng sửa config global của chính mình.
Chặn ở tool_call Cả dạng proxy mcp lẫn direct tool, để không có đường vòng. Direct tool được truy theo tên server đang cấu hình, vì prefix của nó chính là tên server.

Điểm chặn lý tưởng là trước khi connect, nhưng chặn được ở đó thì phải sở hữu connection. Platform chạy trong Pi và không sở hữu nó, nên nó chọn điểm chặn xa nhất mà nó thật sự kiểm soát được — rồi nói rõ phần còn thừa thay vì để người đọc tự suy ra.

Migration

Project đã có server từ trước

Project nào đã có server trong .mcp.json hoặc .pi/mcp.json sẽ chuyển sang pending-approval sau khi update. Chạy /piagent-mcp approve <name> một lần cho mỗi project. Template ship rỗng nên đa số project không bị ảnh hưởng; notice đầu session và doctor đều nêu tên server cần duyệt.