Strona główna / Artykuły / Protokół kontekstu modelu dla początkujących z FastMCP i Ollama

Protokół kontekstu modelu dla początkujących z FastMCP i Ollama

Przyswoić sobie role MCP – host, klient, serwer, transport – a następnie połączyć serwer narzędzia pogodowego z lokalnym modelem qwen3:8b za pomocą FastMCP i STDIO.

1841 słów

Model Context Protocol, zwykle skracany do MCP, to wspólny język służący do łączenia dużych modeli językowych z narzędziami i źródłami danych, do których same nie mogą uzyskać dostępu. Określanie go jako protokół podkreśla, że standaryzuje on sposób prowadzenia rozmowy; konkretne biblioteki realizują ten standard, dzięki czemu zespoły nie muszą samodzielnie tworzyć mechanizmów komunikacji i schematów wiadomości. FastMCP to jedna z takich implementacji, wykorzystywana w poniższym przewodniku.

Repozytorium towarzyszące: https://github.com/harshagangari747/MCPTutorial/tree/main

Wymagania wstępne

Demo polega na użyciu trzech pakietów: fastmcp, ollama oraz langchain-community. Proces inferymentu odbywa się przy użyciu lokalnego modelu qwen3:8b. Uruchom go za pomocą:

ollama run qwen3:8b

Przygotuj folder projektu, który zawiera już puste pliki szablonowe o nazwach weather_server_mcp.py i app.py, aby serwer i aplikacja miały określone miejsca przechowywania.

Rozumienie MCP

Samodzielnie LLM jest jedynie konwerterem tokenów – tokeny wchodzą, tokeny wychodzą. Nie łączy się z API pogody, nie otwiera baz danych ani nie odczytuje zegara systemowego, chyba że coś poza modelem wykona te czynności. Dostawcy chmury czasami dodają do swoich API własne narzędzia do uruchamiania, co jest wygodne w środowisku produkcyjnym, ale utrudnia zrozumienie samego protokołu. Uruchamianie lokalnego modelu za pomocą Ollamy sprawia, że eksperyment pozostaje zamknięty w sobie.

Spróbuj zadać pytanie w stylu „jaka jest pogoda dzisiaj we Włoszech?”. Typowa lokalna odpowiedź zaczyna się od przyznania, że nie ma aktualnych danych pogodowych. Mimo to zdanie zawiera trzy wskazówki, które system musi rozszyfrować: pogodę jako temat, „dzisiaj” jako datę oraz Włochy jako miejsce. Model potrzebuje sposobu na obliczenie lub pobraanie danych pogodowych, metody określenia daty „dzisiaj” oraz sposobu powiązania tej pogody z Włochami.

Oczywistym brakiem jest możliwość określenia daty w kalendarzu. Wagi modelu nie potrafią pewnie określić bieżącej daty. MCP staje się przydatne, gdy model może proponować narzędzia i argumenty, a otaczający go silnik faktycznie uruchamia te narzędzia, zwracając aktualne dane, które model może wykorzystać do sformułowania odpowiedzi.

Komponenty w MCP

W praktyce implementacja MCP zazwyczaj obejmuje kilka współpracujących elementów:

  1. Aprawna API — każda usługa, która już odpowiada na pytania z danej dziedziny, np. punkt końcowy pogodowy dostępny w Internecie.
  2. Server MCP — proces, który ukrywa sposób dostępu do API lub bazy danych i udostępnia narzędzia, które można wywołać.
  3. Host MCP — interfejs produktu, na przykład inteligentny planer podróży łączący rozumowanie modeli językowych z danymi w czasie rzeczywistym.
  4. Klient MCP — mostek znajdujący się wewnątrz hosta. Informuje model o dostępnych narzędziach, przekształca intencje modelu w żądania MCP oraz odpowiedzi MCP w kontekst przyjazny dla modelu.
  5. Szyna transportowa — JSON-RPC 2.0, przekazywany albo przez HTTP/SSE, gdy komponenty są zdalne, albo przez STDIO, gdy model i narzędzia znajdują się na tej samej maszynie.
  6. LLM — tutaj qwen3:8b udostępniany przez Ollamę.
  • Harness — opcjonalna orkiestracja, która łączy komponenty stosu przy użyciu mniejszej ilości ręcznie pisanych kodów łączących; w oryginalnym opisie jako przykład podano Goose AI.
  • Gdy te role są już określone, pytanie dotyczące pogody we Włoszech staje się kwestią choreografii zamiast pojedynczego wywołania modelu.

    Analogia

    Metafaora kierowania utrzymuje te role w stałej relacji. Intencją kierowania jest aplikacja gospodarzowa. Mózg stanowi LLM: odczytuje kontekst drogowy i decyduje się na przyspieszenie, hamowanie lub zmianę biegu, ale nie może nacisnąć pedałów. Kończyny odpowiadają serwerowi MCP; mięśnie i kości w obrębie kończyny to poszczególne narzędzia – jedna kończyna kieruje lub zmienia bieg, druga hamuje lub przyspiesza. Interfejs nerwowy pomiędzy mózgiem a mięśniem to klient MCP. Nerwy przenoszące impulsy elektryczne stanowią system transportu. Samochód to zewnętrzna API. Złożone ciało to zestaw elementów, które umożliwiają współpracę poszczególnych części.

    Zmapowanie w formie skróconej:

    • LLM → mózg
    • Server MCP → kończyna
    • Narzędzie → ruch mięśnia
    • Gospodarz MCP → intencja kierowania
    • Klient MCP → interfejs nerwowy
    • Transport → nerwy
    • API robocze → samochód
    • Zestaw elementów → struktura ciała

    To zdjęcie wystarcza, by serwer, klient i mechanizm transportu nie zmieniły się w jeden niewyraźny „plugin”.

    Funkcjonalność MCP

    Implementacja opiera się na określonych rolach: uruchomienie serwera, hosta, modelu LLM, mechanizmu transportu, opcjonalnie narzędzia pomocniczych oraz prawdziwej API lub usługi. Serwer abstrahuje API i udostępnia narzędzia. Każde narzędzie to pojedyncza akcja, o którą może poprosić model; model nigdy sam nie wykonuje żadnego wywołania HTTP. Klient zarówno publikuje katalog dostępnych funkcji, jak i przetwarza dane w obu kierunkach, dzięki czemu model i serwer pozostają luźno połączone.

    W przypadku serwera oferującego funkcje get_todays_date() oraz get_weather_data(city, date), zapytanie typu „Jaka jest dziś pogoda w Paryżu?” może przebiegać w następujący sposób:

    1. Model zauważa, że potrzebuje daty dzisiejszej.
    2. Pożąda od klienta MCP użycia funkcji get_todays_date.
    3. Klient przekazuje żądanie do serwera.
  • Serwer to realizuje.
  • Klient przekształca odpowiedź serwera pod potrzeby modelu.
  • Mimo posiadania daty, model nadal potrzebuje informacji o pogodzie w Paryżu.
  • Prosi klienta o wywołanie funkcji get_weather_data z podanym miastem i datą.
  • Klient przekształca tę intencję w żądanie do serwera.
  • Serwer wywołuje API pogodowe i zwraca zawartość odpowiedzi.
  • Klient ponownie przekształca tę zawartość pod potrzeby modelu.
  • Model prezentuje ostateczną odpowiedź użytkownikowi.
  • Zadania historyczne, które mieścią się w oknie szkoleniowym, mogą być rozwiązane wyłącznie na podstawie pamięci, ale celem MCP jest aktualny kontekst: daty i warunki pogodowe, które zmieniają się po szkoleniu.

    Projekt

    Przykład sprawia, że opis pogody jest konkretny. Serwer MCP zawiera logikę komunikacji z zewnętrznym API pogody. Aplikacja host tworzy klienta MCP, rejestruje serwer i wysyła zapytania do Ollamy. Izolacja dostępu do LLM w osobnym narzędziu ułatwia zrozumienie struktury komunikacji.

    Serwer 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()
    

    Funkcje, które łączą się z API, są oznaczone tagiem @server.tool(), co umożliwia ich publikację jako narzędzi. Dokumentacja na początku każdej funkcji nie służy jedynie dekoracji – informuje model, kiedy należy użyć danego narzędzia. W przykładzie dostępne są dwa takie narzędzia: jedno pobiera aktualną pogodę dla danej miasta, a drugie – pogodę z przeszłości dla tej samej miasta w określonym dniu.

    MCP Host, Client, LLM, metoda transportu

    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())
    

    Co się dzieje?

    Należy ustalić ścieżkę modułu serwera obok aplikacji host:

    server_path = Path(__file__).parent / "weather_server_mcp.py"
    

    Stwórz transport STDIO, który uruchomi ten moduł za pomocą bieżącego interpretera Pythona:

      # The transport method here is STDIO
        transport = StdioTransport(
            command=sys.executable,
            args=[str(server_path)],
        )
    

    Zainstaluj klienta MCP z tego transportu:

    mcp_client = Client(transport)
    

    Host posiada teraz zarejestrowaną ścieżkę serwera, wybrany transport oraz klienta. Przyłącz model za pośrednictwem Ollamy:

    llm = Ollama(model="qwen3:8b", temperature=0.5)
    

    Zapytaj klienta o katalog narzędzi opublikowany przez plik weather_server_mcp.py:

    mcp_tools = await mcp_client.list_tools()
    

    P przekaż ten katalog do promptu i poinstruuj model, aby odpowiadał jedynie nazwą narzędzia oraz parametrami. Po przetworzeniu wykonaj wybrane narzędzie:

    result = await mcp_client.call_tool(tool_name, params)
    

    Podstawa tego przewodnika polega zatem na: stworzeniu serwera, jego zarejestrowaniu, zarejestrowaniu klienta, przyłączeniu modelu LLM oraz wyborze transportu. Narzędzia typu Agent mogą ukrywać większość tych elementów; prosty pętla umożliwia widzenie każdego kroku w protokole podczas nauki.

    Łącznie rzecz biorąc, MCP to raczej podział zadań niż pojedyncze wezwanie biblioteki. Model proponuje; klient tłumaczy; serwer działa; mechanizm transmisji przekazuje wiadomości JSON-RPC; host zarządza pętlą skierowaną do użytkownika. Gdy te granice będą jasne, zamiana funkcji pogodowych na kalendarze, systemy CRM czy wewnętrzne narzędzia wyszukiwania sprowadza się głównie do napisania nowych narzędzi i ich dobrze udokumentowania, aby model mógł dokonać prawidłowego wyboru. Podczas działania pętli obserwuj, co model wysyła przed każdym wezwaniem narzędzia. Poprawny zapis pokazuje, że model podaje nazwę rzeczywiście istniejącego narzędzia, dostarcza klucze argumentów opisane w dokumentacji i czeka na dane od klienta przed sformułowaniem zdania skierowanego do użytkownika. Jeśli model wymyśla nazwę narzędzia, należy uprościć prompt lub poprawić opisy narzędzi. Jeśli serwer zwraca błąd, ten powinien zostać wyświetlony przez klienta, aby model mógł spróbować ponownie lub przeprosić zamiast tworzyć fałszywe informacje.

    Uzyskiwanie wartości pogodowych. Ta dyscyplina w zakresie informacji zwrotnych ma takie samo znaczenie jak początkowe połączenia.

    Literatura pokrewna

  • Przestań zwracać JSON: wysyłaj interaktywną interfejs użytkownika z aplikacjami MCP — Aplikacje MCP umożliwiają serwerom wysyłanie izolowanych interfejsów użytkownika razem z narzędziami, dzięki czemu ludzie mogą je zatwierdzać, konfigurować i obsługiwać bez opuszczania rozmowy z agentem.
  • Narzędzia MCP Vision z MiniCPM-V na Ollama — Udostępnij narzędzia do opisywania, OCR oraz porównywania obrazów przez MCP, aby Cursor i Claude Desktop mogły analizować skróty ekranu lokalnie.