Asistan yapan Asistan: Ollama tabanlı Kod Asistanı (MCP + Streamlit)

9 minute read

Published:


Ne zamandır aklımda olan bir proje vardı: Lokalde çalışan Ollama tabanlı bir kod asistanı oluşturmak. Opus 4.5’in kodlama yetenekleri test etmek için güzel bir fırsat olacağını düşündüm ve aklımdaki kısıtları da vererek 2 aşamalı bir proje geliştir(ttim)dim. İlk aşamada ollama Python API ile MCP sunucusu oluşturuldu. İkinci aşamada ise Streamlit tabanlı bir web arayüzü geliştirildi ve bu sırada FastAPI kullanılarak Rate Limiter eklendi.

Mimari

İlk Faz:

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   VS Code /     │────▶│   MCP Server    │────▶│    Ollama       │
│   IDE Client    │◀────│   (Python)      │◀────│    API          │
└─────────────────┘     └─────────────────┘     └─────────────────┘

İkinci Faz (Web UI Eklendi):

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Tarayıcı      │────▶│   Streamlit     │────▶│    Ollama       │
│   (Web UI)      │◀────│   App           │◀────│    API          │
└─────────────────┘     └─────────────────┘     └─────────────────┘

Bunlara ek olarak Claude 3. ve 4. seçenek olarak VSCode eklentisi veya CLI aracını önerdi fakat ben bu kısmı dahil etmedim.

İlk Kurşun: MCP Tabanlı Kod Asistanı

İlk prompt’um aşağıdaki gibi:

windows ortamında lokalde ollama kullanarak kod asistanı geliştirmesi yapacak bir uzman yazılımcısın. ollama kullanacağın ortam windows ve rtx 4060ti (16vram) gpu’ya, 64 gb ram’e sahip. kod asistanının sadece python dilinde çalışması yeterli. asistanın nasıl çalışacağı konusunda kesin bir yöntemin yok o yüzden ilk olarak potansiyel yöntemler ile başlayacaksın. örneğin lokal bir mcp yapıp kod tamamlamayı buradan çağırmak bir seçenek. veya streamlit gibi bir arayüze oturtup istenen kodu yazacak arayüz olması da bir seçenek. ilk olarak kısıtları düşünerek çözümleri listele sonrasında ise kullanacağın teknolojileri ve yaklaşımları belirle. kaynak kısıtlarına göre model seçmeyi unutma!

İlk olarak uzman yazılımcı olduğuna ikna ederek başladım 😅 Bu prompt’a karşılık bana ilk iş kaynak kısıtlarını çıkardı ve buna uygun olduğunu düşündüğü modelleri listeledi. Benim zaten aklımda olan Qwen2.5-Coder‘ı önerdiği için model seçimim ondan yana oldu. Bununla birlikte yukarıda bahsettiğim fazları listeledi ve bunları da kolaylık, esneklik gibi yönlerden karşılaştıran bir matris hazırlayıp bana önerilen çözüm sundu ve sonraki adımda seçimimi istedi.

📊 Karşılaştırma Matrisi
KriterMCP ServerStreamlitVS Code ExtCLI
Geliştirme Kolaylığı⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
IDE Entegrasyonu⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Kullanıcı Deneyimi⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Esneklik⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Bakım Kolaylığı⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

İlk seçimim MCP tabanlı bir çözüm oldu. Buradaki amacım VSCode içerisinde de bu asistanı kullanıp kullanamayacağımı test etmekti. O yüzden bu aşama ile başladım. ollama list ile hali hazırda mevcut olan modelleri kontrol etti ve bu arada da venv kullanarak sanal ortam oluşturmak istedi. Bu noktada araya girerek venv yerine uv kullanmasını önerdim çünkü Windows ortamında path uzunlukları ve izinler konusunda bazen sorunlar yaşanabiliyor. Bunu kabul etti ve uv venv ile sanal ortamı oluşturdu. Sonrasında gerekli kütüphaneleri yükledi ve MCP sunucusunu yazmaya başladı. Bu arada da modeli ollama pull qwen2.5-coder:14b ile çekti. Gerekli .env ve mcp-config.json dosyalarını oluşturduktan sonra ollama API’sini test etti. İlk testinde kod hatası aldığını fark edip son versiyona uygun şekilde kodunu güncelledi. Kodun çalıştığını görünce MCP sunucusunu tamamladı ve sunucuyu başlattı. İlk çalıştırmada yine hata aldı ve bu hatayı da düzeltti. Tüm bunlara göre de başta oluşturduğu README.md‘yi güncellemeyi unutmadı. Nihayetinde aşağıdaki araçları oluşturdu ve VSCode üzerinden MCP sunucusunu eklemememi söyledi (neden kendi eklemedi bilmiyorum 😅). Ctrl + Shift + P ile Command Palette‘yi açıp MCP User Configuration seçerek %USER%\AppData\Roaming\Code\User\mcp.json altındaki config dosyasını açtım. Claude’un oluşturduğu mcp-config.json dosyasındaki json kısmı buraya ekledim (fastmcp install mcp-json server.py > mcp-config.json kodunun çıktısı).

ToolAçıklama
complete_codeKod tamamlama
explain_codeKod açıklama
refactor_codeKod iyileştirme
debug_codeBug analizi
document_codeDokümantasyon oluşturma
generate_testsTest yazma
review_codeKod inceleme
convert_to_pythonBaşka dilden çevirme
list_modelsMevcut modelleri listele
set_modelAktif modeli değiştir

Bu aşamadaki dosya yapısı aşağıdaki gibi:

ollama-code-assist-mcp/
├── .venv/                  # uv ile oluşturulan sanal ortam
├── src/
│   ├── __init__.py
│   ├── __main__.py        # Entry point
│   ├── config.py          # Ayarlar
│   ├── ollama_client.py   # Ollama API wrapper
│   └── server.py          # MCP Server
├── tests/
│   └── test_ollama_client.py
├── .env                   # Konfigürasyon
├── .env.example
├── .gitignore
├── mcp-config.json        # MCP ayar örneği
├── pyproject.toml
├── README.md
└── requirements.txt

config.py içinde pydantic kullanılarak oluşturulmuş host, varsayılan model, temperature gibi değerlerin olduğu ortam değişkenleri var. ollama_client.py içinde ise Ollama API’si ile etkileşim için gerekli fonksiyonlarla birlikte sistem prompt’ları da bulunuyor. Son olarak server.py içinde mcp paketini kullanan bir MCP sunucusu oluşturulmuş. Burada her araç için ayrı endpoint’ler var ve bu endpoint’ler ollama_client.py içindeki fonksiyonları çağırıyor.

Örnek bir prompt:

CodeTask.COMPLETE: """You are an expert Python code completion assistant. 
Complete the code at the cursor position. Only output the completion, no explanations.
Follow Python best practices, PEP 8 style guide, and use type hints where appropriate.""",

Tüm bu adımların sonunda MCP sunucusunu aşağıdaki gibi MCP Servers sekmesine eklendi. Sıra test etmeye geldi. Test etmesi için yine Claude’a sordum ve benim için arkada test_scenarios.py dosyasını oluşturdu. Bu dosyada çeşitli kod parçaları için her aracın nasıl kullanılacağını gösteren örnekler var. Bu dosyayı arka planda istek atarak test etti ve her şeyin sorunsuz çalıştığını doğruladı. Ve bana Chat içinden bu fonksiyonları kullanabileceğimi söyledi. Chat içinden explain_code aracını kullanarak bir kod parçasını açıklamasını istedim sorunsuz bir şekilde MCP sunucusuna istek atıp cevabı döndü.

İkinci Kurşun: Streamlit Arayüzü ile Kod Asistanı

MCP’nin çalıştığına emin olduktan sonra 2. aşama olan FastAPI ve Streamlit arayüzü geliştirmesine geçtim. Prompt’um şu şekildeydi (bekleme süresine girsin gibi bir Türkçe katliamı var ama olsun 😅):

Şimdi hali hazırdaki yapıyı streamlit kullanan bir arayüze çevir. Bu sayede ollama fonksiyonları arayüz ile kullanılabilsin. Gerekirse fastapi kullanımını değerlendir. Fastapi kullanacaksan eğer rate limiting eklemeyi unutma. Kullanıcı belirli bir periyot içinde belirli sayıda istek atıp sonra bekleme süresine girsin

İlk olarak uv için pyproject.toml güncellendi ve web kısmına fastapi, streamlit gibi paketleri ekledi. Sonrasında api.py altında FastAPI tabanlı bir API oluşturdu. Bu kodun içerisinde rate limit için dakikada 10 saatte ise 100 olarak limit belirledi. requests paketini kullanarak request.client.host if request.client else "unknown" ile istemciye ait IP’yi alıp bu IP’ye göre rate limit uyguladı. Bunlara ek olarak ollama için oluşturduğu araç listesini endpoint’lere çevirdi. Schema altında tüm ResponseModel ve pydantic modellerini yazdığı için bir hayli detaylı ve iyi dokümante edilmiş bir API ortaya çıktı.


API’yi test ettikten sonra sıra Streamlit arayüzüne geldi. Burada da streamlit_app.py dosyasını oluşturdu. Arayüzde sol tarafta model seçimi, rate limit detayları ve modelin çalışıp çalışmadığını gösteren kısımlar bulunurken arayüzün ana içeriğinde ise sekmelerle seçilen fonksiyonlar ve sonuçların gösterileceği alan var. Sekmelere göre (complete, explain, refactor, debug, document, tests, review, convert) butonlar ve ek parametreler değişiyor. Butonlara basıldığında FastAPI altındaki endpoint’lere istek atılıyor ve sonuçlar arayüzde gösteriliyor.

Örnek bir kod tamamlama isteği API ile arka planda aşağıdaki gibi gerçekleşiyor:

# istek
{
    "code": "def pandas_reader():   |CURSOR|",
    "additional_context": "use pandas to read csv file in a folder. add necessary arguments"
}
# cevap
{
    "success": true,
    "result": "```python\nimport pandas as pd\n\ndef pandas_reader(file_path: str, **kwargs) -> pd.DataFrame:\n    return pd.read_csv(file_path, **kwargs)\n```",
    "error": null,
    "rate_limit": {
        "allowed": true,
        "remaining_minute": 9,
        "remaining_hour": 99,
        "reset_in": 0,
        "message": "OK"
    }
}

Arayüzde ise 👇🏻


Bunula birlikte arayüz de hazır hale geldi. Ben söylemeden (Windows diye ne kadar vurguladıysan artık) start_app.bat ve (hiç gerek olmadığı halde) start_app.ps1 script’lerini oluşturdu. Bu sayede tek tek başlatmak yerine tek komutla hem FastAPI hem de Streamlit başlatılabiliyor.

Ola ki elle başlatmak istersem de 2 terminal kullanarak FastAPI ve Streamlit’i ayrı ayrı başlatabileceğimi söyledi. Tüm bu adımların sonunda README.md dosyasını da güncelledi ve bana projenin nasıl çalıştırılacağını gösterdi.

# Terminal 1: FastAPI
uv run python -m src.api

# Terminal 2: Streamlit
uv run streamlit run src/streamlit_app.py

Arayüze doğrudan süre ölçen bir kod eklemedim. Kendi testlerime göre (hem arayüz hem Postman ile) basit bir kod tamamlama isteği ortalama 8-12 saniye arasında sürüyor. Daha karmaşık isteklerde bu süre 20-30 saniyeye kadar çıkabiliyor. Fakat test case’i yazılması durumunda ise detaylı bir yanıt döndüğü için süre 1 dakikayı aşabiliyor. Kod çevirme ise genellike 30-45 saniye arasında sürüyor. Basit bir CSV dosya okuması için denediğim Rust kodu bile Python’a şükrettirdi 😂


Yine de bu süreler lokalde kullanılan ortalama bir model için oldukça kabul edilebilir bana göre. Bununla birlikte kod içerisinde bir profilleme (profiling) yapmadım ama görev yöneticisi (task manager) üzerinden GPU, CPU ve RAM kullanımı göz ucuyla takip ettim. Model çalıştırıldığında GPU kullanımı %95-100 arasında değişiyor. VRam ise 12-14 GB arasında gidip geliyor. Dolayısıyla 16 GB VRam’li bir kart ile rahatlıkla kullanılabilir. CPU ve Ram için ise doğrudan bir gözlem yapamadım ama sistemde herhangi bir yavaşlama hissetmedim (pik vb. durumlar olmadı).

Sonuç olarak ortaya gayet kullanışlı bir kod asistanı çıktı. Bu örnek ile hem ilk MCP sunucumu geliştirmiş oldum hem de FastAPI tarafında rate limiting’i öğrenmiş oldum. Bununla birlikte Opus 4.5’in hiç teklemeden (onu demedim, öyle değil vs. diyerek kavga etmeye çok hazırdım) çalışması da beni oldukça memnun etti.

Klasörün son hali aşağıdaki gibi:

ollama-code-assist-mcp/
├── src/
│   ├── __init__.py           # Paket tanımı
│   ├── __main__.py           # Entry point
│   ├── api.py                # FastAPI backend + Rate Limiting
│   ├── config.py             # Pydantic ayarları
│   ├── ollama_client.py      # Ollama API wrapper
│   ├── server.py             # MCP Server
│   └── streamlit_app.py      # Streamlit Web UI
│
├── tests/
│   ├── __init__.py
│   └── test_ollama_client.py # Unit testler
│
├── .env                      # Ortam değişkenleri
├── .env.example              # Örnek ortam dosyası
├── blog.md                   # Blog yazısı
├── mcp-config.json           # MCP yapılandırması
├── pyproject.toml            # Proje bağımlılıkları
├── README.md                 # Dokümantasyon
├── requirements.txt          # Pip bağımlılıkları
├── start_app.bat             # Windows batch başlatıcı
├── start_app.ps1             # PowerShell başlatıcı
├── test_scenarios.py         # Test senaryoları
└── uv.lock                   # uv lock dosyası

Ekran Görüntüleri





Repo’ya buradan erişebilirsiniz: ollama-code-assistant

Chat’in tamamına buradan erişebilirsiniz.