Phạm Văn Thư
Tự động hóa và tích hợp · AI-assisted content

MCP Go SDK: dựng máy chủ công cụ cho trợ lý AI bằng Go

Đăng ngày 12/10/2026

Mục lục bài nghiên cứu
Hình đại diện MCP Go SDK — tự động hóa quy trình mã nguồn mở

Tóm lược: SDK chính thức để dựng máy chủ và máy khách MCP bằng Go

MCP Go SDK là bản cài đặt bằng ngôn ngữ Go của Model Context Protocol (MCP), giao thức chuẩn để một ứng dụng AI kết nối với công cụ và nguồn dữ liệu bên ngoài. README mô tả đây là SDK chính thức và chia thư viện thành bốn gói: mcp cho máy khách và máy chủ, jsonrpc cho người tự viết kênh truyền, auth cho các thành phần OAuth, oauthex cho phần mở rộng OAuth [1]. Nói đơn giản, nó giúp đội Go không phải tự viết lớp JSON-RPC, vòng đời phiên và kiểm tra tham số khi muốn mở một hệ thống nội bộ cho trợ lý AI.

Nên cân nhắc khi doanh nghiệp đã có dịch vụ viết bằng Go, có một số thao tác nghiệp vụ rõ ràng muốn cho trợ lý AI gọi, và muốn một giao diện không gắn chặt vào một mô hình cụ thể. Tài liệu máy chủ cho thấy một hàm Go thông thường có thể được gắn thành công cụ, trong khi schema đầu vào và đầu ra được suy ra từ kiểu dữ liệu của hàm [4]. Đây là điểm đáng giá nhất với đội backend: việc khai báo công cụ gần với cách họ viết code hằng ngày.

Chưa nên dùng khi ứng dụng chỉ gọi một API cố định từ chính mã của mình, khi đội không dùng Go, hoặc khi cần một giao diện lập trình đã đóng băng nhiều năm. Dự án còn giữ danh sách những quyết định API muốn xem lại cho phiên bản v2 [8], và đặc tả MCP bản 2026-07-28 vừa đưa vào những thay đổi đáng kể về vòng đời phiên [1][6]. Khuyến nghị của bài là bắt đầu bằng một máy chủ chỉ đọc, đặt sau xác thực, chạy trong phạm vi thử nghiệm nhỏ.

Bài toán gốc: mỗi trợ lý AI một kiểu kết nối riêng

Khi một công ty muốn trợ lý AI tra cứu thông tin hoặc thực hiện một thao tác, cách làm quen thuộc là viết bộ chuyển đổi riêng cho từng mô hình hoặc từng ứng dụng. Mỗi bộ chuyển đổi có cách mô tả tham số, cách trả lỗi và cách xác thực riêng, nên chi phí bảo trì tăng theo số cặp kết nối. Giao thức MCP cố gắng thay bằng một ngôn ngữ chung: máy chủ cung cấp công cụ (tool, tức hàm gọi từ xa), mẫu lời nhắc (prompt) và tài nguyên (resource, tức dữ liệu được định danh bằng URI) [4].

Phần SDK lo những việc lặp lại ở tầng giao thức. Tài liệu máy chủ liệt kê rằng nếu dùng API mức thấp Server.AddTool, người viết phải tự cung cấp schema, kiểm tra đối số theo schema, giải mã vào kiểu Go, chạy logic, đóng gói kết quả có cấu trúc, kiểm tra đầu ra và gói lỗi vào nội dung kèm cờ IsError. Hàm AddTool dạng generic của SDK làm sẵn các bước đó [4]. Nhờ vậy lập trình viên chủ yếu viết phần nghiệp vụ.

Server, Client, Session và Transport: bốn khái niệm cần nắm

Về mô hình đối tượng, tài liệu giao thức mô tả Client và Server là các thực thể logic với các tùy chọn riêng. Khi kết nối bằng Connect, mỗi bên tạo ra một phiên (ClientSession hoặc ServerSession). Kênh truyền (Transport) là một luồng hai chiều của các thông điệp JSON-RPC, và người dùng có thể tự cài giao diện Transport nếu cần một kênh riêng [6]. Cách tách này cho phép viết một máy chủ một lần rồi chạy qua nhiều kênh khác nhau.

Khả năng (capability) của máy chủ được suy ra từ những gì đã đăng ký trước khi kết nối. Chẳng hạn máy chủ có capability tools nếu có công cụ được thêm trước khi nối với máy khách, hoặc nếu ServerOptions.HasTools được đặt tường minh. Nếu đăng ký tính năng sau khi đã kết nối thì cần tự khai báo HasTools, HasPrompts hoặc HasResources, nếu không máy khách sẽ không nhận thông báo thay đổi danh sách [4]. Đây là một chi tiết dễ bỏ sót khi tạo công cụ động.

Vòng đời phiên có hai kiểu. Kiểu cũ dùng bắt tay initialize cho các phiên bản đặc tả đến 2025-11-25. Kiểu không trạng thái ra đời ở phiên bản 2026-07-28, trong đó mỗi yêu cầu tự mang phiên bản giao thức và khả năng của máy khách trong trường _meta. SDK hỗ trợ cả hai với cùng một API và chọn theo phiên bản đã đàm phán [6]. Với người dùng SDK, ý nghĩa thực tế là mã ứng dụng ít phải đổi khi chuyển giữa hai thế hệ giao thức.

Đường đi của một lệnh gọi công cụ, từ máy khách tới hàm Go

Hình dung một trợ lý AI muốn gọi công cụ có tên greet. Máy khách gọi CallTool với tên công cụ và đối số, đối số có thể là bất kỳ giá trị nào chuyển được sang JSON [4]. Trên kênh HTTP dạng streamable, StreamableHTTPHandler nhận yêu cầu và tạo một StreamableServerTransport cho mỗi phiên mới [6].

Với phiên bản đặc tả 2026-07-28, mỗi yêu cầu mang trong _meta phiên bản giao thức và khả năng máy khách. Một số header như Mcp-Method và Mcp-Name phải khớp với thân JSON-RPC, nếu lệch máy chủ trả mã lỗi -32020 [6]. Nếu máy chủ bọc bằng RequireBearerToken, bước kế tiếp là kiểm tra header Authorization, gọi TokenVerifier để phân tích token, rồi kiểm tra hạn dùng và phạm vi quyền. Thông tin token sau đó đến được handler qua req.Extra.TokenInfo [6].

Tới handler, nếu công cụ được gắn bằng AddTool dạng generic, SDK kiểm tra đối số theo schema, giải mã vào kiểu Go, chạy hàm, đóng gói kết quả vào StructuredContent cùng nội dung văn bản, rồi kiểm tra đầu ra. Lỗi thông thường được lưu với IsError bằng true [4]. Các cuộc gọi như tools/call được xử lý bất đồng bộ với nhau, nên handler phải an toàn khi chạy đồng thời [6].

Tính năng đã được tài liệu xác nhận

Về nội dung máy chủ, SDK hỗ trợ prompt, resource (kể cả resource template theo mẫu URI và đăng ký theo dõi thay đổi) và tool. Mỗi loại có phương thức thêm vào máy chủ và phương thức liệt kê hoặc gọi ở phía máy khách, kèm thông báo list_changed khi danh sách đổi [4]. Kết quả công cụ có thể chứa văn bản, hình ảnh, âm thanh, tài nguyên nhúng hoặc đường dẫn tới tài nguyên, và tài liệu khuyên dùng liên kết khi máy khách chưa chắc cần nội dung [4].

Về xác thực, phía máy chủ có middleware RequireBearerToken và bộ phục vụ metadata tài nguyên được bảo vệ theo RFC 9728. Phía máy khách có AuthorizationCodeHandler hỗ trợ Client ID Metadata Documents, máy khách đăng ký sẵn, đăng ký động và kiểm tra tham số iss theo RFC 9207, kèm làm mới token và nâng quyền khi gặp insufficient_scope. Một EnterpriseHandler thực hiện luồng đăng nhập doanh nghiệp theo SEP-990 [6]. Bảng tương thích trong README đánh dấu OAuth phía máy khách ở mức thử nghiệm với dải phiên bản v1.4.0 đến v1.6.1 [1].

Về tính năng phía máy khách, tài liệu mô tả roots, sampling và elicitation (máy chủ yêu cầu người dùng nhập thông tin theo một schema phẳng) [5]. README và tài liệu máy khách đều ghi rằng roots, sampling và logging bị đánh dấu ngừng dùng từ phiên bản đặc tả 2026-07-28 theo SEP-2577, vẫn được hỗ trợ trong cửa sổ chuyển tiếp ít nhất mười hai tháng [1][5]. Ai bắt đầu dự án mới nên tránh dựa vào ba tính năng này.

Đối tượng phù hợp và lĩnh vực nên thử

Nhóm phù hợp nhất là đội backend Go ở doanh nghiệp vừa và nhỏ có sẵn dịch vụ nội bộ. Họ đã quen với kiểu dữ liệu Go, ngữ cảnh (context) và middleware HTTP, những thứ SDK dùng trực tiếp: hủy bỏ lệnh gọi bằng context [6], bọc handler bằng middleware xác thực [6]. Với nhóm này, chi phí học SDK chủ yếu nằm ở việc hiểu giao thức, không phải học một phong cách lập trình mới.

Nhóm chưa phù hợp gồm đội không có lập trình viên Go, đội chỉ cần tích hợp một ứng dụng AI có sẵn với một dịch vụ SaaS đã có máy chủ MCP của nhà cung cấp, và các nhóm cần cam kết API không đổi. Với những nhóm này, dùng SDK ở ngôn ngữ họ đang dùng hoặc dùng sản phẩm có sẵn sẽ kinh tế hơn.

Tình huống giả định: trợ lý cho đội tư vấn của một nền tảng tuyển dụng

Đây là một đề xuất ứng dụng, không phải trường hợp đã xảy ra. Giả sử một nền tảng tuyển dụng cỡ vừa ở Việt Nam có backend Go. Đội tư vấn khách hàng doanh nghiệp mỗi ngày phải mở nhiều màn hình để trả lời các câu hỏi như tin tuyển dụng này đang ở trạng thái nào, ứng viên nào đã xem việc làm, buổi phỏng vấn nào còn trống. Nền tảng có thể dựng một máy chủ MCP nội bộ tên recruiter-tools bằng SDK, để trợ lý AI mà đội tư vấn đã dùng gọi vào đó.

Phiên bản đầu chỉ có ba công cụ. Công cụ thứ nhất tra trạng thái tin tuyển dụng theo mã tin, chỉ đọc. Công cụ thứ hai tìm hồ sơ ứng viên theo tiêu chí kỹ năng và khu vực, trả về thông tin đã che số điện thoại và email. Công cụ thứ ba soạn đề xuất lịch phỏng vấn dưới dạng bản nháp. Công cụ thứ ba không gửi gì cho ứng viên; nó chỉ yêu cầu người tư vấn xác nhận qua cơ chế elicitation mà tài liệu máy khách mô tả [5], rồi mới tạo lịch trong hệ thống. Việc gắn mỗi công cụ vào một hàm Go với kiểu đầu vào rõ ràng là cách dùng đúng thế mạnh của AddTool [4].

Về xác thực, máy chủ chạy dưới dạng dịch vụ HTTP nội bộ, bọc bằng RequireBearerToken. TokenVerifier đọc mã người dùng từ token đăng nhập của công ty và gán vào TokenInfo.UserID, nhờ đó phiên MCP bị khóa với đúng người tư vấn, theo cơ chế chống chiếm phiên mà tài liệu mô tả [6]. Quyền trên hồ sơ ứng viên vẫn do hệ thống nghiệp vụ hiện có quyết định, không do trợ lý AI.

Có một điểm kỹ thuật cần kiểm chứng sớm. Tài liệu nói phiên bản 2026-07-28 chỉ được chấp nhận trên bộ xử lý streamable khi bật chế độ Stateless, và ở chế độ này máy chủ không thể gửi yêu cầu ngược tới máy khách [6]. Trong khi đó mẫu Multi Round-Trip Requests được mô tả như cách thay thế cho yêu cầu ngược [4]. Đội thử nghiệm cần xác nhận bằng một bài kiểm tra cụ thể rằng bước xác nhận của người tư vấn hoạt động trọn vẹn với tổ hợp này, thay vì suy luận từ tài liệu.

Triển khai và vận hành: chọn kênh truyền trước, rồi mới tính hạ tầng

Lựa chọn đầu tiên là kênh truyền. Nếu công cụ chỉ phục vụ một ứng dụng chạy trên máy người dùng, stdio là đủ: máy khách khởi chạy tiến trình máy chủ và trao đổi qua stdin, stdout [6]. Nếu nhiều người dùng chung một dịch vụ, streamable HTTP là lựa chọn chính, và tài liệu khuyên triển khai mới dùng nó thay cho SSE kiểu cũ [6].

Lựa chọn thứ hai là có trạng thái hay không. Theo tài liệu, máy chủ streamable mặc định không hỗ trợ tiếp tục phát lại thông điệp vì cần lưu trữ bền vững hoặc bộ nhớ không giới hạn; bật EventStore mới có, và MemoryEventStore chỉ nên dùng thử nghiệm hoặc trường hợp đơn giản [6]. Phiên bản đặc tả 2026-07-28 còn bỏ khả năng tiếp tục luồng SSE, nên khi luồng phản hồi đứt, yêu cầu đang xử lý bị mất và máy khách phải gửi lại như yêu cầu mới [6]. Với công cụ chỉ đọc, thao tác này an toàn; với công cụ ghi, cần thiết kế khóa chống trùng ở phía nghiệp vụ.

Bảo mật và quyền riêng tư: những gì SDK làm sẵn và những gì còn lại cho bạn

Tài liệu giao thức có một mục riêng đối chiếu từng rủi ro trong hướng dẫn bảo mật của MCP với cách SDK xử lý. Về confused deputy, SDK sinh giá trị state ngẫu nhiên mật mã cho mỗi yêu cầu cấp quyền và kiểm tra khi nhận mã, còn việc xin đồng ý của người dùng cho máy khách đăng ký động chủ yếu thuộc về người viết máy chủ proxy. Về token passthrough, việc chỉ nhận token được cấp cho chính máy chủ này nằm ở TokenVerifier do người dùng cung cấp [6].

Về giả mạo yêu cầu phía máy chủ (SSRF), các hàm khám phá OAuth mặc định bắt buộc HTTPS (trừ loopback), từ chối địa chỉ không công khai kể cả điểm metadata 169.254.169.254, kiểm tra lại ở thời điểm kết nối để chống DNS rebinding, kiểm tra đích chuyển hướng và giới hạn số lần chuyển hướng. Tuy nhiên nếu truyền http.Client tùy chỉnh với DialContext riêng, proxy, hoặc CheckRedirect, các biện pháp này bị vô hiệu một phần hoặc toàn phần và trách nhiệm quay lại người dùng [6].

Về chiếm phiên, SDK sinh mã phiên an toàn theo mặc định, nhưng nếu tự đặt GetSessionID thì phải tự bảo đảm độ an toàn; tài liệu khuyến nghị crypto/rand.Text. Tài liệu cũng khuyến nghị đặt TokenInfo.UserID để khóa phiên với người dùng, và nhấn mạnh người dùng phải tự bọc RequireBearerToken quanh mọi handler [6].

Giấy phép: Apache-2.0 cho đóng góp mới, MIT cho mã hiện có

Tệp LICENSE ở commit được kiểm tra không phải một giấy phép đơn. Phần đầu nói dự án MCP đang chuyển từ MIT sang Apache-2.0: mã mới và đóng góp cho đặc tả theo Apache-2.0, đóng góp tài liệu (trừ đặc tả) theo CC-BY-4.0, còn những đóng góp mà tác giả chưa đồng ý chuyển giấy phép vẫn theo MIT, và không có quyền nào ngoài giấy phép gốc của từng đóng góp [2]. Sau đó là văn bản Apache License 2.0 đầy đủ và một đoạn MIT với bản quyền Model Context Protocol, a Series of LF Projects, LLC [2]. README tóm tắt tương tự: Apache 2.0 cho đóng góp mới, MIT cho mã hiện có [1].

Giấy phép chỉ áp dụng cho mã SDK tại commit này. Nó không bao trùm văn bản đặc tả giao thức, mô hình AI, dữ liệu, các máy chủ MCP bên thứ ba, dịch vụ đám mây mà bạn kết nối, hay các thư viện phụ thuộc có giấy phép riêng.

Chi phí và nguồn lực: chủ yếu là thời gian kỹ sư, không phải phí bản quyền

Nhân lực: một đến hai kỹ sư backend Go cho giai đoạn thử nghiệm, một người phụ trách an ninh thông tin để duyệt mô hình quyền và dữ liệu, và một người đại diện nghiệp vụ để xác định công cụ nào đáng mở. Phần việc tốn công nhất thường là mô tả công cụ, xử lý quyền, viết bài kiểm thử và ghi nhật ký, không phải gọi SDK.

Hạ tầng: một dịch vụ HTTP nhỏ trong mạng nội bộ, hệ thống quản lý bí mật cho khóa và token, kênh thu thập nhật ký, và môi trường thử tách khỏi dữ liệu thật. Nếu dùng chế độ có trạng thái thì thêm kho lưu phiên hoặc định tuyến dính phiên; chế độ không trạng thái giảm bớt phần này nhưng mang theo giới hạn đã nêu [6].

Đặt cạnh các hướng tiếp cận khác

Ở mức cách tiếp cận, có bốn hướng. Thứ nhất là dùng chính SDK chính thức này để dựng máy chủ MCP. Thứ hai là dùng một SDK Go của bên thứ ba: README nêu tên mcp-go của Ed Zynda, mcp-golang và go-mcp, ghi rằng chúng đã truyền cảm hứng cho thiết kế và vẫn là các lựa chọn khả dụng [1]. Bài viết chưa đọc mã của các thư viện này nên không đánh giá chúng.

Hướng thứ ba là bỏ qua giao thức chung, dùng cơ chế gọi hàm riêng của từng nhà cung cấp mô hình và viết bộ chuyển đổi cho từng nơi. Cách này đơn giản khi chỉ có một mô hình và một ứng dụng, nhưng hợp lý chỉ khi bạn chắc chắn không cần thêm đối tác. Hướng thứ tư là mở API REST có sẵn kèm tài liệu để một lớp trung gian tự gọi, tiện nếu đã có API ổn định nhưng khó thể hiện các khái niệm như resource, prompt hay vòng hỏi lại người dùng.

Hạn chế và các điều kiện không nên dùng

Nhóm phát triển tự công bố một danh sách API cần xem lại cho v2 vì không thể sửa mà không phá tương thích. Ví dụ năng lực mặc định lẽ ra nên rỗng nhưng hiện máy chủ mặc định quảng bá logging và máy khách quảng bá roots với listChanged, nên giá trị nil không có nghĩa là không có capability; cách tắt là đặt Capabilities thành cấu trúc rỗng. Tên công cụ không hợp lệ hiện chỉ ghi log lỗi thay vì dừng chương trình, và ToolAnnotations chưa dùng con trỏ bool cho mọi trường [8]. Theo ROADMAP, Tasks (SEP-1686) mới ở mức thử nghiệm và Enterprise Managed Authorization ghi là đang tiến hành [7].

Không nên dùng SDK này khi công cụ có thể gây thiệt hại không thể hoàn tác mà chưa có bước xác nhận của con người, khi chưa có phương án xác thực theo người dùng, hoặc khi dữ liệu nhạy cảm sẽ được trả nguyên văn cho một mô hình nằm ngoài vùng kiểm soát. Cũng không nên dùng nếu bạn cần một cam kết hỗ trợ có hợp đồng; các tệp đã đọc không nêu bản hỗ trợ thương mại.

Kế hoạch thử nghiệm bốn giai đoạn với tiêu chí đo được

Giai đoạn một, khoảng hai tuần: dựng máy chủ với công cụ tra trạng thái tin tuyển dụng chạy qua stdio trên máy lập trình viên, viết bài kiểm thử dùng kênh trong bộ nhớ như ví dụ trong tài liệu [4]. Tiêu chí qua cổng: mọi công cụ có schema đầu vào được suy ra, mô tả bằng tiếng Việt rõ, và đối số sai bị từ chối thay vì chạy.

Giai đoạn hai, khoảng hai đến ba tuần: chuyển sang streamable HTTP, bọc RequireBearerToken, đặt TokenInfo.UserID, thêm nhật ký kiểm toán. Tiêu chí: mọi lệnh gọi có nhật ký chứa mã người dùng và tên công cụ; một phiên không dùng được bởi token của người khác (kiểm thử âm tính bắt buộc); kiểm tra tay các nhánh SSRF nếu có luồng OAuth phía máy khách [6].

Giai đoạn ba, khoảng ba tuần: mở cho một nhóm nhỏ năm đến mười người tư vấn, thêm công cụ bản nháp lịch phỏng vấn và bước xác nhận. Các ngưỡng sau là đề xuất của bài viết và đội cần tự hiệu chỉnh: không có thao tác ghi nào chạy khi chưa được xác nhận; tỷ lệ lệnh gọi công cụ với đối số sai nằm dưới ngưỡng đội đặt ra; người dùng đánh giá bằng khảo sát ngắn rằng thời gian tra cứu giảm so với cách làm cũ.

Giai đoạn bốn là rà soát nâng cấp: thử đổi phiên bản SDK, chạy lại bộ kiểm thử trên cả phiên bản đặc tả cũ và 2026-07-28, và kiểm tra bước xác nhận trong chế độ không trạng thái. Điều kiện dừng: nếu bước xác nhận không chạy ổn định ở tổ hợp bắt buộc, hoặc nếu không thể khóa phiên theo người dùng, thì ngừng mở rộng và chuyển sang phương án gọi API có người duyệt.

Kết luận

MCP Go SDK đáng xem như một khối xây dựng hạ tầng cho đội Go muốn đưa hệ thống nội bộ vào thế giới trợ lý AI một cách có chuẩn mực. Điểm mạnh nằm ở việc gắn công cụ vào hàm Go, hỗ trợ nhiều kênh truyền và có mục bảo mật đối chiếu với hướng dẫn của giao thức [4][6].

Điều cần giữ tỉnh táo là giao thức vẫn đang tiến hóa, vài tính năng đã ở diện ngừng dùng, và các quyết định an ninh quan trọng nhất như phân quyền theo người dùng, che dữ liệu và xác nhận thao tác ghi vẫn do người triển khai chịu trách nhiệm. Hãy bắt đầu nhỏ, chỉ đọc, có nhật ký, rồi mới mở rộng.

Nguồn và phương pháp

Đây là nghiên cứu bàn giấy (desk research), không phải công trình khoa học đã qua bình duyệt. Bài viết không cài đặt, không biên dịch, không chạy và không đo đạc SDK; mọi nhận định kỹ thuật dựa trên các tệp tại commit 944ac1970ff05cf145fd5b28054d7ec5464ec550, ngày commit 11/10/2026, được kiểm tra ngày 12/10/2026. Các tệp đã đọc gồm README, LICENSE, SECURITY.md, docs/server.md, docs/client.md, docs/protocol.md, ROADMAP.md và docs/rough_edges.md [1][2][3][4][5][6][7][8].

Dự án được chọn từ kho lưu trữ GitHub Trending do cộng đồng sao lưu. Theo dữ liệu thu thập, kho này xuất hiện 5 lần, lần đầu ngày 12/02/2026, lần cuối ngày 31/07/2026, thuộc nhóm Tự động hóa và tích hợp; trang bằng chứng đầu tiên ghi vị trí thứ 7 trong danh sách Go [9]. Kho lưu trữ chỉ bao gồm danh sách Python, Go, JavaScript và Swift, thiếu các ngày 03/09/2026 và 12/10/2026, và không phải bảng xếp hạng top 100 chính thức.

Xem mã nguồn MCP Go SDK trên GitHub

Khám phá nghiên cứu của BDSG Foundation

Trao đổi về ứng dụng công nghệ cho doanh nghiệp