Skip to content

MCP Server — Thiết kế chức năng (tổng thể)

MụcNội dung
Trạng thái🟡 Đang thiết kế
Case liên quan#13 MCP Server (Thiết lập mới)
GitLab IssueMappy #58
Tài liệu cha(Tài liệu này là cha của thiết kế chức năng MCP)
Tài liệu conTool Catalog / Auth & Tenancy / Cơ chế an toàn write

1. Mục đích tài liệu

Định nghĩa bức tranh tổng thể của thiết kế chức năng MCP Server. So sánh stack triển khai (Python / TypeScript), phân chia component, flow request, spec transport, phương châm xử lý lỗi sẽ được chốt tại đây làm tiền đề cho các tài liệu design sau (tool catalog・auth・write safety・audit log v.v.).

2. Bức tranh tổng thể hệ thống

2.1 Sơ đồ kiến trúc

2.2 Trách nhiệm từng component

ComponentTrách nhiệmVị trí
Streamable HTTP endpointTiếp nhận protocol MCP, duy trì kết nối long-lived, gửi/nhận message và eventProcess MCP Server
OAuth 2.1 Authz ServerĐăng ký client, phát authorization code, phát token, kiểm tra scopeProcess MCP Server (hoặc tách riêng)
Tool DispatcherRouting từ tên tool tới hàm implement, validate input, kiểm tra scope, format kết quảProcess MCP Server
Audit LoggerGhi tất cả tool call, auth failure, exception vào audit log DBProcess MCP Server
Laravel API (cho MCP)Thêm endpoint MCP dưới /api/mcp/*. Gọi service・model hiện cóTrong Laravel app
Mappy DBDữ liệu thực. Từ MCP chỉ access qua Laravel APIHiện có
GBP APITrung gian tới Google Business Profile. Laravel API quản lý tokenExternal
Jobs QueueXử lý bất đồng bộ cho write tool. Dùng bảng jobs hiện cóHiện có

Cấm truy cập DB trực tiếp

MCP Server không SELECT/UPDATE Mappy DB trực tiếp. Mọi data access đều qua Laravel API. Lý do:

  • Không duplicate logic kiểm tra tenancy・quyền
  • Tận dụng validation・service logic・cơ chế audit hiện có
  • Tối thiểu hóa phạm vi ảnh hưởng khi schema thay đổi

3. Flow request

3.1 Flow kết nối lần đầu・xác thực (OAuth 2.1 + PKCE)

Chi tiết xem Auth & Tenancy.

3.2 Flow gọi read tool (đồng bộ)

3.3 Flow gọi write tool (bất đồng bộ)

Chi tiết xem Cơ chế an toàn write.

4. Transport — Streamable HTTP

4.1 Lý do chọn

  • Transport chính thức của MCP 2025-03-26 spec (SSE cũ đang dần bỏ)
  • Duy trì kết nối long-lived nhưng hợp với HTTP/2 / HTTP/3
  • Xử lý được bằng load balancer・WAF・CDN tiêu chuẩn
  • ChatGPT Connectors / Claude Desktop đều hỗ trợ chính thức

4.2 Endpoint

PathMethodMục đích
/sseGETThiết lập session MCP (event stream)
/messagesPOSTClient gửi message MCP
/oauth/authorizeGETEndpoint authorize OAuth
/oauth/tokenPOSTPhát access token
/oauth/registerPOSTDynamic client registration (RFC 7591)
/.well-known/oauth-authorization-serverGETOAuth metadata
/healthGETHealth check

4.3 Quản lý session

  • 1 connection = 1 session
  • Session ID phát từ server, trả về qua header Mcp-Session-Id
  • Khi disconnect thì hủy session, kết nối lại = session mới
  • Idle timeout: 30 phút
  • Bắt buộc re-auth: khi refresh_token hết hạn

5. So sánh chi tiết stack triển khai

Đề xuất song song 2 phương án, nhưng tài liệu này làm rõ tiêu chí chọn.

5.1 Phương án A: Python (FastMCP)

MụcNội dung
MCP libraryFastMCP 2.x
Python version đề xuất3.11+
HTTP serverUvicorn (ASGI)
Implement OAuth 2.1Authlib hoặc tự implement
Validate input/outputPydantic v2
Laravel API clienthttpx (async)
Loggingstructlog + JSON output
Testpytest + pytest-asyncio
Quản lý dependencyPoetry hoặc uv

Sample code (định nghĩa tool):

python
from fastmcp import FastMCP
from pydantic import BaseModel, Field

mcp = FastMCP("Mappy MCP")

class LocationListInput(BaseModel):
    user_id: int = Field(..., description="ID user đối tượng")
    group_id: int | None = Field(None, description="Lọc theo group")
    limit: int = Field(50, ge=1, le=100)

@mcp.tool(scopes=["mappy:location:read"])
async def location_list(input: LocationListInput) -> list[dict]:
    """Trả về danh sách location mà user có quyền access"""
    resp = await laravel_api.get(
        "/api/mcp/locations",
        params=input.model_dump(exclude_none=True),
    )
    return resp.json()

5.2 Phương án B: TypeScript (SDK chính thức)

MụcNội dung
MCP library@modelcontextprotocol/sdk
Node version đề xuất20 LTS
HTTP serverExpress / Hono / Fastify
Implement OAuth 2.1oauth4webapi / panva/jose
Validate input/outputZod
Laravel API clientundici / fetch
Loggingpino
Testvitest
Quản lý dependencypnpm hoặc npm

Sample code (định nghĩa tool):

typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

const server = new McpServer({ name: "Mappy MCP", version: "1.0.0" });

const LocationListInput = z.object({
  user_id: z.number().int().describe("ID user đối tượng"),
  group_id: z.number().int().optional(),
  limit: z.number().int().min(1).max(100).default(50),
});

server.tool(
  "location.list",
  "Trả về danh sách location mà user có quyền access",
  LocationListInput.shape,
  async (input) => {
    const resp = await fetch(
      `${LARAVEL_API}/api/mcp/locations?${new URLSearchParams(input)}`,
    );
    return { content: [{ type: "text", text: await resp.text() }] };
  },
);

5.3 Bảng so sánh

Tiêu chíPython (FastMCP)TypeScript (SDK chính thức)Ghi chú
Hỗ trợ chính thứcCộng đồng (phổ biến)Chính thứcTS lợi thế hơn một bước
Tài liệuTốtĐầy đủTS lợi thế hơn một bước
Type safetyPydantic (runtime)Zod + TS (static)TS mạnh hơn
Skill nội bộ hiện cóTích lũy qua scraping・AITích lũy phía frontendTương đương
Đồng cư với AI report○ cùng Python× khác ngôn ngữPython lợi thế
Mở rộng PPTX/Excel v.v.○ python-pptx v.v.△ ít library cho Node.jsPython lợi thế
Đồng cư trong LaradockThêm container mớiTận dụng được container Node hiện cóTS lợi thế
Tốc độ khởi động・memoryNặng hơn Node.jsNhẹTS lợi thế
Độ trưởng thành Streamable HTTPỔn địnhỔn địnhTương đương
Library OAuth 2.1Authlib (phong phú)oauth4webapi (chuẩn)Tương đương

5.4 Đề xuất và tiêu chí phán đoán

Đề xuất: Python (FastMCP)

Thứ tự ưu tiên của tiêu chí phán đoán:

  1. Tính dễ đồng cư・vận hành tích hợp (AI report #9 đã chọn Python)
  2. Khả năng mở rộng tương lai (option PPTX/Excel, tích hợp ML)
  3. Skill nội bộ (scraping cũng là Python)

Với 3 điểm này Python ưu thế. Lợi thế của TypeScript (hỗ trợ chính thức・type safety) cũng có, nhưng ưu tiên tích hợp vận hành xuyên tổ chức.

Quyết định cuối cùng tại review design → ngay trước khi raise Issue manufacture.

6. Khác biệt hành vi theo client

ClientTransportOAuth flowLưu ý
Claude DesktopStreamable HTTP / stdio cả 2Browser nội bộ chạy PKCE flowHỗ trợ macOS / Windows / Linux
Claude CodeStreamable HTTP / stdio cả 2Tương tựCLI based
ChatGPT ConnectorsChỉ Streamable HTTPMàn hình cấu hình connector trên webPhải đăng ký redirect URI bên phía ChatGPT

6.1 Bắt buộc để đảm bảo tương thích

  • Trả về /.well-known/oauth-authorization-server
  • Dynamic client registration RFC 7591 (ChatGPT có thể không cần đăng ký trước)
  • Bắt buộc support PKCE (code_challenge_method=S256)
  • Tool description nên kèm tiếng Anh hoặc có cấu trúc theo ngôn ngữ của AI khách
  • Whitelist redirect URI: đăng ký URI chính thức của Claude / ChatGPT

7. Xử lý lỗi

7.1 Phân loại lỗi

LoạiHTTP / JSON-RPCVí dụHành động
Lỗi auth401Token vô hiệu hoặc hết hạnYêu cầu client re-auth
Lỗi authz403 / -32604Thiếu scopeTrả về tool result với isError: true
Lỗi input400 / -32602Validation failTrả về kèm message chi tiết
4xx phía MappyPass-throughRecord không tồn tại v.v.Giữ error code và trả về
5xx phía Mappy502 / -32603Laravel API gặp sự cốGhi Audit Log, xét khả năng retry
GBP API hỏng502Google bị lỗiTruyền thông điệp lỗi cho AI khách
Timeout504Quá 30 giây không responseThông báo client, write thì truy theo batch_id

7.2 Phương châm timeout

Khu vựcTimeout
MCP Client → MCP ServerTheo cấu hình client (thường 30〜60 giây)
MCP Server → Laravel API10 giây (read) / 30 giây (write đồng bộ)
Laravel API → GBP APITheo cấu hình hiện có (thường 30 giây)
Toàn bộ write (đến khi job xong)Bất đồng bộ, truy theo batch_id

7.3 Phương châm retry

  • Read: chỉ 5xx, client tự retry 1 lần
  • Write: chỉ cho phép resend với idempotency_key. Server không auto retry
  • Rate limit GBP API: tận dụng middleware rate-limiter hiện có của Laravel

8. Rate limit

Phạm vi áp dụngGiới hạnLý do
Theo access token60 request/phút (read)Chống DoS
Theo access token10 request/phút (write)Cân nhắc giới hạn GBP API
Theo client ID1000 request/giờChống loạn từ một client
Cùng idempotency_key24 giờChống duplicate write

9. Cấu hình deploy (tổng quan)

Chi tiết xem Thiết kế hạ tầng.

MụcNội dung
Vị tríAWS (cùng VPC với Mappy hiện có)
ContainerECS Fargate (hoặc EC2)
Load balancerALB (HTTPS termination)
Domainmcp.mappy.example.com (tạm)
TLSCert ACM
Common storeRedis (session, counter rate limit, cache idempotency)
Quản lý secretAWS Secrets Manager
Tập trung logCloudWatch Logs
Giám sátCloudWatch Metrics / Alarms

10. Audit log

MCP Server ghi toàn bộ thao tác vào audit log. Chi tiết xem DB (audit log).

Đối tượng ghi:

  • Tool call (input・output・thời gian thực thi・mã kết quả)
  • Authz thành công・thất bại
  • Phát token・revoke
  • Rate limit hit
  • Exception・timeout

11. Tenancy・Scope (tổng quan)

Chi tiết xem Auth & Tenancy.

TầngPhạm vi thao tác
admin (is_supervisor=1)Toàn bộ mappy_users
admin (is_supervisor=0)User trong phạm vi preview_user_id
MAIN_USERBản thân + group dưới parent_user_id
MASTER_USERToàn bộ group dưới parent_user_id
GROUP_USERChỉ bản thân

Ranh giới cửa hàng:

  • Lọc qua mappy_user_available_gbp_locations
  • Theo group: mappy_groups + mappy_group_location (dạng số ít)

12. Tài liệu thiết kế liên quan

Tài liệuNội dung
Tool CatalogSchema input/output của từng tool, scope, phân loại side effect
Auth & TenancyChi tiết OAuth 2.1 flow, thiết kế scope, logic xác định tenancy
Cơ chế an toàn writedry_run / idempotency / confirm token / batch polling
DB (audit log)Định nghĩa bảng audit log
DB (OAuth client)Bảng quản lý OAuth client・token
Thiết kế hạ tầngCấu hình AWS・container・network
Chi tiết IssueTask implement・điều kiện nghiệm thu

13. Điểm chưa chốt (quyết định tại review design)

#MụcPhương án
1Stack triển khaiPython (FastMCP) / TypeScript (SDK chính thức)
2Library OAuthPython: Authlib / tự implement
TS: oauth4webapi / tự implement
3Hostname MCP Servermcp.mappy.example.com (tạm)
4Phạm vi cho phép thao tác thay mặt adminPhase 1 chỉ chính admin / Phase 2 hỗ trợ preview_user_id
5Giá trị rate limit cuối cùngTrên đây là tạm, điều chỉnh sau khi xem tải production
6Redis vs DynamoDBChọn store cho session・idempotency
7Cache phía clientAI khách có cache tool result hay không