CodeGym /Kurslar /ChatGPT Apps /MCP mesaj formatı: requests, replies, notifications, tool...

MCP mesaj formatı: requests, replies, notifications, tools/resources/prompts

ChatGPT Apps
Səviyyə , Dərs
Mövcuddur

1. MCP və JSON‑RPC: bir dəfə anlayanda kifayət edən “darıxdırıcı” əsas

Ötən mühazirədə MCP‑nin niyə lazım olduğundan və onun Apps SDK yığınına necə oturduğundan danışmışdıq. Bu mühazirədə diqqəti ən “darıxdırıcı” təbəqəyə — MCP mesajlarının formatına daraldacağıq ki, siz xam JSON loglarını inamla oxuya biləsiniz və ChatGPT‑nin serverinizə nə göndərdiyini, serverin nə cavab verdiyini başa düşəsiniz.

MCP verilənlərin daşınması üçün JSON‑RPC 2.0‑dan istifadə edir: bütün sorğular, cavablar və bildirişlər — proqnozlaşdırılan sxemə malik adi JSON obyektləridir.

Yəni “hər xidmət öz formatını uydurur” əvəzinə, bazada bir müqavilə var:

  • sorğunun məcburi jsonrpc sahəsi (adətən "2.0"), unikal id, metodun sətir adı method və parametrlərdən ibarət params obyekti olur;
  • cavab sorğu ilə id üzrə əlaqələndirilir və ya result, ya da error saxlayır;
  • bildirişlər (notifications) sorğulara bənzəyir, lakin id olmur və onlara cavab gəlməyəcək.

Təxminən belə görünür:


{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tools/list",
  "params": {
    "cursor": null
  }
}

Bu, request‑dir. Uğurlu halda cavab:

{
  "jsonrpc": "2.0",
  "id": 42,
  "result": {
    "tools": [],
    "nextCursor": null
  }
}

Əgər beyninizdə “bu axı adi RPC‑dir” fikri canlandısa — elə dədir. MCP sadəcə olaraq hansı metodların mövcud olduğunu (tools/list, tools/call, resources/list, prompts/list, …) və hansı formatda parametrlər gözlədiyini və verilənləri qaytardığını dəqiqləşdirir.

Vacib hiss: JSON‑RPC “sorğu–cavab–bildiriş” karkasıdır. MCP isə “məhz hansı sorğular var və içində nə olur”.

2. Request: MCP nəyisə necə istəkləndirir

Sorğulardan başlayaq. Onlar həmişə “kimsə nəsə etmək istəyir” istiqamətində gedir. Adətən bu, müştəri → server (ChatGPT → sizin MCP serveriniz) olur, lakin MCP əks sorğuları da qəbul edir — server müştəridən sampling və ya elicitation istəyəndə. Bu mühazirədə ilk növbədə klassik varianta baxacağıq: müştəri serverdən istəyir.

Hər bir MCP request‑in üç əsas sahəsi var:

  1. jsonrpc — JSON‑RPC protokolunun versiyası, adətən "2.0".
  2. id — sorğunun identifikatoru; istənilən JSON tipi ola bilər, praktikada çox vaxt rəqəm və ya sətir. Əsas odur ki, aktiv sorğular üçün id unikal olsun.
  3. method"tools/list" və ya "tools/call" kimi sətir. MCP icazə verilən metodların toplusunu müəyyənləşdirir.

Və konkret metodun parametrlərinin olduğu params obyekti var.

Nümunə: alətlər siyahısının sorğusu

Təsəvvür edək ki, ChatGPT indicə MCP serverinizə qoşulub və hansı tools çağırmaq ola biləcəyini bilmək istəyir. O, təxminən belə sorğu göndərəcək:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "cursor": null
  }
}

cursor sahəsi səhifələmə üçün lazımdır — əgər alətlər çoxdursa, server onları hissə‑hissə qaytara bilər.

Tədris tətbiqimiz (hədiyyə seçimi) üçün hələlik darıxdırıcı olacaq: bir‑iki alət, amma protokol eyni qalır. Hələ ki, buna intuitiv nümunə kimi baxın; rəsmi strukturlara alətlər bölməsində sonra qayıdacağıq.

Nümunə: alətin çağırılması (tools/call)

İndi bir az maraqlısı. Fərz edək ki, sizdə artıq MCP‑tool suggest_gifts var və onu MCP server haqqında mühazirədə reallaşdırmağı planlaşdırırsınız. O, bu parametrləri gözləyir:

  • occasion — səbəb (Birthday, Wedding, …),
  • budget — dollarda rəqəm,
  • recipient — kimə hədiyyə etdiyimizi təsvir edən sətir.

ChatGPT bu alətdən istifadə etməyə qərar verdikdə, MCP sorğusunu belə formalaşdıracaq:

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "suggest_gifts",
    "arguments": {
      "occasion": "birthday",
      "budget": 100,
      "recipient": "friend who loves board games"
    }
  }
}

Bir neçə məqama diqqət yetirin.

Birincisi, alətin adı server tərəfində elan etdiyinizdən götürülür (server.registerTool("suggest_gifts", …)). İkincisi, arguments obyekti alətin təsvirində əlavə edəcəyiniz JSON Schema‑ya uyğun olmalıdır.

Əgər GPT sxemaya uyğun olmayan arqumentlər göndərməyə cəhd etsə (məsələn, budget: "yüz dollar"), server implementasiyadan asılı olaraq bunu protokol səviyyəsində və ya biznes məntiqi səviyyəsində səhv kimi qaytara bilər. Hələlik əsas olan belə sorğunun ümumi formasını tutmaqdır; aşağıdakı tools bölməsində eyni mesajlara daha sistemli şəkildə baxacağıq.

Resurslar və promptlar üçün requests

Resurslara və promptlara sorğular da oxşar görünür. MCP spesifikasiyası aşağıdakı metodları müəyyən edir:

  • resources/list — mövcud resursları sadalamaq;
  • resources/read (və ya resources/get) — URI üzrə konkret resursu oxumaq;
  • prompts/list — əlçatan promptların siyahısını almaq;
  • prompts/get — konkret promptun mətnini almaq.

Hədiyyə kataloqu resursunu oxumaq üçün sorğu nümunəsi:

{
  "jsonrpc": "2.0",
  "id": 15,
  "method": "resources/read",
  "params": {
    "uri": "mcp://gift-server/resources/gift_catalog"
  }
}

Hələlik iki şeyi yadda saxlayın. Birincisi, hər primitiv üçün */list*/get/*/read metodları var. İkincisi, metodun adı həmişə sətir tipli method sahəsində olur, bütün məzmun isə params obyektində yaşayır.

3. Reply: MCP necə cavab verir — resulterror

Cavab (reply) həmişə sorğu ilə id sahəsi üzrə bağlıdır. Bu, bir çox paylanmış sistemlərdəki correlationId kimidir: loglara baxırsınız və görürsünüz ki, id=7 olan sorğu id=7 olan cavabı alıb — deməli, bu bir cütdür.

JSON‑RPC sadə qayda qoyur: cavabda ya result, ya da error olur, amma heç vaxt hər ikisi birlikdə deyil. Bunun üzərində MCP müxtəlif metodlar üçün (tools/list, tools/call və s.) result strukturunu dəqiqləşdirir və səhv kodlarını tövsiyə edir.

Uğurlu cavab (result)

tools/call üçün bizim suggest_gifts alətinə aid uğurlu cavab nümunəsinə baxaq. Server hər şeyi icra etdi, uyğun hədiyyələri tapdı və siyahını result sahəsində qaytarır:

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Here are some gift ideas for your friend..."
      }
    ],
    "structuredContent": {
      "gifts": [
        { "name": "Board game: Catan", "price": 45 },
        { "name": "Dice set", "price": 20 }
      ]
    },
    "isError": false
  }
}

Burada bir neçə məqam vacibdir.

  • Birincisi, contentstructuredContent — Apps SDK‑da artıq gördüyünüz MCP‑tools cavabının həmin hissələridir. Model contentdəki mətndən istifadə edir, sizin vidjet isə structuredContentdəki verilənləri səliqə ilə çəkir.
  • İkincisi, isError bayrağı biznes nəticəsinə aiddir. Protokol baxımından hər şey uğurlu keçib: JSON etibarlıdır, metod mövcuddur, arqumentlər pars edilib. Amma biznes məntiqi deyə bilər: “heç bir hədiyyə ideyası tapmadım, UX baxımından bunu səhv sayırıq”. Onda isError: true qoyursunuz və problemi contentdə təsvir edirsiniz.
  • Üçüncüsü, müxtəlif metodlar üçün (tools/list, tools/call, */list, */get) MCP spesifikasiyası resultda hansı sahələrin olmalı olduğunu detallı təsvir edir. Məsələn, tools/list üçün server adlar, başlıqlar, təsvirlər və giriş arqumentlərinin JSON Schema‑sı ilə alət təsvirləri massivini qaytarır.

Səhv cavab (error)

Əgər protokol və ya server səviyyəsində nəsə qaydasında getmirsə, result əvəzinə error obyekti qaytarılır. Adətən burada:

  • code — səhv üçün sayısal kod;
  • message — insan üçün oxunaqlı təsvir;
  • data — opsional əlavə məlumat (stack trace, detallı açıqlama, …).

Nümunə: model mövcud olmayan metodu çağırdı:

{
  "jsonrpc": "2.0",
  "id": 99,
  "error": {
    "code": -32601,
    "message": "Method not found: tools/col"
  }
}

-32601 kodu JSON‑RPC üçün klassik “method not found”dur.

İki növ səhv arasında incə, amma vacib fərq var.

Protokol xətası — MCP/JSON‑RPC qaydaları pozulanda: naməlum metod, params sahəsində yanlış tip, etibarsız JSON. Onda yuxarı səviyyədə error qaytarmaq yerinə düşür.

Biznes xətası — protokol qaydasındadır, amma əməliyyat domen səbəbinə görə alınmayıb: boş kataloq, konkret resursa icazə yoxdur, yanlış biznes identifikatoru. MCP adətən belə halda etibarlı result qaytarmağı, lakin onu isError: true kimi işarələməyi və problemi məzmundakı izahla bildirməyi tövsiyə edir.

Bu bölgü ChatGPT və sazlama alətlərinə çox kömək edir: loglara baxanda dərhal görürsünüz — texniki nasazlıq olub, yoxsa biznes məntiqi şüurlu imtina verib.

4. Notifications: təkistiqamətli ismarışlar

Bildiriş (notification) — “cavab gözlənilməyən məktub”dur. JSON‑RPC‑də bildirişlər id sahəsi olmayan adi sorğular kimi görünür. Müştəri onlara reply göndərməməlidir.

MCP‑də bildirişlər hadisələr üçün istifadə olunur: tools/resources/prompts siyahılarının dəyişməsi, uzun əməliyyatların gedişi, log mesajları və s.

Ən sadə və mütləq qarşılaşacağınız nümunə — alətlər siyahısının dəyişdiyi barədə bildirişdir. Tools üçün MCP spesifikasiyası listChanged adlı capability və alət dəsti dəyişəndə serverin göndərəcəyi tools/list_changed bildirişini təsvir edir.

Bildiriş belə görünə bilər:

{
  "jsonrpc": "2.0",
  "method": "tools/list_changed",
  "params": {
    "reason": "New tool 'suggest_gift_cards' was added"
  }
}

Ona cavab lazım deyil. Müştəri belə bildirişi alanda qərar verə bilər: “aha, tools/list‑i yenidən çağırım və alət keşini yeniləyim”.

Digər tipik MCP bildirişləri (onlar haqqında axınlar və hadisələr modulunda ətraflı danışacağıq):

  • proqres hadisələri (notifications/progress) uzun əməliyyatlar üçün;
  • server logları (notifications/logging/message);
  • resurs dəyişiklikləri (resources/list_changed) və prompt dəyişiklikləri (prompts/list_changed).

Hələlik bir şeyi yadda saxlayın: bildiriş = id olmayan sorğu və cavab gözlənilmir. Əgər loglarda id olmadan JSON görürsünüzsə, çox güman bu, notification‑dır.

Insight

Təcrübi olaraq müəyyən edilib ki, ChatGPT App ona göndərilən mesajları (MCP‑notification) nəzərə almır. Bununla belə, ChatGPT Apps hələ inkişafın başlanğıc mərhələsindədir və yaxın gələcəkdə MCP protokolunun bütün tərəflərinin tam dəstəklənməsi ehtimalı çox böyükdür. Ona görə də MCP protokolunun bu tərəfini də öyrənməyi tövsiyə edirəm.

5. Mesajlarda tools/resources/prompts necə görünür

İndi ən maraqlısı: çox danışdığımız tools, resources və prompts MCP mesajlarının içində dəqiq olaraq necə təsvir olunur.

Tools: təsvir və çağırış

Protokol səviyyəsində tools üçün iki əsas proses var:

  1. discovery — müştəri hansı alətlərin mövcud olduğunu öyrənir;
  2. invocation — müştəri konkret aləti çağırır.

Yuxarıda artıq tools/listtools/call‑a qısa baxmışdıq. İndi onlara daha sistemli baxaq: onlar hansı prosesləri əhatə edir və resultda dəqiq nə qaytarılır.

5.1.1. Alətlərin siyahısı — tools/list

tools/list üçün request‑i artıq görmüşük. Cavabın strukturuna baxaq. MCP spesifikasiyası deyir ki, result.tools massivində hər biri bir aləti təsvir edən obyektlər qaytarılmalıdır. Alətin mütləq olmalıdır:

  • name — sonradan tools/call üçün istifadə ediləcək unikal ad;
  • title — qısa başlıq (bunu həm insan, həm model görür);
  • description — alətin nə etdiyini daha geniş təsvir (kollegaya başa salırmış kimi);
  • inputSchema — alətin arqumentləri üçün JSON Schema.

Bizim suggest_gifts üçün tools/list cavabı (çox sadələşdirilmiş):

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "suggest_gifts",
        "title": "Gift ideas generator",
        "description": "Suggests gift ideas for a given occasion and budget.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "occasion": { "type": "string" },
            "budget": { "type": "number" },
            "recipient": { "type": "string" }
          },
          "required": ["occasion", "budget"]
        }
      }
    ],
    "nextCursor": null
  }
}

Əgər siz Apps SDK‑da aləti qeydiyyatdan keçirərkən inputSchema yazmısınızsa, bu obyektə demək olar ki, artıq baxmısınız — sadəcə “yuxarıdan”, TypeScript obyekt kimi. MCP onu protokol üzrə müştəriyə ötürür.

5.1.2. Alətin çağırılması — tools/call

Çağırış formatına artıq toxunduq. MCP spesifikasiyası params daxilində bunların olmasını təsvir edir:

  • name — alətin adı;
  • argumentsinputSchema‑ya uyğun obyekt.

Məsələn:

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "suggest_gifts",
    "arguments": {
      "occasion": "wedding",
      "budget": 150,
      "recipient": "coworker from marketing"
    }
  }
}

Cavabda isə server content, structuredContent və opsional olaraq _meta ilə result qaytarır (məsələn, bu aləti konkret vidjetlə bağlamaq üçün openai/outputTemplate göstərmək istəyirsinizsə).

Bu tools/listtools/call əlaqəsi MCP‑tools işinin baza dövrüdür: əvvəlcə discovery, sonra istifadə.

Resources: ünvanı olan məlumatlar

MCP‑də Resources — müştərinin URI üzrə müraciət edə biləcəyi istənilən məlumat parçasıdır: fayllar, DB qeydləri, konfiqlər, kataloqlar və s.

Standart əməliyyat dəsti:

  • resources/list — hansı resursların olduğunu öyrənmək;
  • resources/read — konkret resursu (və ya onun hissəsini) oxumaq.

Tutaq ki, gift_catalog adlı resurs var — hədiyyələrin baza kataloqu: kateqoriyalar, brendlər, minimal və maksimal qiymətlər. Server onu "mcp://gift-server/resources/gift_catalog" URI‑si ilə elan edə bilər.

resources/list cavabı (sadələşdirilmiş) belə ola bilər:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "resources": [
      {
        "uri": "mcp://gift-server/resources/gift_catalog",	// sadəcə unikal sətir. MCP — protokol deyil.
        "name": "gift_catalog",
        "description": "Base catalog of gifts with categories and prices",
        "mimeType": "application/json"
      }
    ],
    "nextCursor": null
  }
}

Resursu oxumaq — resources/read:

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "resources/read",
  "params": {
    "uri": "mcp://gift-server/resources/gift_catalog"
  }
}

Cavabda məzmunun özünü və meta‑məlumatları görmək olar:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "contents": [
      {
        "uri": "mcp://gift-server/resources/gift_catalog",
        "mimeType": "application/json",
        "text": "{\"categories\":[\"boardgames\",\"books\"]}"
      }
    ]
  }
}

Baş ideya: resurs — ünvanlana bilən məlumat, tools isə əməliyyatlardır. MCP protokolda hər ikisini açıq şəkildə göstərir.

Prompts: təkrar istifadə olunan şablonlar

Prompts — serverin müştəriyə təqdim edə biləcəyi “hazır ipucları” və ya şablonlardır. MCP onları belə bir primitiv kimi görür:

  • ad;
  • insan üçün oxunaqlı başlıq/təsvir;
  • məzmun (tez‑tez system prompt şablonu və ya bir neçə nümunə).

Və, təbii ki, iki metod var:

  • prompts/list — hansı promptların olduğunu öyrənmək;
  • prompts/get — bir promptun məzmununu almaq.

Məsələn, hədiyyə ilə birlikdə təbrik mesajlarının generasiyası üçün xüsusi üslub təyin etmək istəyirsiniz. Onda MCP serverində gift_congrats_style promptunu elan edə bilərsiniz.

prompts/list cavabı belə görünə bilər:

{
  "jsonrpc": "2.0",
  "id": 10,
  "result": {
    "prompts": [
      {
        "name": "gift_congrats_style",
        "description": "Style guide for birthday congratulations in a friendly tone"
      }
    ]
  }
}

prompts/get isə artıq mətnin özünü (və ya strukturlaşdırılmış məzmunu) qaytaracaq; müştəri sonra bunu LLM‑ə system promptun bir hissəsi kimi verə bilər. Sorğu və cavab nümunəsi:

{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "prompts/get",
  "params": {
    "name": "gift_congrats_style"
  }
}
{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "prompt": {
      "name": "gift_congrats_style",
      "messages": [
        {
          "role": "system",
          "content": [
            {
              "type": "text",
              "text": "You are a friendly assistant that writes short, warm birthday congratulations..."
            }
          ]
        }
      ]
    }
  }
}

6. Bu, Apps SDK və bizim vidjetlə necə bağlıdır

Hazırda MCP‑JSON sizə hələ də bir az həcmli görünə bilər. Gəlin bunu artıq Apps SDK ilə etdiklərinizlə əlaqələndirək.

Xatırladaq ki, vidjetin frontendində belə kod ola bilər:

// ChatGPT sandbox-da React komponentinin içində
async function fetchGifts() {
  const result = await window.openai.callTool("suggest_gifts", {
    occasion: "birthday",
    budget: 50,
    recipient: "friend who loves sci-fi"
  });

  console.log(result);
}

Apps SDK səviyyəsində bu, aşağıdakıları edən rahat funksiyadır:

  1. MCP serverinin URL‑ni (tətbiqin konfiqurasiyasından) bilir;
  2. suggest_gifts adına görə alətin təsvirini tapa bilir;
  3. sizin çağırışınızı MCP request tools/call içinə yığır;
  4. onu seçilmiş nəqliyyatla (HTTP/SSE) göndərir;
  5. MCP reply gözləyir, resultu açır və onu sizə JavaScript‑də result kimi verir.

Bunu sxemlə çəksək, təxminən belə alınar:

sequenceDiagram
    participant Widget
    participant AppsSDK as Apps SDK
    participant MCP as MCP server

    Widget->>AppsSDK: window.openai.callTool("suggest_gifts", {...})
    AppsSDK->>MCP: JSON { id:7, method:"tools/call", params:{...} }
    MCP-->>AppsSDK: JSON { id:7, result:{ content, structuredContent } }
    AppsSDK-->>Widget: result (ToolOutput)
    Widget->>Widget: setState(toolOutput)

MCP formatını anlamaq sizə iki əla bacarıq verir.

Birincisi, xam MCP loglarına (məsələn, ayrıca mühazirədə danışacağımız MCP Inspector‑da) adekvat baxa və hansı tools/callın getdiyini, onun arqumentlərinin nə olduğunu, result və ya errorda nə qayıtdığını görəcəksiniz.

İkincisi, alətləri və resursları layihələndirərkən yalnız TypeScript tipləri ilə deyil, həm də MCP sxemləri ilə düşünə bilərsiniz: bu JSON‑da necə görünəcək, digər müştərilər (məsələn, sizin MCP serverinizə qoşula bilən agentlər) üçün nə dərəcədə rahat olacaq.

7. Mini‑praktika: MCP‑JSON oxuyur və “düzəldirik”

MCP formatını mənimsəmək üçün bir‑iki mesajı əllə hissələrə bölüb baxmaq daha yaxşıdır. tools/listtools/call → nəticə ardıcıllığından ibarət nümunə dialoqa baxaq.

Müştəri alətlərin siyahısını istəyir

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

Nə görürük:

  • bu, request‑dir (id var);
  • tools/list metodu — deməli, söhbət alətlərin discovery‑sindən gedir;
  • parametrlər boşdur, səhifələmə yoxdur.

Server cavab verir:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "suggest_gifts",
        "title": "Gift ideas generator",
        "description": "Suggests gift ideas",
        "inputSchema": { "type": "object", "properties": { "occasion": { "type": "string" } } }
      }
    ]
  }
}

Dərhal görünür ki, bu cavab həmin sorğuya aiddir (eyni id: 1), protokol uğurlu keçib (result var, error yoxdur) və indi müştəri suggest_gifts alətinin mövcud olduğunu bilir.

Müştəri aləti çağırır

Sonra müştəri tools/call edir:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "suggest_gifts",
    "arguments": {
      "occasion": "anniversary"
    }
  }
}

Əgər server əlavə olaraq budget də gözləyirdisə, amma model onu göstərməyibsə, server bu cür edə bilər:

  • ya protokol səhvi qaytarmaq (məsələn, “invalid params” kodu ilə error);
  • ya da defolt qərar qəbul etmək (məsələn, orta büdcədən istifadə etmək) və normal result qaytarmaq.

Yuxarıda təqdim etdiyimiz terminlərlə desək, birinci variant — protokol xətasıdır (yuxarı səviyyədə error), ikinci isə artıq biznes məntiqinin sahəsidir: siz yenə də etibarlı result qaytarırsınız və bu vəziyyəti biznes xətası kimi sayıb‑saymamağa (isError: true) qərar verirsiniz.

Arqument səhvi halında cavab belə görünə bilər:

{
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32602,
    "message": "Missing required property 'budget' in arguments"
  }
}

Bir daha xatırladaq: bu, biznes xətası deyil, protokol pozuntusudur (arqumentlər sxemaya uyğun deyil), ona görə də burada error uyğundur.

Yanlış nümunə: xətanı axtaraq

Bəzən yeni başlayanlarda belə JSON rast gəlinir:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "tool": "suggest_gifts",
    "args": {
      "occasion": "birthday",
      "budget": 100
    }
  }
}

İlk baxışda inandırıcı görünür, amma MCP spesifikasiyası ilə müqayisə etsəniz, toolargs sahələrinin gözlənilən namearguments ilə üst‑üstə düşmədiyini görəcəksiniz.

MCP SDK müştəri/serveri çox güman belə JSON generasiya etməyəcək, amma spesifikasiyanı bilmədən əl ilə inteqrasiya edirsinizsə, bu cür bug tam realdır. Elə buna görə də kursda protokolu “təmiz” şəkildə, yalnız SDK örtükləri ilə deyil, ayrıca öyrənirik.

8. MCP mesajları ilə işləyərkən tipik səhvlər

Səhv №1: protokol və biznes xətalarının qarışdırılması.
Tez‑tez inkişaf etdiricilər vərdişən “nə alınmadısa”, hamısını yuxarı səviyyəli error‑a bükürlər — resursun olmaması da, yanlış arqumentlər də, bazanın çökməsi də. MCP kontekstində fərqləndirmək faydalıdır: əgər JSON strukturu və çağırış sxeması pozulubsa (yanlış metod, yanlış sahələr, tip uyğunsuzluğu), bu, error qaytarmaq üçündür. Əgər alət domen əməliyyatını icra edə bilməyibsə (bu büdcə üçün hədiyyə yoxdur, istifadəçi tapılmadı), daha yaxşısı etibarlı result qaytarmaq, isError: true qoymaq və contentdə anlaşılan mesaj yazmaqdır. Onda həm ChatGPT modeli, həm də sazlama alətləri “kanal sındı” ilə “server şüurlu rədd etdi”ni düzgün ayırd edə biləcək.

Səhv №2: id sahəsini və sorğuların korrelyasiyasını görməzdən gəlmək.
Bəzən MCP serverinin loglarında id sahəsi olmadan və ya müxtəlif aktiv sorğular üçün təkrarlanan id dəyərləri ilə əl ilə çıxış görmək olur. Sadə, tək axınlı hello‑world üçün bu, bəlkə də işləyər, amma paralel çağırışlar və ya təkrar cəhdlər yaranan kimi hansı cavabın hansı sorğuya aid olduğunu anlamaq çətinləşir. JSON‑RPC sorğunun ömrü boyu unikal id tələb edir və MCP bu qaydaya güvənir. Rəsmi SDK‑lardan istifadə edirsinizsə, id barədə düşünməyə ehtiyac yoxdur, amma nəqliyyat və ya loglamanı özünüz yazmağa başlayanda id‑ni saxlamağı və çıxarmağı unutmayın — qəribə bugları ilk onunla debug edəcəksiniz.

Səhv №3: eyni metod üçün result strukturunun dəyişkənliyi.
Bəzən “bir az” cavab formatını vəziyyətdən asılı dəyişmək cazibəsi olur: bəzən hədiyyələr massivi, bəzən tək sətirli obyekt, bəzən ümumiyyətlə text structuredContent olmadan. Model bəlkə də bunu həzm edər, amma vidjetləriniz və MCP‑nin digər müştəriləri — çətin. MCP spesifikasiyası hər metod üçün resultun proqnozlaşdırılan strukturunu təsvir edir; ona sadiq qalın. Başqa format lazımdırsa, sxemi yolda dəyişməkdənsə, ayrıca alət və ya versiya elan etmək daha yaxşıdır.

Səhv №4: params daxilində artıq və ya çatışmayan sahələr.
Kastom reallaşdırmalarda tipik problem — paramsə MCP‑nin gözləmədiyi şeyi əlavə etmək və ya məcburi sahəni unutmaqdır. Məsələn, tools/call‑da name əvəzinə toolName göndərmək, ya da resources/read‑də uri əvəzinə resourceId. MCP SDK adətən belə şeyləri validasiya edir və anlaşılan istisna atır, amma protokola daha yaxın işləyirsinizsə, “server niyə məni başa düşmür” sualını uzun müddət axtarmaq lazım gələ bilər. Yaxşı üsul — handlerin yanında spesifikasiyadan və ya işləyən müştərinin loglarından götürülmüş düzgün JSON sorğu nümunəsini saxlayıb, göndərdiyinizlə müqayisə etməkdir.

Səhv №5: notifications‑dan “ikinci cavab kanalı” kimi istifadə cəhdi.
Bəzən inkişaf etdiricilər notifications görən kimi nəticələri reply əvəzinə bildirişlərlə göndərməyə başlayırlar: “artıq MCP‑dəyik və bizdə SSE var, gəlin hər şeyi bildirişlərlə push edək”. Problem ondadır ki, JSON‑RPC bildirişləri tərifə görə konkret id ilə bağlı deyil və müştəri tərəfindən sorğuya cavab kimi qəbul edilmir. Nəticədə sazlama çətinləşir və hansı alət çağırışına hansı mesajın aid olduğu anlaşılmır. Bildirişlər hadisələr üçün əladır (tools/resources/prompts siyahıları dəyişdi, yeni proqres yarandı, log gəldi), amma tools/call və bənzəri sorğulara adi cavablar üçün deyil.

Səhv №6: MCP loglarına və inspektorlara baxmamaq.
Ən insani səhv — inteqrasiyanı yalnız ChatGPT UI üzərindən sazlamağa çalışmaq: “düyməni basdım, nəsə gəlmədi, nə vaxtsa baxaram”. Xam MCP mesajlarını (requests, replies, notifications) görməyənə qədər problemin hansı səviyyədə olduğunu başa düşmək çətindir: model aləti çağırmadı, Apps SDK MCP serverə çatmadı, server yanlış JSON qaytardı, yoxsa hər şey vidjetin çəkilişində sındı. MCP Inspector / Jam və MCP mesajlarının strukturlaşdırılmış loglanması — ən yaxşı dostunuzdur. Bir dəfə canlı tools/calltools/list‑i loglarda gördükdən sonra MCP mesaj formatı “sehr” olmaqdan çıxıb adi mühəndis rutinuna çevriləcək.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION