Trong bài 3 tôi đã so sánh Ollama, LM Studio, vLLM, llama.cpp ở góc nhìn runner. Bạn chọn được runner, model đã sẵn, prompt cũng OK. Vậy là xong chưa. Câu trả lời ngắn: chưa. Local LLM mà chỉ biết chat thì giống một con vẹt thông minh. Để nó trở thành agent thật, nó cần gọi tool: đọc file, truy vấn database, search web, gọi API nội bộ.

Đó là chỗ MCP (Model Context Protocol) bước vào.

Bài này tôi đi qua ba lựa chọn cụ thể để cắm MCP vào local LLM stack 2026: Ollama qua Open WebUI, Cursor IDE với Ollama backend, và gptme trong terminal. Mỗi cái có một profile reliability khác nhau, và tôi sẽ nói thẳng cái nào reliable, cái nào còn chua khi dùng homelab CPU.

Vì sao “MCP + local” quan trọng năm 2026

Khi bài MCP, chuẩn hoá tool layer viết, MCP còn chủ yếu live trên Claude Desktop và Claude Code. Hết 2025, gió đã đổi chiều. Cursor, Windsurf, Cline, Continue, Open WebUI, gptme đều đã adopt MCP. llama.cpp built-in web UI cũng đã merge MCP client support đầu 2026. MCP không còn là “thứ của Anthropic”, nó là chuẩn de facto cho tool layer.

Lý do bạn nên quan tâm khi đang chạy local LLM:

Chi phí. Một agent reasonable gọi tool 30-50 lần cho một task vừa phải. Với cloud, mỗi tool call là một round-trip kèm token cost. Với local, round-trip free, chỉ tốn điện và thời gian inference. Nếu bạn workflow nặng tool, local rẻ hơn rõ rệt.

Privacy. Database connection string, log production, source code internal. Bạn không muốn ba thứ đó đi qua API public. MCP server local + LLM local nghĩa là data không rời máy.

Offline. Quán cà phê WiFi rớt, đường truyền yếu, máy bay. Một stack hoàn toàn local vẫn chạy được. Cloud agent thì không.

Nhưng phải nói luôn: local + MCP năm 2026 vẫn rough. Không phải mọi model open-source biết “gọi tool”. Không phải mọi client xử lý tool-call format giống nhau. Và như tôi đã trải qua trên homelab Xeon E5 (không GPU driver), một agent loop dài có thể hang cả buổi.

Yêu cầu đầu vào: model phải biết tool calling

Đây là điểm vấp đầu tiên mà tài liệu hay bỏ qua. Tool calling không phải capability “tự nhiên có” của model. Model phải được fine-tune với data dạng tool-call thì mới phát ra JSON đúng format khi nhận tools array.

Tính đến giữa 2026, các model open-source có hỗ trợ tool calling chính thức trên Ollama:

ModelSizeTool callingGhi chú
Llama 3.1, 3.2, 3.38B, 70BYesLlama 3.1 8B là lựa chọn nhẹ phổ biến nhất
Qwen 2.5, Qwen 37B, 14B, 32BYesQwen 2.5 14B reliable hơn cho production agent
Mistral Small, Nemo7B, 12BYesMistral Small 24B mạnh nhất cho local tier
gpt-oss20B, 120BYesOpenAI open-weights, ra cuối 2025
Gemma 31B, 4B, 12B, 27BPhụ thuộc bảnGemma 3 chính thức tool calling từ 4B trở lên
Phi-3, Phi-3.53.8B, 14BHạn chếPhi tool support còn chưa stable bằng các họ trên

Để xem realtime danh sách, vào ollama.com/search?c=tools, filter capability “tools”.

Một lưu ý quan trọng từ thực tế homelab tôi đã viết trong reference homelab local LLM: Gemma 1 7B (model 2024 cũ) không fine-tune cho tool format Anthropic/OpenAI. Nếu bạn lỡ pull bản này về và cắm vào agent loop, model sẽ output sai format, agent retry vô tận, terminal hang. Đó không phải bug của Ollama, đó là model không có capability tương thích.

Rule of thumb: chọn Llama 3.1 8B hoặc Qwen 2.5 14B làm baseline. Cả hai đều có capability tag tools trên Ollama registry và reliable cho 90% workload.

Lựa chọn 1: Open WebUI + Ollama, MCP qua MCPO proxy

Open WebUI là cách dễ nhất để biến Ollama thành một “ChatGPT-like UI có tool”. Nó self-host được, chạy bằng Docker, UI gọn, và quan trọng nhất, có native MCP từ phiên bản 0.6.31.

Catch: Open WebUI native MCP chỉ nói chuyện được với MCP server qua transport Streamable HTTP. Đa số MCP server công khai (filesystem, GitHub, Slack) chạy stdio. Vậy nên đa số case bạn cần một proxy: MCPO (MCP-to-OpenAPI).

MCPO làm hai việc: nhận stdio MCP server, convert thành OpenAPI HTTP endpoint, expose ra cho Open WebUI gọi như tool thường. Tổng thể stack thành:

[Open WebUI]
   |
   |-- HTTP --> [MCPO proxy] -- stdio --> [filesystem MCP server]
   |                            \------> [github MCP server]
   |
   |-- HTTP --> [Ollama] -- inference --> [qwen2.5:14b model]

Docker compose tối giản:

services:
  ollama:
    image: ollama/ollama:latest
    ports:
      - "11434:11434"
    volumes:
      - ollama:/root/.ollama

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    ports:
      - "3000:8080"
    environment:
      - OLLAMA_BASE_URL=http://ollama:11434
    depends_on:
      - ollama

  mcpo:
    image: ghcr.io/open-webui/mcpo:latest
    ports:
      - "8080:8080"
    command:
      - --port=8080
      - --
      - npx
      - -y
      - "@modelcontextprotocol/server-filesystem"
      - "/data"
    volumes:
      - ./data:/data

volumes:
  ollama:

Sau khi docker compose up -d, vào Open WebUI Settings, thêm Tool URL trỏ vào http://mcpo:8080. Chọn model (Llama 3.1 8B hoặc Qwen 2.5 14B), gõ “list file trong thư mục /data” trong chat. Model sẽ phát ra tool call, MCPO chuyển qua filesystem server, kết quả trả về UI.

Điểm cộng:

  • Stack self-host trọn vẹn, không phụ thuộc cloud.
  • UI dùng được cho người không code, gần như ChatGPT.
  • MCPO open-source, tự maintain được, scale OK với 5-10 MCP server cùng lúc.

Điểm trừ:

  • Tốc độ phụ thuộc hardware. Trên Xeon E5 không GPU, Qwen 2.5 14B chạy 1-2 token/giây. Agent loop có 5 tool call sẽ tốn 5-10 phút.
  • MCPO thêm một process. Khi MCP server crash, log lẫn lộn giữa MCPO và Ollama.
  • Stream tool call chưa polish bằng Claude Desktop.

Lựa chọn 2: Cursor IDE với Ollama backend

Cursor 2026 là MCP client trưởng thành nhất phía dev tool. Nó hỗ trợ MCP từ Settings, hot-reload server config, log tool call ra panel rõ ràng. Cursor mặc định trỏ cloud (Anthropic, OpenAI), nhưng bạn có thể override backend sang Ollama.

Hai bước chính: redirect base URL, expose Ollama ra public hostname.

Bước 1: override OpenAI base URL. Vào Cursor Settings, Models, OpenAI API Key. Bật “Override OpenAI Base URL”, nhập http://localhost:11434/v1. Cursor sẽ gọi Ollama qua OpenAI-compatible endpoint. Lưu ý phải có /v1 ở cuối, thiếu là Cursor báo Request Failed mà không nói rõ.

Bước 2: tunneling. Cursor backend nhiều khi chạy sandbox không thấy localhost. Workaround: bật ngrok làm tunnel.

# Trên máy chạy Ollama
export OLLAMA_ORIGINS="*"
ollama serve

# Terminal khác
ngrok http 11434 --host-header="localhost:11434"

Lấy URL ngrok trả ra (kiểu https://xxxx.ngrok.io), paste vào Cursor base URL với /v1 suffix. Bây giờ Cursor gọi Ollama thành công.

Bước 3: MCP server config trong Cursor. File ~/.cursor/mcp.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/niafam/projects"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

Restart Cursor. Tool xuất hiện trong agent panel, có thể bật/tắt theo session.

Một gotcha quan trọng tài liệu Cursor không nói rõ: Ollama mặc định context window 4K-8K token, Cursor gửi prompt 30K+ token với codebase. Nếu bạn không set num_ctx, model sẽ drop quietly nửa context, tool call sai lung tung. Fix:

# Tạo Modelfile bump context
cat > Modelfile.qwen-coder-32k <<EOF
FROM qwen2.5-coder:14b
PARAMETER num_ctx 32768
EOF

ollama create qwen2.5-coder:14b-32k -f Modelfile.qwen-coder-32k

Rồi điểm Cursor sang model mới này. Tốc độ chậm hơn vì context dài, nhưng tool call cuối cùng đúng.

Điểm cộng:

  • IDE-first workflow, code completion + agent + MCP cùng một chỗ.
  • Tool call log rõ ràng, debug dễ.
  • MCP server hot-reload không cần restart.

Điểm trừ:

  • Phụ thuộc ngrok hoặc Cloudflare Tunnel để Cursor backend thấy local Ollama. Free tier ngrok có rate limit, không bền.
  • Trên CPU-only, model 14B + context 32K cực kỳ chậm. Khuyến nghị Apple Silicon M3+ hoặc RTX 3060 trở lên.

Lựa chọn 3: gptme trong terminal

gptme là cái tôi recommend cho người ưu tiên terminal-first, hoặc khi bạn chỉ cần “AI agent chạy nền với MCP” mà không cần GUI. Project open-source ở gptme.org, Python, cài bằng pipx.

Cấu hình MCP của gptme ở hai chỗ:

  • Global: ~/.config/gptme/config.toml
  • Project: gptme.toml ở workspace root

Ví dụ ~/.config/gptme/config.toml:

[prompt]
about_user = "Tôi là dev backend Python, ưu tiên Linux."

[env]
MODEL = "ollama/qwen2.5:14b"
OPENAI_BASE_URL = "http://localhost:11434/v1"

[mcp]
enabled = true

[[mcp.servers]]
name = "filesystem"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/niafam/projects"]

[[mcp.servers]]
name = "sqlite"
command = "uvx"
args = ["mcp-server-sqlite", "--db-path", "/home/niafam/data.db"]

Secret tách ra config.local.toml:

[[mcp.servers]]
name = "github"
env = { GITHUB_TOKEN = "ghp_xxxx" }

gptme merge hai file theo tên server, nên bạn để credentials riêng mà không cần duplicate config.

Chạy: gptme "list table trong sqlite database". gptme spawn MCP server, gọi tool, in kết quả ra terminal, kết thúc. Đây là kiểu one-shot, không loop.

Nếu muốn agent mode (loop tự retry, multi-turn): gptme --agent .... Lúc này gptme giữ session, gọi tool, nhận kết quả, gọi tiếp.

Từ thực tế homelab tôi đã từng debug (memory note 2026-05-18): gptme one-shot work tốt với Gemma 7B base, gptme agent mode thì hay hang. Lý do giống nhau như khi OpenClaw/OpenCode hang: agent mode expect model output JSON tool format chuẩn, model 7B base không fine-tune kỹ thì output sai. Workaround: dùng Qwen 2.5 14B hoặc Llama 3.1 8B (đều có tag tools), tránh model base không tool-fine-tuned.

Điểm cộng:

  • Lightweight, không daemon nặng. Spawn, work, exit.
  • Config toml rõ ràng, version control được.
  • One-shot mode cực kỳ reliable trên CPU yếu.

Điểm trừ:

  • TUI không phải GUI. Mới dùng có rào cản learning.
  • Agent loop chưa polish bằng Cursor hoặc Claude Code.

Giới hạn thực tế: tool format mismatch và agent loop hang

Đây là phần tôi muốn nói thật, không gloss-over như tutorial khác.

Vấn đề 1: tool format mismatch. OpenAI dùng JSON function-calling, Anthropic dùng XML tool-use, một số model local fine-tune cho format MIxed-up. Khi Cursor (OpenAI-compatible) gửi tool definitions sang Ollama, model phải hiểu đúng cú pháp. Nếu model fine-tune cho format khác, nó sẽ output text mô tả tool call thay vì JSON, client parse fail, agent loop retry vô tận.

Cách check nhanh: vào Ollama registry, model card phải có dòng Capabilities: tools. Nếu không có, model không guarantee phát ra JSON đúng format.

Vấn đề 2: agent loop hang trên CPU yếu. Một agent loop điển hình: prompt vào, model output tool call, client gọi tool, kết quả vào lại model, model output tiếp. Mỗi turn là một inference call. Với Qwen 2.5 14B trên Xeon E5 không GPU, mỗi turn 30-60 giây. Loop 10 turn là 5-10 phút. Nếu model output sai format ở turn nào đó, client retry, dồn lên 15-20 phút “hang” mà thực ra là model đang nghĩ.

Workaround:

  • Dùng model nhỏ hơn (Llama 3.1 8B thay vì Qwen 14B) cho agent loop.
  • Set timeout aggressive ở client (Cursor có cấu hình tool timeout).
  • Khi có thể, ưu tiên one-shot pattern: cho LLM context đầy đủ một lần, không loop nhiều turn.

Vấn đề 3: context overflow. Như đã nói ở Cursor section, Ollama default context 4K-8K. Codebase 100K dòng + MCP tool descriptions + chat history dễ vượt 32K. Bump num_ctx lên 32K-64K qua Modelfile, đánh đổi tốc độ.

Recommendation theo profile 2026

ProfileStack đề xuấtLý do
Apple Silicon M3+, single-userLM Studio hoặc gptme + Llama 3.1 8BSetup nhẹ, GPU built-in đủ nhanh, tool call reliable
Mac/Linux dev, code-firstCursor + Ollama + Qwen 2.5 14BIDE-integrated, MCP server hot-reload
Homelab Linux, headless, multi-userOpen WebUI + MCPO + Ollama + Llama 3.1 8BUI cho cả gia đình, MCP centralized qua MCPO
Homelab CPU yếu, hobbygptme one-shot + Phi-3 hoặc Gemma 3 4BTránh agent loop, ưu tiên model nhẹ
Production agent thậtKhông local. Dùng cloud (Claude, GPT-4o)Local 2026 chưa đủ tin cậy cho production loop

Đặc biệt lưu ý dòng cuối. Tôi viết bài này không phải để nói “local thay được cloud”. Local + MCP là một stack học, prototype, hobby project. Khi bạn cần SLA, observability, throughput nhiều người dùng cùng lúc, cloud agent vẫn ăn đứt. Local LLM 2026 reliable cho chat và one-shot, chưa reliable cho long-running agent loop với 30+ tool calls.

Cheatsheet so sánh ba lựa chọn

Tiêu chíOpen WebUI + MCPOCursor + Ollamagptme
Mục tiêu chínhSelf-host chat UI cho cả nhàIDE agent + code completionTerminal one-shot và agent
MCP transport hỗ trợStreamable HTTP (qua MCPO)stdio, SSE, HTTPstdio, SSE
Setup time15-20 phút20-30 phút (tính ngrok)5-10 phút
GUI cho non-devKhông (IDE)Không
Tốc độ trên CPU yếuChậm 1-2 tok/s với 14BRất chậm với 32K ctxOK khi one-shot
Reliability với agent loopTrung bìnhCaoThấp với 7B base
Multi-userMột user/máyMột user/process
CostFree, self-hostCursor Pro $20/mo + local freeFree
Hot-reload MCP serverPhải restart Open WebUIYesPhải restart process
Log debugMCPO + Open WebUI riêngCursor panel rõ ràngStdout terminal

Nhìn vào bảng, không có “winner” tuyệt đối. Open WebUI thắng khi bạn cần share stack cho nhiều người. Cursor thắng khi bạn là dev và muốn code-first. gptme thắng khi bạn cần một CLI agent gọn nhẹ trong shell script hoặc cron job.

Cấu hình hybrid: local MCP server + cloud LLM

Một pattern tôi thấy 2026 đang phổ biến mà ít người nói: MCP server local, LLM cloud. Tức là bạn vẫn dùng Claude hoặc GPT-4o cho reasoning (vì local 14B chưa đủ), nhưng MCP server thì self-host để giữ data private.

Ví dụ: bạn có MCP server đọc database production. Database query không leak ra cloud (chỉ kết quả query đi vào prompt). LLM cloud nhận kết quả qua MCP client (Cursor, Claude Code), reasoning, gọi MCP tool tiếp.

Lợi ích: bạn giữ được sức mạnh reasoning của cloud LLM, đồng thời control được phần data access qua MCP server local. Tradeoff: prompt và kết quả tool call vẫn đi qua cloud (chính sách provider sẽ áp dụng), nên data nhạy cảm trong kết quả query vẫn cần redact ở MCP server trước khi return.

Hybrid này không phải “fully local” theo nghĩa privacy maximalist. Nhưng với một dev solo cần balance giữa performance và privacy, đây là điểm sweet spot 2026.

Bảo mật MCP server local: ba điểm dễ quên

Tôi đã thấy nhiều người setup MCP server local rồi quên ba điểm bảo mật cơ bản.

1. Filesystem server scope. @modelcontextprotocol/server-filesystem / (root) là dấu chấm hỏi. Model có thể đọc và ghi mọi file. Luôn scope vào thư mục cụ thể, ví dụ /home/niafam/projects/blog-heniart. Đừng cho MCP filesystem thấy ~/.ssh, ~/.aws, .env ở cấp home.

2. Credentials trong MCP env. Nếu bạn nhúng GITHUB_TOKEN hay DATABASE_URL vào mcp.json, file đó là target. Cursor mcp.json lưu cleartext. Khuyến nghị: dùng env var ${GITHUB_TOKEN} rồi load từ shell env, hoặc dùng gptme config.local.toml (tách credentials ra khỏi config chính).

3. Network MCP server không có auth. Một số MCP server expose HTTP port (SSE transport). Nếu server đó không có auth và máy bạn không có firewall, ai trong cùng LAN có thể gọi tool. Đặt server sau reverse proxy có basic auth hoặc Tailscale ACL, đừng expose trần ra LAN.

Bước tiếp

Bài bài 5: failure modes của local agent sẽ đi sâu vào năm dạng failure phổ biến (agent loop hang, tool-call format mismatch, OOM, stop sequence không trigger, generation lặp), với checklist debug từ thực tế homelab. Nếu bạn vừa setup xong stack ở bài này và đụng issue, bài 5 là điểm dừng tiếp theo.

Một câu hỏi đáng nghĩ trước khi kết: bạn đã cài Cursor backend Ollama. Bạn gõ “refactor file này”. Cursor gọi tool read_file, kết quả 800 dòng code. Model gọi tool edit_file với content mới. Tool nào trong stack đang verify rằng content mới đúng cú pháp Python? Câu trả lời 2026: không có ai. Đây là một lý do nữa khiến local agent vẫn chưa thay được production cloud agent. Bạn phải tự lo phần verify, hoặc dùng cloud agent có chain verification built-in.

Cuối cùng, một câu rất thực tế. Tôi đang viết bài này từ M3 Max và verify lại trên homelab Xeon E5. Hai môi trường cho ra kết quả khác nhau hoàn toàn: M3 Max chạy Qwen 2.5 14B mượt 30 tok/s, agent loop xong trong 1 phút. Homelab chạy cùng model 1-2 tok/s, agent loop kéo 15-20 phút. Cùng setup phần mềm, khác hẳn về trải nghiệm. Đó là lý do tôi không thể recommend “homelab thấp cấu hình + agent loop” cho ai cả. Nếu bạn ở vị trí đó, hoặc upgrade hardware (RTX 3060 12GB sweet spot), hoặc stick với one-shot pattern và cloud cho agent.