Skip to main content
Glama
elifbeyzatok00

mcp-openapi-demo

README.md
# mcp-openapi-demo
Model Context Protocol

“LLM function calling” mekanizması ile MCP’yi otomatik tetikleyen küçük bir demo.

## 📂 Proje Dizini
```
mcp-openapi-demo/
│
├── server.js          # Node.js tarafı → MCP Server (Petstore API)
├── package.json       # Node bağımlılıkları
├── .env               # Ortam değişkenleri (API anahtarı vs.)
└── python-client/
    ├── client.py      # Python tarafı → MCP Client (OpenAI entegrasyonu ile)
```

## Proje Nasıl Çalışır
👉 Modele sadece “Find available pets” denir.
👉 Model, kendi isteğiyle function call yapacak.
👉 Python kodu, bu function call’u yakalayacak, MCP server’a yönlendirecek, cevabı alacak.
👉 Sonucu tekrar modele verip son yanıtı yazdıracak.

---

# 🚀 Adım 1: MCP Server’ı Çalıştır

Önce Node.js tarafını aç ve terminalde:

```bash
cd mcp-openapi-demo
node server.js
```

Eğer doğruysa:

```
🚀 MCP Server running on http://localhost:4000
```

mesajını görmen lazım ✅

---

# 🚀 Adım 2: Python Ortamını Kur

Python client klasörüne geç:

```bash
cd python-client
python -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
pip install requests openai
```

---

# 🚀 Adım 3: OpenAI API Key Ayarla

API anahtarını `.env` dosyasına yazabilirsin:

```
OPENAI_API_KEY=senin_api_key
```

Python kodunda anahtarı almak için `python-dotenv` paketini kur:

```bash
pip install python-dotenv
```

Ve `client.py` içinde şöyle ekle:

```python
from dotenv import load_dotenv
load_dotenv()
```

Artık anahtar otomatik olarak `.env` dosyasından alınacak.

---

# 🚀 Adım 4: Python Client Çalıştır

```bash
python client.py
```

Beklenen çıktı:

1. Önce **Petstore API’den gelen JSON** → yani “available pets” listesi.
2. Ardından **OpenAI modelinin doğal dilde özeti** → mesela “There are 20 available pets, most are dogs and cats...” gibi.


📌 Özetle:

* Node.js tarafı → Petstore MCP Server
* Python tarafı → Hem MCP’den veri çekiyor hem de OpenAI modeline verip yorum alıyor



## LLM Function Calling Mekanizması Nasıl Çalışır?

👉 Modelin `"find_available_pets"` fonksiyonunu çağırması **senin yazdığın prompt + ona verdiğin `tools` tanımı sayesinde** oluyor. Yani bu çağrı **senin API çağrının bir yanıtı olarak, modelin output’unda** gerçekleşiyor.



### 📍 Nerede olur?

OpenAI’nin `chat.completions.create` cevabında olur.
Örneğin Python’da:

```python
from openai import OpenAI

client = OpenAI()

tools = [
    {
        "type": "function",
        "function": {
            "name": "find_available_pets",
            "description": "Find pets in the Petstore API by status",
            "parameters": {
                "type": "object",
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": ["available", "pending", "sold"]
                    }
                },
                "required": ["status"],
            },
        }
    }
]

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "user", "content": "Can you show me all available pets?"}
    ],
    tools=tools
)

print(response.choices[0].message)
```



### 📍 Modelin cevabı nasıl olur?

Model sana düz metin dönmez, **function call döner**:

```json
{
  "role": "assistant",
  "tool_calls": [
    {
      "id": "call_1",
      "type": "function",
      "function": {
        "name": "find_available_pets",
        "arguments": "{ \"status\": \"available\" }"
      }
    }
  ]
}
```


### 📍 Sen ne yaparsın?

1. Buradaki `function.name` ve `arguments` değerini alırsın.
2. Bu bilgiyi MCP server’a **JSON-RPC request** olarak gönderirsin (`pet/findByStatus`).
3. Dönen cevabı tekrar modele verirsin →

   ```python
   client.chat.completions.create(
       model="gpt-4o-mini",
       messages=[
           {"role": "user", "content": "Can you show me all available pets?"},
           response.choices[0].message,  # function call çıktısı
           {
             "role": "tool",
             "tool_call_id": response.choices[0].message.tool_calls[0].id,
             "content": json.dumps(mcp_result)
           }
       ]
   )
   ```



✅ Yani “find\_available\_pets” çağrısı **senin kodunda değil, modelin output’unda gerçekleşiyor.**
Sen sadece bu function call’u yakalayıp **gerçekten çalıştırıyorsun** (MCP’ye gönderiyorsun).



 ### tam zincir:

 kullanıcı → LLM → function call → MCP → sonuç → tekrar LLM

 ## Tool tanımındaki description mı süreci etkiliyor?

 Aynen öyle ✅ — tool tanımındaki **description** kısmı sürecin en kritik parçalarından biri.

LLM, kullanıcı mesajını alıyor → sonra kendisine senin verdiğin **tool schema**yı inceliyor.
Tool’un **adı**, **parametreleri** ve özellikle **description** kısmı, modelin hangi durumda o tool’u çağıracağına karar vermesini sağlıyor.



🔎 **Detaylı olarak etkileyen faktörler:**

1. **Tool adı (`name`)**

   * Model için bir “anahtar kelime”.
   * Ama tek başına yeterli değil, çünkü kullanıcı hep “find pets” demeyebilir.
   * Örn: kullanıcı *“show me all dogs available for adoption”* derse → model description’a bakıp “bu tool adoption için available pets getiriyor” diye eşleştirir.

2. **Description (Açıklama)**

   * Modelin karar verme sürecinde en güçlü sinyal.
   * Buraya yazdığın açıklama ne kadar açık, görev tanımı ne kadar iyi olursa model o kadar doğru karar verir.
   * Örn:

     ```json
     "description": "Find pets that are currently available in the Petstore API. Use this function if the user asks about pets, animals, or available pets."
     ```

     Böyle yazarsan, model daha doğru tetikler.
   * Eğer description zayıfsa, model yanlış tool’u seçebilir ya da hiç tool çağırmayabilir.

3. **Parameters (şema)**

   * Modelin doğru argüman üretmesini sağlar.
   * Mesela enum `["available", "pending", "sold"]` dersen, model bu üç değerden birini seçecektir.
   * Bu da seni gereksiz validation’dan kurtarır.



📌 **Özet:**

* **Evet, description doğrudan etkiliyor.**
* Description, modelin “hangi tool ne işe yarıyor” bilgisini anlaması için kritik.
* İyi yazılmış description → doğru tool seçimi ve doğru parametreler.