Lần đầu tôi wire OpenClaw vào Ollama trên homelab Xeon E5, tôi gõ một task đơn giản: “list 5 file lớn nhất trong /var/log”. Agent loop kéo 23 phút, hết phút thứ 8 tôi đã bỏ đi pha cà phê, hết phút thứ 20 mới quay lại thấy terminal vẫn quay. Phút 23 nó báo timeout. Không có kết quả, không có log rõ. Cùng task đó tôi chạy lại bằng gptme one-shot trên cùng hardware, hai phút có output.

Đó là bài học hai mặt: local + MCP 2026 không phải plug-and-play, và chọn sai client sẽ đốt tiếng đồng hồ. Bài này tôi đi qua ba lựa chọn cụ thể để cắm MCP vào local LLM stack: Ollama qua Open WebUI, Cursor IDE với Ollama backend, và gptme trong terminal. Mỗi cái có profile reliability khác nhau, và tôi sẽ nói thẳng cái nào chạy được, cái nào còn chua khi dùng homelab CPU.

Bài 3 đã so xong runner. Bài này giả định bạn có Ollama hoặc llama.cpp endpoint sẵn, model đã pull, prompt cũng OK. Câu hỏi cần trả lời: 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, query database, search web, gọi API nội bộ. Đó là chỗ MCP (Model Context Protocol) bước vào.

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

Khi tôi viết bài MCP, chuẩn hoá tool layer, MCP còn chủ yếu sống 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 khá thực dụng. Cost: một agent reasonable gọi tool 30-50 lần cho một task vừa, 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; workload 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 cộng 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, stack hoàn toàn local vẫn chạy được, cloud agent thì không.

Phải nói thẳng: 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

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

Lưu ý quan trọng từ homelab tôi: Gemma 1 7B (model 2024 cũ) không fine-tune cho tool format Anthropic/OpenAI. 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: pick Llama 3.1 8B hoặc Qwen 2.5 14B làm baseline, cả hai đều có 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 nhận stdio MCP server, convert thành OpenAPI HTTP endpoint, expose ra cho Open WebUI gọi như tool thường.

[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 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 phát tool call, MCPO chuyển qua filesystem server, kết quả trả về UI.

Stack này thắng khi bạn cần share UI cho nhiều người. Self-host trọn vẹn, UI dùng được cho người không code, MCPO open-source và scale OK với 5-10 MCP server cùng lúc. Cá nhân tôi setup Open WebUI ở homelab cho cả nhà dùng chung, đỡ phải mỗi người tự cài Ollama. Tradeoff: tốc độ phụ thuộc hardware, trên Xeon E5 không GPU, Qwen 2.5 14B chạy 1-2 tok/s, agent loop 5 tool call 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. 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 có thể override backend sang Ollama.

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

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õ. Tôi đã từng debug hai tiếng vì quên cái /v1 này.

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.

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, bật/tắt theo session.

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 không set num_ctx, model sẽ drop quietly nửa context, tool call sai lung tung. Fix bằng 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

Trỏ Cursor sang model mới. Tốc độ chậm hơn vì context dài, tool call cuối cùng đúng.

Cursor là pick rõ ràng nếu bạn là dev và muốn IDE-first workflow: code completion, agent, MCP cùng một chỗ, tool call log rõ, MCP server hot-reload không cần restart. Trade-off là phụ thuộc ngrok hoặc Cloudflare Tunnel để Cursor backend thấy local Ollama. Free tier ngrok có rate limit, không bền cho daily driver. Trên CPU-only model 14B với context 32K cực kỳ chậm: khuyến nghị Apple Silicon M3+ hoặc RTX 3060 trở lên, đừng cố dùng combo Cursor + Xeon E5 CPU-only.

Lựa chọn 3: gptme trong terminal

gptme là cái tôi recommend khi bạn ưu tiên terminal-first hoặc 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 hoặc 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, 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 ....

Quan sát thật từ homelab: gptme one-shot chạy ổn 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 tôi đang dùng: pick Qwen 2.5 14B hoặc Llama 3.1 8B (đều có tag tools), tránh model base không tool-fine-tuned. Hoặc đơn giản hơn, stick với one-shot mode trên homelab yếu, agent mode để dành cho máy có GPU.

gptme thắng khi bạn cần CLI agent gọn nhẹ trong shell script hoặc cron job. Lightweight, không daemon, spawn-work-exit. Config toml rõ ràng, version control được. One-shot mode cực kỳ ổn định trên CPU yếu. Đổi lại, TUI có rào cản với người mới, agent loop chưa polish bằng Cursor hoặc Claude Code.

Ba giới hạn thực tế bạn sẽ đụng

Phần này tôi nói thật, không gloss-over như tutorial khác.

Tool format mismatch là vấp đầu tiên. 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 fine-tune cho format khác, nó output text mô tả tool call thay vì JSON, client parse fail, agent loop retry vô tận. Check nhanh: vào Ollama registry, model card phải có dòng Capabilities: tools. Không có thì model không guarantee phát ra JSON đúng format.

Agent loop hang trên CPU yếu là vấp thứ hai và đau nhất. Một 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 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 model đang nghĩ. Workaround tôi dùng: model nhỏ hơn cho agent loop (Llama 3.1 8B thay vì Qwen 14B), set timeout aggressive ở client (Cursor có cấu hình tool timeout), và khi có thể ưu tiên one-shot pattern (cho LLM context đầy đủ một lần, không loop nhiều turn).

Context overflow là vấp âm thầm. Ollama default context 4K-8K. Codebase 100K dòng cộng MCP tool descriptions cộng chat history dễ vượt 32K. Bump num_ctx lên 32K-64K qua Modelfile, đánh đổi tốc độ. Đừng phát hiện ra vấn đề này sau khi đã debug 4 giờ vì sao tool call sai liên tục.

Hybrid: MCP server local, LLM cloud

Một pattern 2026 đang phổ biến mà ít người nói: MCP server local, LLM cloud. 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ụ: MCP server đọc database production. 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: giữ sức mạnh reasoning của cloud LLM, đồng thời control 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 á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.

Cá nhân tôi thấy đây là sweet spot 2026 cho dev solo: không “fully local” theo nghĩa privacy maximalist, nhưng balance được performance và privacy. Tôi đang chạy combo này cho một số workflow: MCP server đọc note Obsidian vault local cộng Claude reasoning ở cloud. Note không leak (chỉ excerpt liên quan task hiện tại được paste vào prompt), Claude vẫn lo phần “thinking” tốt hơn local 14B.

Ba điểm bảo mật MCP server local dễ quên

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

Filesystem server scope quan trọng nhất. @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.

Credentials trong MCP env là điểm thứ hai. Nhúng GITHUB_TOKEN hay DATABASE_URL vào mcp.json thì 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.

Network MCP server không có auth là điểm thứ ba. 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.

Profile nào dùng gì

Apple Silicon M3+ single-user: LM Studio hoặc gptme + Llama 3.1 8B. Setup nhẹ, GPU built-in đủ nhanh, tool call reliable.

Mac/Linux dev code-first: Cursor + Ollama + Qwen 2.5 14B. IDE-integrated, MCP server hot-reload, log rõ.

Homelab Linux headless multi-user: Open WebUI + MCPO + Ollama + Llama 3.1 8B. UI cho cả gia đình, MCP centralized qua MCPO.

Homelab CPU yếu hobby: gptme one-shot + Phi-3 hoặc Gemma 3 4B. Tránh agent loop, ưu tiên model nhẹ.

Production agent thật: không local. Dùng cloud (Claude, GPT-4o). Local 2026 chưa đủ tin cậy cho production loop, 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. Khi cần SLA, observability, throughput nhiều người dùng cùng lúc, cloud agent vẫn ăn đứt.

Bước tiếp

Bài 5: failure modes của local agent đ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, đó là điểm dừng tiếp theo.

Một câu hỏi đáng nghĩ trước khi đóng bài: bạn đã cài Cursor backend Ollama, 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.

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 kết quả khác hẳ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 recommend “homelab thấp cấu hình + agent loop” cho ai. Hoặc upgrade hardware (RTX 3060 12GB là sweet spot 2026), hoặc stick với one-shot pattern và cloud cho agent.

Tham khảo