Laravel ile Model Context Protocol (MCP) Kullanımı
Model Context Protocol, gerçek bir iş akışına bağlı olduğunda daha kolay anlaşılır hale gelir.
Laravel projemde, üç somut işlevselliğe sahip, destek odaklı bir MCP sunucusu oluşturmak istedim:
- Bir destek bileti oluşturmak
- Bir bileti bir kaynak URI’den okumak
- Bir müşteri veya ekip arkadaşına gönderilmeye hazır bir özet oluşturmak
Genel bir demo yerine, kapsamı dar ve kullanışlı tuttum. Sonuç, laravel/mcp ile güçlendirilmiş bir yerel destek MCP sunucusu oldu; tek bir araç, tek bir kaynak ve tek bir istemci küçük bir destek sistemi olarak iş birliği yapıyor.
Neden Bu İyi Bir MCP Kullanım Durumu
Birçok MCP örneği, “burada bazı JSON döndüren bir araç var” ile sınırlıdır. Bu, API’yi öğrenmek için iyi olsa da, protokolün neden ilginç olduğunu göstermez.
Destek iş akışları, üç farklı etkileşim türünü bir araya getirdikleri için daha iyi bir uyum sağlayabilir:
- Durumu değiştiren bir eylem,
- Sonradan tekrar çekilebilecek bir kaynak,
- Ham operasyonel verileri insanın kullanabileceği bir şeye dönüştüren bir istemci.
Bu, MCP’ye temiz bir biçimde eşleşir:
- Araç: bileti oluştur.
- Kaynak: identifi ile bileti getir.
- İstemci: bileti profesyonel bir özet haline getir.
Bu ayrım, yaklaşımın en sevdiğim yönlerinden biridir. AI istemcisinin Laravel uygulamam hakkında özel bilgiye ihtiyaç duymamasını sağlar. Sadece hangi MCP yeteneklerinin mevcut olduğunu bilmesi yeterlidir.
Laravel’de Sunucunun Kaydı
Projemdeki ilk adım, routes/ai.php içinde yerel bir MCP sunucusu kaydetmekti:
use App\Mcp\Servers\SupportServer;
use Laravel\Mcp\Facades\Mcp;
Mcp::local('support', SupportServer::class);Bu, uygulamaya destek işlemleri için özel bir MCP giriş noktası sağlar. Ayrıca, aynı projede ayrı bir CRM sunucum var, bu da yanıtları tek bir büyük yüzeye itmek yerine sorumlulukları izole tutuyor.
Destek Sunucusunun Tanımlanması
Sunucunun kendisi kasıtlı olarak küçüktür. Görevi, işlevleri bir araya getirmek, iş mantığını tutmamakta. app/Mcp/Servers/SupportServer.php içinde, iş akışını kullanışlı kılan üç parçayı kaydettim:
class SupportServer extends Server
{
protected array $tools = [
CreateTicketTool::class,
];
protected array $resources = [
TicketResource::class,
];
protected array $prompts = [
SummarizeTicketPrompt::class,
];
}Bu yapı, Laravel’in burada nasıl rahat hissettiğinin sebeplerinden biridir. Framework, zaten net sorumluluklara sahip küçük sınıfları teşvik eder ve laravel/mcp bu stili iyi bir şekilde benimser.
Bilet Oluşturma Aracı
İhtiyacım olan ilk işlev, bir AI istemcisinin güvenli bir şekilde bir destek bileti oluşturabilmesiydi.
app/Mcp/Tools/CreateTicketTool.php içindeki araç, üç girişi doğrular:
- başlık
- tanım
- öncelik
Daha sonra bileti oluşturur ve bir temsilci için gerekli alanlarla yapılandırılmış bir yanıt döner:
return Response::structured([
'id' => $ticket->id,
'title' => $ticket->title,
'status' => $ticket->status,
'priority' => $ticket->priority,
]);Bu önemli bir detaydır. Aracın, bir sonraki adımın yeni bilet kimliğine dayanabilmesi için yapılandırılmış bir metin döndürmesini istemiyorum. MCP araçları, diğer bir adımın hemen tüketebileceği tahmin edilebilir veriler döndürdüklerinde çok daha faydalıdır.
Ayrıca, şemayı açık bir şekilde tanımladım. Bu, istemciye makine tarafından okunabilir bir sözleşme sunar ve argümanları tahmin etmeye zorlamaz:
public function schema(JsonSchema $schema): array
{
return [
'title' => $schema->string()->required(),
'description' => $schema->string()->required(),
'priority' => $schema->string()
->enum(['low', 'medium', 'high'])
->default('medium'),
];
}Destek iş akışları için bu oldukça önemlidir. Doğrulama kuralları artık sadece arka uç endişesi değil; Laravel uygulamanız ile AI istemcisi arasındaki arayüzün bir parçası haline gelir.
Bilet Kaynağı
Bir bilet oluşturmak hikayenin sadece yarısıdır. Bilet var olduğunda, bir temsilci onu bir değişim aracı çağırmadan tekrar alabilmelidir.
Bunu sağlamak için kaynak devreye girer. app/Mcp/Resources/TicketResource.php içinde, kaynak bir bilet belirteci alır, kaydı yükler ve okunabilir bir metin temsili döner:
return Response::text(
"Ticket #{$ticket->id}\n".
"Başlık: {$ticket->title}\n".
"Durum: {$ticket->status}\n".
"Öncelik: {$ticket->priority}\n\n".
"Açıklama:\n{$ticket->description}"
);Bu modeli seviyorum çünkü bileti birçok farklı bağlamda yeniden kullanmayı kolaylaştırır:
- bir asistan, kullanıcıya yanıt vermeden önce onu okuyabilir
- başka bir istemci, bileti özetleyebilir
- bir insan, çıktıyı JSON’u çözmeden inceleyebilir
Bu küçük bir tasarım seçeneği, sistemi daha bileşenli hale getirir. Bir araç durum değiştirir. Bir kaynak durumu sergiler. Bu sorumlulukları ayrı tutmak, daha temiz MCP yüzeyleriyle sonuçlanır.
Ham Verileri Göndermeye Hazır Bir Özete Dönüştüren İstemci
Üçüncü parça, demoyu gerçek bir destek iş akışı gibi hissettiren kısımdır.
app/Mcp/Prompts/SummarizeTicketPrompt.php içinde, bir istemci alacak şekilde bir istemci oluşturdum:
- bir ton
- ham bilet metni
İstemci, modele aşağıdaki konularla ilgili yapılandırılmış bir destek özeti döndürmesi talimatını verir:
- sorun
- etki
- önerilen öncelik
- sonraki eylem.
Temel fikir şu şekildedir:
return [
Response::text(
"Sen bir destek asistanısın. Aşağıdaki bileti {$tone} bir tonla özetle. ".
"Dön: problem, etki, önerilen öncelik, sonraki eylem."
)->asAssistant(),
Response::text($ticket_text),
];Birçok ekip bu kısmı atlar. Verileri ortaya çıkarır, ancak nihai çıktıyı şekillendirmez. Destekte, nihai ifade çok önemlidir:
- iç ekiplerin kısa operasyonel özetler isteyebileceği durumlar
- müşteri ile yüzleşen ekipler, daha profesyonel bir ton isteyebilir
- bazen teknik gerçekleri kaybetmeden daha dostane bir mesaj gerektiren durumlar
Bunu bir MCP istemcisi olarak paketlemek, biçimlendirme mantığını yeniden icat etmektense yeniden kullanılabilir hale getirir.
Bu Mimarayı Neden Seviyorum
Sonuçta, büyük bir sistem değil, çok küçük bir sistem oluşturmuş oldum. İşte bu yüzden iyi çalışıyor.
- MCP’nin her bir bileşeni, net bir role sahiptir:
- araç kaydı oluşturur,
- kaynak kaydı açar,
- istemci kaydı iletişime dönüştürür.
Bu ayrım projenin genişletilmesini daha kolay hale getirir. Daha ileri gitmek istersem, bir sonraki mantıklı adımları zaten biliyorum:
- bilet durumunu güncellemek için bir araç eklemek,
- son biletler için bir kaynak açmak,
- escalation notları veya müşteri yanıtları için istemciler oluşturmak,
- aynı destek sunucusunu dış AI istemcileri ile bağlamak.
Laravel, zaten güvendiğim uygulama yapısını, doğrulama ve kalıcılık deseni sağlar. MCP ise bunun üstünde temiz bir arayüz katmanı ekler.
Son Düşünceler
Bu projeden çıkarılan ana ders, MCP’nin gerçek bir iş akışını modellediğinizde çok daha çekici hale gelmesidir. Laravel uygulamamda, destek sunucusu üç bağlantılı şeyi iyi yaptığı için faydalıdır:
- doğrulanmış girişle bir bilet oluşturur,
- istemcinin bileti bir kaynak olarak geri okumasına izin verir,
- ham bilet verilerini profesyonel bir özet haline dönüştürecek bir istemci sağlar.
Bu, “AI arka ucumu arayabilir” aşamasından “AI, net sınırlarla bir destek akışına katılabilir” aşamasına geçmek için yeterlidir.
Laravel/mcp ile denemeler yapıyorsanız, ilk olarak destek, satış devri, yönlendirme veya olay sıra takip gibi dar bir alanla başlamanızı şiddetle öneririm. Bir iş akışı seçin, ardından bunu bir araç, bir kaynak ve bir istemci ile modelleyin. Genel bir demo ile yapacağınızdan çok daha fazla şey öğreneceksiniz.
Bu projeyi geliştirmeye devam edersem, sonraki adım bu destek sunucusunu, daha zengin kaynaklarla daha kapsamlı bir bilet operasyon katmanına dönüştürmek olacaktır. Ancak mevcut formunda bile, Laravel ve MCP’nin neden bu kadar doğal bir şekilde bir araya geldiğini göstermektedir.
Kaynak: Orijinal Makale


