Serwer MCP i własne zasoby (resources)

Czym są resources (zasoby)?

Resources to dane i kontekst udostępniane modelowi – można je porównać do źródeł danych tylko do odczytu, analogicznych do endpointów GET w tradycyjnym API.

Zasoby w MCP reprezentują określone informacje (pliki, dokumenty, rekordy, itp.), które mogą zostać wczytane do kontekstu modelu na żądanie. Ważne jest, że zasoby nie powinny mieć efektów ubocznych – ich rola to dostarczanie treści (a nie np. modyfikacja danych).
Każdy zasób jest identyfikowany przez unikalny URI oraz opcjonalnie może przyjmować parametry (np. identyfikator dokumentu w URI).

UWAGA: Protokół MCP pozwala Agentowi korzystać z Resources, ale… sposób wykorzystania zależy od konkretnej implementacji klienta MCP np. Copilot czy Claude.

W VS Code Copilot, aby skorzystać z zasobów (resources) musimy je dodać ręcznie do kontekstu rozmowy!. W interfejsie Copilot Chat należy wybrać opcję “Add Context… > MCP Resources”, a następnie wskazać dostępny zasób z listy.

Oficjalna dokumentacja Extending Copilot coding agent with the Model Context Protocol (MCP): https://docs.github.com/en/copilot/how-tos/agents/copilot-coding-agent/extending-copilot-coding-agent-with-mcp

Cały wynikowy kod

Zawartość pliku main.ts:

import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';


const server = new McpServer({
  name: 'mcp-server-countries',
  version: '1.0.0',
});


server.registerPrompt(
  'get-all-countries-prompt',
  {
    title: 'Get all countries details',
    description: 'Get all countries details from the REST API',
    argsSchema: {},
  },
  () => ({
    messages: [
      {
        role: 'user',
        content: {
          type: 'text',
          text: `Use tool to get all countries details from the REST API`,
        },
      },
    ],
  })
);


server.registerPrompt(
  'get-a-country-prompt',
  {
    title: 'Get a specific country details',
    description: 'Get a specific country details from the REST API',
    argsSchema: { countryName: z.string() },
  },
  ({ countryName }) => ({
    messages: [
      {
        role: 'user',
        content: {
          type: 'text',
          text: `Use tool to get a specific country details "${countryName}" from the REST API`,
        },
      },
    ],
  })
);


server.registerTool(
  'get-all-countries',
  {
    title: 'Get all countries',
    description: 'Tool to get all countries from the REST API',
    inputSchema: {},
  },
  async () => {
    const response = await fetch(
      'https://restcountries.com/v3.1/all?fields=name,capital,region,population,area,flags,languages,currencies'
    );
    const data = await response.json();
    return {
      content: [
        {
          type: 'text',
          text: JSON.stringify(data),
        },
      ],
    };
  }
);


server.registerTool(
  'get-a-country',
  {
    title: 'Get a specific country details',
    description: 'Tool to get a specific country details from the REST API based on country name',
    inputSchema: {
      countryName: z.string().describe('The name of the country to get'),
    },
  },
  async ({ countryName }) => {
    const response = await fetch(`https://restcountries.com/v3.1/name/${countryName}`);
    const text = await response.text();
    return {
      content: [
        {
          type: 'text',
          text,
        },
      ],
    };
  }
);




// Register a dynamic greeting resource
server.registerResource(
  "greeting",
  new ResourceTemplate("greeting://{name}", { list: undefined }),
  {
    title: "Greeting Resource", // Display name for UI
    description: "Dynamic greeting generator",
  },
  async (uri, { name }) => ({
    contents: [
      {
        uri: uri.href,
        text: `Hello, ${name}!`,
      },
    ],
  })
);




// Register a simple resource without parameters
const regionDataSet = [
  { region: "Europe", avgTemperature: 10 },
  { region: "Americas", avgTemperature: 15 },
  { region: "Asia", avgTemperature: 20 },
  { region: "Africa", avgTemperature: 25 },
  { region: "Oceania", avgTemperature: 30 },
  { region: "Antarctica", avgTemperature: -5 },
  { region: "Polar", avgTemperature: -10 },
  { region: "R'lyeh", avgTemperature: -2 },
];


server.registerResource(
  "regions-resource",
  new ResourceTemplate("regions://all", {
    list: undefined,
  }),
  {
    title: "All Regions (Static)",
    description: "Static resource with regions",
  },
  async (uri) => {
    // This is a static resource, so we return the predefined data
    const data = regionDataSet;
    return {
      contents: [
        {
          uri: "regions://all",
          text: JSON.stringify(data, null, 2),
          mimeType: "application/json",
        },
      ],
    };
  }
);




const transport = new StdioServerTransport();
server.connect(transport);

Prompt do testów serwera MCP

Przykładowe prompty do testów:

use tool to get 5 countries that matches each region with temperature below 0 from the resource list

Ten prompt instruuje agenta, by skorzystał z narzędzia (use tool) i przeszukał zasób danych (from the resource list). Filtruje kraje według regionu i temperatury.
✅ Jest dobry na start – szybki test integracji narzędzia z zasobem.
🚫 Może dawać nieprzewidywalne wyniki i wyniki mogą się różnić w zależności od momentu wykorzystania.

Możesz skorzystać z bardziej precyzyjnego zapytania:

use tool to get all countries and then find 5 countries that matches each region with temperature below 0 from the resource list

Prompt dzieli operację na dwa etapy: pobranie pełnych danych, a potem ich filtrowanie.
✅ Dzięki temu agent rzadziej pomija dane i wykonuje pełną analizę.

Jeśli chcesz, by agent z MCP wykonał działania w konkretnej kolejności, możesz sformułować prompt jako serię kroków. Taki sposób zwiększa szansę na logiczne wykonanie wszystkich operacji – zwłaszcza w przypadku bardziej złożonych zapytań.

Follow these steps:
1. Load region data from the resource list (regions with avgTemperature)
2. From this list, identify regions where avgTemperature is below 0
3. Use the tool to fetch the full list of countries from the API
4. For each country, check which region it belongs to
5. Select countries that belong to the cold regions (from step 2)
6. For each region, return up to 5 matching countries

Taki prompt zachowuje ten sam cel co:

use tool to get all countries and then find 5 countries that matches each region with temperature below 0 from the resource list

…ale rozdziela działanie na jasno określone etapy, co poprawia zrozumienie zadania przez agenta!

Dobre praktyki:

  • ✅ Wskazuj narzędzie i zasób: use tool, from resource list
  • ✅ Doprecyzuj dane wejściowe i warunki filtracji
  • ✅ Dziel operacje na etapy i kroki (“get all”, potem “filter”)
  • 🚫 Unikaj ogólników typu “analyze the data” – lepiej: “group by region, filter by temperature”
  • ✅ Testuj różne warianty

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *