Протакол контексту модэля для пачатківцаў з FastMCP і Ollama
Выучыце ролі MCP — хост, кліент, сервер, транспорт — а пасля пад’яжыце сервер з інструментамі для працы з пагодай да локальной моделі qwen3:8b через FastMCP і STDIO.
Model Context Protocol, які частае скарацьовваюцца як MCP, — это спяшчаны язык для падключэння большых мовных модэляў да інструментаў і источнікаў дадзенаў, да якіх яны самыя не можаць дасягнуць. Адзначэнне яго як пратакола падчервягае, што ён стандартызуе формат размовы; конкрэтныя бібліятекі пасля таго рэалізуюць гэты стандарт, так што каманды не змушаны самыя ствараць сокеты і шэмы паведамленняў. FastMCP — адна з такіх рэалізацый, якая викорыстоўваецца у практычным кераванні нижэй.
Репазітарыю-сааднік: https://github.com/harshagangari747/MCPTutorial/tree/main
Прыямыя выкананні
Дэмант завісіць ад трох пакетаў: fastmcp, ollama і langchain-community. Аналіз дадзенаў выкананы на локальным модэлі qwen3:8b. Запускайце яго так:
ollama run qwen3:8b
Падготавьце папку для проекта, яка вжо мячыць порожнія шаблоны пад назвамі weather_server_mcp.py і app.py, каб сервер і хост мелі чыстае месца размешчэння.
Розумеўце MCP
Якщо не втручацца, LLM ёсць трансдыютор токенаў. Токаны заходзяць; токаны выходзяць. Ён не вызывае API па паветра, не ачынае базы дадзэння і не чытае системны гадзіннік, як толькі штояць за межамі модэлю не выкарыстоўваецца для адбывання такіх дзействаў. Прадаўцы хмары інодзе дадаюць да своіх API прыналежныя інструменты для запуску, што ўдобна пад час роботы у працэсе, але стварае труднасці, калі метай ёсць аналіз самага протаколу. Запуск локальнага модэлю через Ollama дазволяе заставіць эксперымент самастойным.
Паскуюце запытаку на кшталт «Якая пагода сёння в Італіі?». Тыповая местная адказ усвядомляе, што няма рэальнага даных пра пагоду. Усё-такі ў гэтым запытанні є тры парадакты, якія система должна разгледзець: пагода як тэма, «сёння» як дата і Італія як месца. Модэлю патрэбны спосабы вычыслення або запрашання даных пра пагоду, спосабы адначасовага визначэння даты «сёння» і спосабы паўязкі гэтай пагоды з Італіяй.
Відсутнае визначэння даты ёст крытычныя прасоўкай. Вагі модэлю ня могуць надзеяна адначасова ведаць текущую дату. MCP становіцца корыстным, калі модэль можа запрасіць адпаведныя інструменты і аргументы, а супакоўкі выканаюць гэтыя інструменты, вяртаючы свежыя даны, якія модэль можа аднаць у свой адказ.
Компаненты MCP
У практычным выкарыстоўванні MCP зазвычай называюць кальколькі супрацоўнае элементаў:
- Рабочы API — будь-яка служба, яка вже адказвае на запыткі домэна, напрыклад канцэнтр па пагоду, які можна знайсці ў Інтэрнете.
- Сервер MCP — процэс, які маскіруе спосаб прыўязкі да API або базы дадзенаў і публікуе інструменты, якія можна вызваць.
- Хост MCP — інтерфейс продукту, напрыклад розумны планавальнік паездак, який спалюеяе логіку LLM з жывымі дадзеннямі.
- Кліент MCP — мост, які знаходзіцца ўнутры хоста. Ён паведамляе модэлю, якія інструменты існуюць, ператварае намеры модэля на запыткі MCP і ператварае адпаведзі MCP у контэкст, зручны для модэля.
- Шар транспорту — JSON-RPC 2.0, які передаецца або через HTTP/SSE, калі компаненты знаходзяцца на аддаленых серверах, або через STDIO, калі модэль і інструменты знаходзяцца на адной машыне.
- LLM — тут
qwen3:8b, які аддаецца через Ollama.
Калі такі ролі ўжо названы, запит пра пагоду в Італіі стае частым процесам замест адзінаго вызову модэлі.
Аналагія
Адаптаваная метафора дапамагае прыtrzymаць ролі ў сваім стані. Намер кераваць — гаспадарскі прыкладны праграма. Мозг — гэта LLM: ён чытае контекст дарогі і вырашае праспячваць, гальваваць або змінюваць передачу, але не можа нажымаць педалі. Канаткі адпавядаюць серверу MCP; мышцы і кості ў канатку — гэта адзінаковыя інструменты: адны канаткі керуюць або змінюють передачу, іншыя гальваюць або праспячваюць. Нервовы інтэрфейс межу мозгам і мышцай — гэта кліент MCP. Нервы, якія пераводзяць электрычныя імпульсы, — гэта средства транспорту. Автомабіль — гэта зовнішняя API. Складаны корпус — гэта креплень, який дапамагае часткам саўместна працаваць.
Скорачаная карточка:
- LLM → мозг
- Сервер MCP → канатак
- Інструмент → дзеянне мышцы
- Гаспадар MCP → намер керавання
- Кліент MCP → нервовы інтэрфейс
- Средства транспорту → нервы
- Рабочая API → автомабіль
- Креплень → складаны корпус
Этага фота якраз дастычна, каб сервер, кліент і механізм перадачы дадзеных не злучыліся ў аднаго невялікага “плагіна”.
Функцыонаванне MCP
Адбудова выконвачыцца са адпаведным распадам на ролі: стварэнне сервера, хоста, LLM, механізма перадачы дадзеных, за пажылостнасцю — інструменту для канектавання, а таксама справжнья API чы ўслуга. Сервер абстрагуе API і надае інструменты. Кожны інструмент — цэлае дзеянне, якое модель можа запрашваць; сама модель ніколі не выкананяе HTTP-званак. Кліент адночасна праказвае каталог і здзейснюе пераклад у обох направленнях, тады модель і сервер застаюцца слабкаясно з’ўязанымі.
Якшто сервер прадае методы get_todays_date() і get_weather_data(city, date), запит на кшталт “Якая погода сёньня ў Парыжы?” можа выглядаць так:
- Модель усвядомляе, што ёй патрэбна дата сёньня.
- Яна прасіць кліента MCP выкарыстаць
get_todays_date. - Кліент перадае запит серверу.
get_weather_data з назвай горада і датой.Історычныя запыты, якія падпадаюць пад період навчання, могу быть адпаведзены толькі на базе памяці, але сэнс MCP — гэта чыргавы контекст: даты і пагода, якія зменяюцца пасля навчання.
Праект
Эты прыклад дапамагае ўтварыць конкрэтыя нарадзеныя пра пагоду. Сервер MCP карыстаецца логікай, якая ведае справу з зовнішнім API пагоды. Аплікацыя-хост стварае кліента MCP, рэгіструець сервер і запрашвае дапамогу у Ollama. Ізоляцыя доступу да LLM у ўласным памагальніку дапамагае зрозумець структуру передачы даных.
Сервер MCP
# MCP Server
# weather_server_mcp.py
from fastmcp import FastMCP
import requests
# This is a server instance that we register in our host
server = FastMCP("weather-mcp-server")
# Third party api data
WEATHER_API_KEY = "api_key_here"
WEATHER_BASE_URL = "https://api.weatherapi.com/v1/"
# Tool 1
@server.tool()
def get_weather_data(city: str) -> float:
"""Get current temperature in Celsius"""
response = requests.get(
WEATHER_BASE_URL + "current.json",
params={"key": WEATHER_API_KEY, "q": city},
)
response.raise_for_status()
return response.json()["current"]["temp_c"]
# Tool 2
@server.tool()
def get_historical_weather_data(city: str, date: str) -> float:
"""Get max temperature for a historical date"""
response = requests.get(
WEATHER_BASE_URL + "history.json",
params={"key": WEATHER_API_KEY, "q": city, "dt": date},
)
response.raise_for_status()
return response.json()["forecast"]["forecastday"][0]["day"]["maxtemp_c"]
if __name__ == "__main__":
server.run()
Функцыі, якіе звяжываюцца з API, адзначаюцца тэгам @server.tool(), што дазволяе выклікваць іх як інструменты. Докстрынгі, якія знаходзяцца на пачатку кожной функцыі, не ўжо атрыбуты; яны паведамляюць модэлю, калі трэба выкорыстоўваць той чы іншы інструмент. У прыкладзе є два інструмента: адны выкарыстоўваецца для запытання пра текущую пагоду ў горадзе, а другі — для запытання пра пагоду ў горадзе у пэўны дзень у минулом.
MCP Host, Client, LLM, метод передачы
import asyncio
import sys
import json
from pathlib import Path
from langchain_community.llms import Ollama
from fastmcp import Client
from fastmcp.client.transports import StdioTransport
async def main():
# We mention the mcp server path.
server_path = Path(__file__).parent / "weather_server_mcp.py"
# The transport method here is STDIO
transport = StdioTransport(
command=sys.executable,
args=[str(server_path)],
)
# Register the MCP Client
mcp_client = Client(transport)
# LLM via Ollama
llm = Ollama(model="qwen3:8b", temperature=0.5)
async with mcp_client:
print("✓ Connected to MCP server!")
# We can now access that tools are present in the weather server mcp now.
mcp_tools = await mcp_client.list_tools()
tools_info = "\n".join([f"- {t.name}: {t.description or t.name}" for t in mcp_tools])
print(f"✓ Available tools:\n{tools_info}\n")
# Interactive loop
while True:
question = input("🌤️ Ask: ").strip()
if question.lower() == 'exit':
break
try:
# Step 1: Ask LLM to decide which tool to use
decision_prompt = f"""Given the question: "{question}"
Available tools:
{tools_info}
Respond with ONLY a JSON object (no other text):
{{"tool": "tool_name", "params": {{"city": "city_name"}}}}
For get_historical_weather_data, use: {{"tool": "get_historical_weather_data", "params": {{"city": "city_name", "date": "YYYY-MM-DD"}}}}"""
print(f"\n📍 Processing: {question}")
llm_response = llm.invoke(decision_prompt)
# Step 2: Parse JSON from LLM response
json_start = llm_response.find('{')
json_end = llm_response.rfind('}') + 1
if json_start == -1 or json_end == 0:
print("❌ LLM didn't return valid tool call")
continue
json_str = llm_response[json_start:json_end]
tool_call = json.loads(json_str)
print("Tool call: ", tool_call)
# Handle array responses
if isinstance(tool_call, list):
tool_call = tool_call[0]
tool_name = tool_call.get("tool")
params = tool_call.get("params", {})
print(f"🔧 Calling: {tool_name} with {params}")
# Step 3: Call MCP tool. This is where we actually call the tool.
result = await mcp_client.call_tool(tool_name, params)
answer = result.content[0].text
print(f"✓ Answer: {answer}°C\n")
except json.JSONDecodeError as e:
print(f"❌ JSON parsing error: {e}")
except Exception as e:
print(f"❌ Error: {e}\n")
if __name__ == "__main__":
asyncio.run(main())
Што адбываецца?
Неабходна выявіць шлях да модуля сервера, які знаходзіцца ля аплікацыі-хоста:
server_path = Path(__file__).parent / "weather_server_mcp.py"
Створыце транспорт STDIO, які запускае той модуль з ныямчынным інтэрпретатаром Python:
# The transport method here is STDIO
transport = StdioTransport(
command=sys.executable,
args=[str(server_path)],
)
Створыце экзанпляр кліента MCP з таго транспорту:
mcp_client = Client(transport)
У хоста тепер ёсць зарэгістраваны шлях сервера, выбраны транспорт і кліент. Прыўяжыце модэль через Ollama:
llm = Ollama(model="qwen3:8b", temperature=0.5)
Запытайце кліента пра каталог інструментоў, выданы weather_server_mcp.py:
mcp_tools = await mcp_client.list_tools()
Перадайце гэты каталог у запит і паведаміце модэлю адпавядаць толькі іменем і параметрамі інструменту. Пасля парсавання запытайце выбраны інструмент:
result = await mcp_client.call_tool(tool_name, params)
Такім чынам, аснова навучальнага курсу: стварыце сервер, зарэгіструйце яго, зарэгіструйце кліент, прыўяжыце LLM і выберыце транспорт. Агенты могу скрыць большую частку гэтых наладок; простая петля дазволяе бачыць кожны крок протаколу пад час навучэння.
У сукупнасці MCP — это не столькаа адзін вызов бібліятэкі, сколькая распад працы. Модель прыдумвае; кліент перакладае; сервер дзейнае; канал адчынення перадае паведамленні JSON-RPC; хост керуе цыклам, які спрацоўвае з корыстнікам. Калі гэтыя межы будуць чыстымі, замена паведамленняў пра пагоду на календары, CRM-сістэмы чыста внутранія пошукавая функцыя — гэта пераважна праблема стварэння новых інструментоў і ўсё адносна добрая документацыі, каб модель могла правильна выбраць. Калі цыкл працуе, старанна адзірвайте, што модель выдае перад кожным вызам інструменту. Здаровы траг паказвае, калі модель называе інструмент, які насправды існуе, падае ключы аргументаў, якія описаны ў докстрынгу, і чакае, пакуль кліент вернёў дадзеныя, перш чым складаць рэченне для корыстніка. Якщо модель выдумвае назву інструменту, падкрэпіце запит або паспрабуйце паўнейша удосконаліць описы інструментоў. Якщо сервер выдае памылку, яна павінна быть паказана через кліент, каб модель могла спробаваць зноў чыста папрашыць вялікіх перакананняў уместо таго, каб ствараць халюцинаціі.
Збір данных працэўнае абставіны паветра. Гэтая дисцыпліна зворотнага зв’язку мае такое ж значэнне, як і пачатковая працэўнае падключэння.