MCP Olayları Açıklandı: ChatGPT'nin Abone Olabileceği Webhook Gönderen MCP Sunucusu Kurulumu ve Testi

MCP Etkinlikleri açıklandı: ChatGPT'nin events/subscribe ile MCP sunucunuza nasıl abone olduğu, Standart Webhook imzalama, 256 KiB sınırı ve Apidog'daki testler.

Medy Evrard

2 October 2026

MCP Olayları Açıklandı: ChatGPT'nin Abone Olabileceği Webhook Gönderen MCP Sunucusu Kurulumu ve Testi

Kurumsal İçin Apidog

Şirket İçi (On-Premises) Dağıtım

SSO ve RBAC

SOC 2 Uyumlu

Apidog Enterprise'ı Keşfedin

MCP Etkinlikleri, MCP sunucunuzun meydana geldiği anda ChatGPT'ye güncellemeler göndermesine olanak tanır, böylece hiçbir aracının bunları yoklamasına gerek kalmaz. OpenAI DevDay'den bu yana, 29 Eylül 2026'da, ChatGPT tüm planlarda, protokol sürümü `2026-07-28` (MCP 2.0) ile önerilen MCP Etkinlikleri spesifikasyonunu desteklemektedir. Sunucunuz üç yöntem ( `events/list`, `events/subscribe`, `events/unsubscribe`) ekler, `server/discover` içinde `events` ilan eder, bir geri arama doğrulama sorgulamasını geçer ve her teslimatı Standart Webhook'lar HMAC ile imzalar. ChatGPT yalnızca webhook teslimatını kabul eder.düğmeBu kılavuz, OpenAI'ın belgelediği her mesaj biçimini, sunucunuzun uyguladığı güvenlik kurallarını ve tüm döngü için bir test geçişini kapsar. Protokole yeni mi başladınız? MCP'nin ne olduğunu öğrenmek için buradan başlayın. JSON-RPC çağrılarını gönderecek ve Apidog'da geri aramayı taklit edeceksiniz.

MCP Etkinlikleri bir bakışta

Öğe ChatGPT'nin bekledikleri
Protokol MCP 2.0, sürüm 2026-07-28
Yetenek server/discover yeteneklerinde "events": {}
Yöntemler events/list, events/subscribe, events/unsubscribe, araçlarınızla aynı kimliği doğrulanmış uç noktada
Teslimat Yalnızca Webhook: yoklama yok, akış yok, gap veya terminated bildirimleri yok
İmzalama Standart Webhook'lar HMAC-SHA256
Başlıklar webhook-id, webhook-timestamp, webhook-signature, X-MCP-Subscription-Id
Gizli Anahtar whsec_ artı 24-64 bayta çözülen base64, ChatGPT tarafından sağlanır
Yük limiti 256 KiB (262.144 bayt), istek başına bir etkinlik
Abonelik Kimliği Deterministik: asıl, geri arama URL'si, etkinlik adı, argümanlar
Geri Aramalar HTTPS, sorgulamayla doğrulanmış, özel adres yok, yönlendirme yok

Kaynaklar: OpenAI'ın MCP Etkinlikleri kılavuzu ve MCP Etkinlikleri tasarım taslağı.

Neden yoklama yerine etkinlikler?

Etkinlikler olmadan, inceleme yorumlarını izleyen bir aracı, bir zamanlayıcı üzerinde bir aracı çağırır ve sonuçları karşılaştırır; hiçbir şey değişmediğinde istekleri yakar ve bir şey değiştiğinde gecikir. MCP Etkinlikleri yönü tersine çevirir: sunucunuz bir kaydın ne zaman değiştiğini bilir, böylece güncellemeyi gönderir. Takaslar, artık MCP içinde, klasik webhook'lar ve yoklama arasındaki takaslardır. OpenAI'ın DevDay özetinde bir proje panosu kullanılıyor: kullanıcı ChatGPT'den yeni görevleri izlemesini istiyor ve bir görev geldiğinde, ChatGPT bağlantılı belgeleri okuyor ve bir plan taslağı hazırlıyor. Belgeler iki vaka daha ekliyor: bir kanaldaki hata raporlarını taslak çekme isteklerine dönüştürme (`message.created`, `channel_id` ile filtrelenmiş) ve bir belgeye inceleme yorumları uygulama (`comment.created`, `document_id` ile filtrelenmiş). Spesifikasyon, MCP'nin Tetikleyiciler ve Etkinlikler Çalışma Grubu (repo) tarafından hazırlanmıştır ve deneysel olarak etiketlenmiştir, bu nedenle kodunuzu `2026-07-28`'e sabitleyin. Lansmanın geri kalanı için, DevDay 2026 merkezine bakın.

Etkinlikleri duyurun ve tanımlayın

`server/discover` yanıtınızdaki yeteneklere `events` ekleyin:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "supportedVersions": ["2026-07-28"],
    "capabilities": { "tools": {}, "events": {} }
  }
}

Ardından `events/list`'ten tanımları döndürün. Her biri bir `name`, bir `description`, `delivery: ["webhook"]`, abonelik argümanları için bir `inputSchema` ( `document_id` gibi filtreleriniz) ve her teslimattaki `data` nesnesi için bir `payloadSchema` taşır. Kararlı adlar ve belirli açıklamalar kullanın, filtreleri sunucunuzda uygulayın ve yalnızca bağlı hesabın görebileceği olayları listeleyin.

events/subscribe: istek ve yanıt

Bir kullanıcı ChatGPT'den bir şeyi izlemesini istediğinde, ChatGPT `events/subscribe` çağırır:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "events/subscribe",
  "params": {
    "name": "comment.created",
    "arguments": { "document_id": "doc_123" },
    "delivery": {
      "mode": "webhook",
      "url": "https://receiver.example.com/mcp-events/callback_123",
      "secret": "whsec_<base64-encoded-signing-key>"
    },
    "cursor": null
  }
}

Kabul etmeden önce, kullanıcıyı o olay ve argümanlar için yetkilendirin, ikisini de tanımınıza göre doğrulayın, base64'ü 24-64 bayta çözülen bir `whsec_` gizli anahtarı isteyin, geri aramayı doğrulayın (sonraki bölüm) ve aboneliği sahibi, filtreleri, URL'si, gizli anahtarı ve süresiyle birlikte saklayın. Ardından yanıtlayın:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "id": "sub_123",
    "refreshBefore": "2026-10-02T12:00:00Z",
    "cursor": null,
    "truncated": false
  }
}

Üç kural abonelikleri doğru tutar:

Herhangi bir veriden önce geri aramayı doğrulayın

Uygulama verilerini göndermeden önce, yeni, tek kullanımlık, kısa ömürlü bir sorgulamayla imzalı bir doğrulama gövdesi POST edin:

{ "type": "verification", "challenge": "a-single-use-random-value" }

Buna benzersiz bir `webhook-id` (örneğin `msg_verification_123`) ve teslimatla aynı imzalama başlıklarını verin. ChatGPT, `{"challenge": "a-single-use-random-value"}` ile `2xx` yankılar. Sabit zamanda karşılaştırın, ardından teslimatı etkinleştirin. Başarısız olursa, `challenge_failed` veya `timeout` gibi bir `data.reason` ile JSON-RPC hatası `-32015` (`CallbackEndpointError`) döndürün. Her bir asıl ve URL için sınırlı bir süre için bir geçiş önbelleğe alın, böylece yenilemeler yeniden sorgulama yapmaz. Sorgulama, abonenin gizli anahtarı sağlaması nedeniyle mevcuttur: onsuz, herkes sunucunuzu bir kurbanın URL'sine yönlendirebilir ve onu boğabilir. Her giden isteğe aynı sertleştirmeyi uygulayın: yalnızca HTTPS, bağlantı zamanında adresi çözümleyin ve doğrulayın, özel, yerel ve diğer genel olmayan adresleri engelleyin ve asla yönlendirmeleri takip etmeyin.

Etkinlikleri teslim edin ve imzalayın

Eşleşen bir olay meydana geldiğinde, geri arama URL'sine bir olay nesnesi POST edin:

{
  "eventId": "evt_456",
  "name": "comment.created",
  "timestamp": "2026-10-01T12:05:00Z",
  "data": {
    "document_id": "doc_123",
    "comment_id": "comment_456",
    "text": "Bu bölüme dağıtım tarihlerini ekleyebilir miyiz?",
    "url": "https://docs.example.com/doc_123#comment_456"
  },
  "cursor": null
}

`Content-Type: application/json`, `webhook-id` (`eventId` ile aynı), `webhook-timestamp` (imzalama anındaki Unix saniyeleri), `webhook-signature` ve `X-MCP-Subscription-Id` gönderin. Gövdeyi bir kez serileştirin ve imza onları kapsadığı için bu tam baytları gönderin. 256 KiB'nin altında kalın; büyük kayıtlar için bir özet gönderin ve bir okuma aracı açığa çıkarın. Kullanıcı tarafından yazılan metni veri olarak ele alın ve hiçbir zaman model talimatlarını bir yük içine koymayın. Kademeli üstel geri çekilmeyle geçici hataları yeniden deneyin, olay kimliğini koruyun ve her denemeyi taze olarak imzalayın. `410` veya `413` durumlarını yeniden denemeyin. Olaylar sırasız gelebilir, bu nedenle yazma araçlarını idempotent yapın. Güvenilir webhook tasarım kılavuzu yeniden deneme zamanlamalarını kapsar.

Standart Webhook imzasını doğrulayın

Standart Webhook'lar spesifikasyonuna göre, imzalı içerik `${webhook-id}.${webhook-timestamp}.${body}` şeklindedir, HMAC-SHA256 anahtarı `whsec_` çıkarıldıktan sonra base64 ile çözülmüş gizli anahtardır ve başlık bir veya daha fazla boşlukla ayrılmış `v1,` imzası içerir. MCP taslağı alıcılara 5 dakikadan eski zaman damgalarını reddetmelerini ve `webhook-id`'ye göre yinelenenleri kaldırmalarını söyler. ChatGPT kendi tarafında doğrular, ancak kendi sıkı bir alıcınız, iyi bir yerel test oracle'ı oluşturur. Bu, yalnızca Node yerleşiklerini kullanır:

// receiver.mjs: yerel testler için sıkı Standart Webhook alıcısı (Node 18+)
import { createServer } from "node:http";
import { createHmac, timingSafeEqual } from "node:crypto";

const SECRET = process.env.WEBHOOK_SECRET; // whsec_...
const MAX_BYTES = 256 * 1024;
const TOLERANCE_S = 5 * 60;
const seen = new Set();

export function verify(raw, h, secret, now = Math.floor(Date.now() / 1000)) {
  const id = h["webhook-id"], ts = h["webhook-timestamp"], sigs = h["webhook-signature"];
  if (!id || !ts || !sigs) return false;
  const t = Number(ts);
  if (!Number.isInteger(t) || Math.abs(now - t) > TOLERANCE_S) return false;
  const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
  const expected = createHmac("sha256", key).update(`${id}.${ts}.`).update(raw).digest();
  return sigs.split(" ").some((s) => {
    const [version, b64] = s.split(",");
    const got = Buffer.from(b64 ?? "", "base64");
    return version === "v1" && got.length === expected.length && timingSafeEqual(got, expected);
  });
}

if (SECRET) createServer((req, res) => {
  const chunks = [];
  let size = 0;
  req.on("data", (c) => { size += c.length; if (size <= MAX_BYTES) chunks.push(c); });
  req.on("end", () => {
    if (size > MAX_BYTES) return res.writeHead(413).end();
    const raw = Buffer.concat(chunks);
    if (!verify(raw, req.headers, SECRET)) return res.writeHead(401).end();
    let body;
    try { body = JSON.parse(raw); } catch { return res.writeHead(400).end(); }
    if (body.type === "verification") {
      res.writeHead(200, { "Content-Type": "application/json" });
      return res.end(JSON.stringify({ challenge: body.challenge }));
    }
    const id = req.headers["webhook-id"];
    if (!seen.has(id)) { seen.add(id); console.log(req.headers["x-mcp-subscription-id"], body.name, id); }
    res.writeHead(200).end();
  });
}).listen(8787);

WEBHOOK_SECRET=whsec_... node receiver.mjs ile çalıştırın. 256 KiB'nin üzerinde `413` ve kötü veya eski bir imza için `401` döndürür, sorgulamaları yankılar ve her `webhook-id`'yi bir kez günlüğe kaydeder. `verify()` fonksiyonunu Standart Webhook JavaScript kütüphanesindeki imzalama test vektörüne göre kontrol ettik. Teori için webhook imza doğrulamasını okuyun. Sunucunuz özel adresleri engeller, bu nedenle varsayılan olarak `localhost`'a teslim etmez. Taslak, genel olmayan hedeflere yalnızca açıkça yapılandırıldığında izin verir: yalnızca geliştirme amaçlı bir izin listesi girişi ekleyin veya alıcıyı bir tünel aracılığıyla açın.

ChatGPT yapmadan önce test edin

İşte OpenAI'ın listelediği hata modları için bir Apidog test geçişi. `MCP_URL`, `MCP_TOKEN`, `CALLBACK_URL` ve `WEBHOOK_SECRET` ile bir ortam oluşturun ve her JSON-RPC çağrısını `{{MCP_URL}}` adresine `Authorization: Bearer {{MCP_TOKEN}}` ile birlikte Akışlanabilir HTTP bağlamasının gerektirdiği başlıklarla bir POST olarak gönderin: `Accept: application/json, text/event-stream`, `MCP-Protocol-Version: 2026-07-28` ve yönteme ayarlanmış `Mcp-Method`. Her gövdenin ayrıca `io.modelcontextprotocol/protocolVersion` ve `io.modelcontextprotocol/clientCapabilities` ile `params._meta`'ya ihtiyacı vardır. OpenAI'ın örnekleri bunu atlar ve eksik bir `_meta` da `-32602` döndürür, bu nedenle 3. adım yanlış nedenle geçer.

  1. Keşif. `server/discover` gönderin ve `$.result.capabilities.events`'in var olduğunu ve `$.result.supportedVersions`'ın `2026-07-28` içerdiğini doğrulayın. `events/list` gönderin ve her olayın `delivery`'sinin `webhook` içerdiğini doğrulayın.
  2. İdempotent abonelik. Yukarıdaki abonelik gövdesini `{{CALLBACK_URL}}` ve `{{WEBHOOK_SECRET}}` kullanarak gönderin, `$.result.id`'yi `SUB_ID` olarak kaydeden bir Değişken Çıkarma son işlemcisi ile. Değiştirmeden yeniden gönderin, ardından `arguments` anahtarları yeniden sıralanmış olarak gönderin ve her iki seferde de `$.result.id`'nin `{{SUB_ID}}`'ye eşit olduğunu doğrulayın.
  3. Doğrulama. 24 bayttan daha azına çözülen bir gizli anahtar, ardından bir `http://` geri araması gönderin. Taslak ikisini de `-32602` (`InvalidParams`) ile eşler; `$.error.code` üzerinde doğrulayın. Özel IP geri araması da başarısız olmalıdır.
  4. Doğrulama sorgulaması. `{"challenge": "wrong"}` yanıtını veren bir Apidog sahte uç noktası oluşturun ve bulut sahte URL'sini geri arama olarak kullanarak abone olun. `$.error.code`'un `-32015` olduğunu ve `$.error.data.reason`'ın `challenge_failed` olduğunu doğrulayın. Ardından `CALLBACK_URL`'yi alıcınıza yönlendirin ve aboneliğin başarılı olduğunu onaylayın.
  5. Büyük yük. Gövdesi 262.144 baytı aşan bir olayı tetikleyin. Göndericiniz bunu reddetmelidir; eğer bir tane kayarsa, alıcı `413` yanıtını verir ve sunucu günlüklerinizde bir deneme, yeniden deneme değil, görünmelidir.
  6. Tekrar oynatma ve kurcalama. İmzalı bir teslimatın başlıklarını ve gövdesini sunucunuzun giden günlüğünden yeni bir Apidog isteğine kopyalayın. Hemen yeniden gönderin: `200` ve ikinci bir günlük satırı yok. Bir gövde baytını değiştirin: `401`. 5 dakika sonra yeniden gönderin: `401`.

Adımları bir senaryo olarak kaydedin ve Apidog CLI ile CI'da çalıştırın. MCP sunucu test playbook'u araç çağrılarını kapsar ve webhook'ları nasıl test edeceğiniz alıcılar hakkında daha derine iner. Ardından sunucuyu bir eklenti aracılığıyla ChatGPT'ye bağlayın ve OpenAI'ın yaşam döngüsü kontrol listesini çalıştırın.

SSS

MCP Etkinlikleri nelerdir? Bir sunucunun, istemcinin yoklama yapması yerine olay bildirimlerini bir istemciye göndermesine olanak tanıyan deneysel bir MCP uzantısı. ChatGPT, webhook modunu 2026-07-28 tarihinde desteklemektedir.

ChatGPT, MCP Etkinlikleri için yoklamayı veya akışı destekliyor mu? Hayır. ChatGPT yalnızca webhook teslimatını ve geri arama doğrulamasını destekler. Yoklama, akış ve gap ve terminated bildirimleri desteklenmez.

Hangi ChatGPT planları MCP Etkinlikleri alır? OpenAI'ın DevDay özeti, özelliğin tüm planlarda mevcut olduğunu belirtiyor.

İmzalama gizli anahtarını kim oluşturur? Abone. ChatGPT, delivery.secret içinde bir whsec_ gizli anahtarı gönderir; sunucunuz bunu doğrular, saklar ve onunla imzalar ve asla kendi başına oluşturmaz.

Bu, Agents API'den nasıl farklıdır? MCP Etkinlikleri, sunucunuzdan ChatGPT'ye veri gönderir. OpenAI Agents API, oluşturduğunuz aracılar çalıştırır ve ilerlemelerini akış veya webhook'lar aracılığıyla bildirir.

Sonraki adım

Bir sunucuya "events": {} ekleyin, bir filtreli bir olay açığa çıkarın ve ChatGPT'yi bağlamadan önce yerel bir alıcıya karşı altı kontrolü çalıştırın. Bu kontrolleri her taahhütte çalışan bir senaryo olarak tutmak için Apidog'u indirin.

API Tasarım-Öncelikli Yaklaşımı Apidog'da Uygulayın

API'leri oluşturmanın ve kullanmanın daha kolay yolunu keşfedin