Trzy prymitywy MCP: Resources, Tools, Prompts — co serwer może wystawić agentowi

przez Łukasz | cze 5, 2026

Artykuł 2 z serii MCP na części pierwsze Trzy role: host, klient, serwer


W poprzednim artykule ustaliliśmy że serwer MCP „wystawia możliwości dla agentów.” Brzmi ogólnie. W specyfikacji MCP te możliwości mają konkretną taksonomię — trzy typy i tylko trzy. Wszystko co serwer MCP może zaoferować agentowi jest jednym z nich.

Nazywają się: Tools, Resources i Prompts.

Rozróżnienie między nimi nie jest oczywiste na pierwszy rzut oka — wszystkie trzy dostarczają agentowi informacji lub możliwości. Różnica jest w naturze tej możliwości i w tym jak agent jej używa.

Tools — funkcje które agent wywołuje

Tools są najczęściej używanym prymitywem MCP. Jeśli słyszałeś „narzędzia MCP” — chodzi o tools.

Tool to funkcja którą agent może wywołać na serwerze. Serwer przyjmuje parametry wejściowe, wykonuje jakąś operację — zapytanie do bazy, wywołanie API, odczyt pliku, wykonanie skryptu — i zwraca wynik.

Schemat tool:

json
{
  "name": "search_term",
  "description": "Szukaj pojęcia w Słowniku Agentic Web po nazwie lub frazie",
  "inputSchema": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "Fraza do wyszukania — nazwa pojęcia, wariant lub opis"
      }
    },
    "required": ["query"]
  }
}

Trzy pola które każdy tool musi mieć:

name — unikalny identyfikator w obrębie serwera. Agent używa tej nazwy żeby wywołać tool.

description — opis co tool robi i kiedy go użyć. To jest krytyczne: agent decyduje które narzędzie wywołać na podstawie tego opisu. Zły opis = agent wywołuje złe narzędzie albo nie wywołuje wcale.

inputSchema — JSON Schema opisujący jakich parametrów tool oczekuje. Agent korzysta ze schematu żeby wiedzieć jakie parametry wpisać. Serwer może walidować wejście przed wykonaniem.

Jak wygląda wywołanie tool w JSON-RPC:

json
// 1. Klient pyta o listę dostępnych tools
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list"
}

// 2. Serwer odpowiada listą tools
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "search_term",
        "description": "Szukaj pojęcia w Słowniku Agentic Web...",
        "inputSchema": { ... }
      },
      {
        "name": "get_term",
        "description": "Pobierz pełną definicję pojęcia po slugu",
        "inputSchema": {
          "type": "object",
          "properties": {
            "slug": { "type": "string" }
          },
          "required": ["slug"]
        }
      }
    ]
  }
}

// 3. Klient wywołuje konkretny tool
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "search_term",
    "arguments": {
      "query": "agent-readiness"
    }
  }
}

// 4. Serwer zwraca wynik
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Znaleziono 3 pojęcia: agent-readiness, agent-ready..."
      }
    ]
  }
}

Ważna zasada: tool może mieć efekty uboczne. Wywołanie send_email naprawdę wysyła email. Wywołanie delete_filenaprawdę usuwa plik. Stąd specyfikacja MCP wymaga żeby host uzyskał explicite zgodę użytkownika przed wywołaniem toolów które mogą mieć nieodwracalne skutki.

Webflux Słownik MCP wystawia 7 toolów: get_term, search_term, list_clusters, get_cluster, get_by_layer, list_layers, create_term. Ostatni wymaga klucza API — przykład kontroli dostępu na poziomie samego toola.

Resources — dane które agent odczytuje

Resources to kontekst. Nie akcje — dane. Pliki, dokumenty, strony, konfiguracje, dane z baz które agent ma „przed oczami” gdy pracuje.

Różnica między tool a resource jest fundamentalna: tool wykonuje akcję i zwraca wynik, resource dostarcza dane do odczytania. Wywołanie query_database jako tool — to akcja. Plik konfiguracyjny aplikacji jako resource — to dane.

Schemat resource:

json
{
  "uri": "file:///workspace/config.json",
  "name": "Konfiguracja aplikacji",
  "description": "Główny plik konfiguracyjny — zawiera ustawienia środowiska, klucze API (zanonimizowane) i parametry deploymentu",
  "mimeType": "application/json"
}

Cztery pola:

uri — unikalny identyfikator resource. Może być ścieżką pliku (file:///), adresem HTTP, custom URI (memo://notes/123). URI to adres resource, nie URL do pobrania.

name — nazwa wyświetlana dla agenta i użytkownika.

description — co ten resource zawiera i kiedy jest przydatny.

mimeType — opcjonalny, ale przydatny: text/plain, application/json, text/markdown. Pozwala agentowi wiedzieć w jakim formacie są dane zanim je pobierze.

Jak wygląda odczyt resource:

json
// 1. Lista dostępnych resources
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "resources/list"
}

// 2. Serwer odpowiada
{
  "result": {
    "resources": [
      {
        "uri": "memo://notes/projekt-x",
        "name": "Notatki projektu X",
        "mimeType": "text/markdown"
      }
    ]
  }
}

// 3. Klient odczytuje konkretny resource
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "resources/read",
  "params": {
    "uri": "memo://notes/projekt-x"
  }
}

// 4. Serwer zwraca zawartość
{
  "result": {
    "contents": [
      {
        "uri": "memo://notes/projekt-x",
        "mimeType": "text/markdown",
        "text": "# Projekt X\n\n## Status\n..."
      }
    ]
  }
}

Resource templates — zaawansowana forma: URI z parametrami (jak URL template RFC 6570). Zamiast statycznej listy resources, serwer deklaruje wzorzec URI:

json
{
  "uriTemplate": "file:///workspace/{path}",
  "name": "Plik w workspace",
  "description": "Dowolny plik w katalogu workspace projektu"
}

Agent może teraz żądać file:///workspace/src/main.py bez tego żeby serwer musiał wcześniej wylistować wszystkie pliki.

Resources vs Tools dla danych — częsty dylemat. Kiedy read_file jako tool, kiedy plik jako resource?

Resource: dane statyczne lub rzadko zmieniające się, kontekst do pracy agenta, nie wymaga parametrów wyszukiwania.

Tool: dane dynamiczne, wymagają zapytania lub filtru, mają efekt uboczny (np. logowanie dostępu), wymagają parametrów wejściowych.

Prompts — szablony interakcji

Prompts to trzeci prymityw MCP — i najrzadziej używany. Nie chodzi tu o prompt engineering w sensie „jak napisać zapytanie do modelu”. Chodzi o gotowe szablony interakcji które serwer proponuje agentowi lub użytkownikowi.

Wyobraź sobie serwer MCP dla bazy kodu. Mógłby wystawić prompt analyze_pr który przyjmuje numer pull requesta i generuje gotowy prompt do analizy code review. Zamiast użytkownik pisze „przeanalizuj PR #123 pod kątem bezpieczeństwa, wydajności i zgodności ze standardami”, wywołuje gotowy szablon który robi to za niego.

Schemat prompt:

json
{
  "name": "analyze_security",
  "description": "Analiza bezpieczeństwa fragmentu kodu",
  "arguments": [
    {
      "name": "code",
      "description": "Kod do analizy",
      "required": true
    },
    {
      "name": "language",
      "description": "Język programowania (opcjonalnie)",
      "required": false
    }
  ]
}

Wywołanie prompt:

json
// Pobierz gotowy prompt z argumentami
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "prompts/get",
  "params": {
    "name": "analyze_security",
    "arguments": {
      "code": "def login(user, pwd): return db.query(f'SELECT * FROM users WHERE pwd={pwd}')",
      "language": "python"
    }
  }
}

// Serwer zwraca gotowe wiadomości do wysłania do modelu
{
  "result": {
    "description": "Analiza bezpieczeństwa kodu Python",
    "messages": [
      {
        "role": "user",
        "content": {
          "type": "text",
          "text": "Przeanalizuj poniższy kod Python pod kątem bezpieczeństwa. Zwróć uwagę na SQL injection, XSS, i inne podatności OWASP Top 10.\n\n```python\ndef login(user, pwd): return db.query(f'SELECT * FROM users WHERE pwd={pwd}')\n```"
        }
      }
    ]
  }
}

Serwer nie wywołuje modelu — zwraca gotowe wiadomości które host może przekazać do modelu. Host decyduje co z nimi zrobić.

Kiedy prompts mają sens: serwer MCP który dobrze rozumie swój domenowy kontekst może pakować wiedzę o tym jak pytać model w gotowe szablony. Użytkownik nie musi znać „prompt engineeringu” dla tej domeny — korzysta z wiedzy wypackowanej przez twórcę serwera.

W praktyce: większość serwerów MCP wystawia tylko tools. Resources są stosowane w narzędziach edycji kodu (pliki projektu). Prompts są rzadkością.

Capability negotiation — serwer mówi co potrafi

Serwer nie musi wystawiać wszystkich trzech prymitywów. Większość serwerów wystawia tylko tools. Część wystawia tools i resources. Prompts są opcjonalne.

Podczas inicjalizacji połączenia serwer deklaruje jakie prymitywy obsługuje:

json
// Odpowiedź serwera na initialize
{
  "result": {
    "protocolVersion": "2025-03-26",
    "capabilities": {
      "tools": {},
      "resources": { "subscribe": true },
      "prompts": {}
    },
    "serverInfo": {
      "name": "webflux-slownik",
      "version": "2.2.0"
    }
  }
}

resources.subscribe: true oznacza że serwer obsługuje subskrypcje — klient może subskrybować resource i dostawać powiadomienia gdy się zmieni. Przydatne dla plików które agent obserwuje.

Jeśli serwer nie zadeklaruje prompts w capabilities — klient wie że nie ma sensu wysyłać prompts/list. To jest właśnie capability negotiation z artykułu 1 w działaniu.

Jak agent „widzi” prymitywy

Specyfikacja MCP jest elastyczna w jednym miejscu — nie definiuje dokładnie jak host prezentuje prymitywy modelowi językowemu. Claude Desktop, Cursor i własny agent mogą to robić różnie.

W praktyce tools trafiają zazwyczaj do system promptu jako lista dostępnych funkcji z opisami i schematami. Resources mogą być wstawiane do kontekstu bezpośrednio albo na żądanie agenta. Prompts są wyświetlane użytkownikowi jako gotowe komendy.

Dlatego opis toola jest tak ważny — to nie jest dokumentacja dla dewelopera. To jest instrukcja dla modelu językowego który ma podjąć decyzję: wywołać ten tool czy nie? Z jakimi parametrami?

Zły opis: "search_term": "Wyszukuje termin"

Dobry opis: "search_term": "Wyszukaj pojęcie w Słowniku Agentic Web. Użyj gdy pytanie dotyczy definicji, wyjaśnienia lub kontekstu terminu z ekosystemu Agentic Web. Zwraca listę pasujących pojęć z definicjami."

Drugi opis mówi agentowi kiedy wywołać tool i czego oczekiwać. Pierwszy pozostawia to do interpretacji.

W następnym artykule: mamy prymitywy, mamy role — czas zobaczyć co faktycznie leci między klientem a serwerem. JSON-RPC pod spodem — anatomia wiadomości MCP i debugowanie przez curl.


Pojęcia ze słownika: MCP · JSON-RPC · Structured output · Tool use · Grounding

Spis treści

Kiedy nie budować agenta

Kiedy nie budować agenta

Cały ten hub uczy, jak budować agenty. Ten wpis jest o tym, że najczęściej nie powinieneś. Jest taka pokusa, która przychodzi po przeczytaniu kilku tekstów o agentach: zbudujmy agenta. Do obsługi maili. Do raportów. Do tego procesu, który teraz robi się ręcznie. Agent...