App Service uygulamasını GitHub Copilot Sohbeti (Python) için MCP Sunucusu olarak tümleştirme

Bu öğreticide Model Bağlam Protokolü (MCP) aracılığıyla FastAPI uygulamasının işlevselliğini kullanıma sunma, GitHub Copilot'a araç olarak ekleme ve Copilot Sohbet aracı modunda doğal dil kullanarak uygulamanızla etkileşim kurma hakkında bilgi edineceksiniz.

MCP aracından gelen yanıtın GitHub Copilot Sohbet penceresinde çağırdığını gösteren ekran görüntüsü.

Web uygulamanızın alışveriş, otel rezervasyonu veya veri yönetimi gibi yararlı özellikleri zaten varsa, bu özellikleri şu özellikler için kullanılabilir hale getirmek kolaydır:

Web uygulamanıza bir MCP sunucusu ekleyerek, bir aracının kullanıcı istemlerine yanıt verirken uygulamanızın özelliklerini anlamasını ve kullanmasını sağlarsınız. Bu, uygulamanızın yapabilecekleri, aracının da yapabilecekleri anlamına gelir.

  • Web uygulamanıza bir MCP sunucusu ekleyin.
  • MCP sunucusunu GitHub Copilot Sohbet aracı modunda yerel olarak test edin.
  • MCP sunucusunu Azure App Service'e dağıtın ve GitHub Copilot Sohbeti'nde bu sunucuya bağlanın.

Önkoşullar

Bu öğreticide , Azure'da PostgreSQL ile Python FastAPI web uygulaması dağıtma bölümünde kullanılan örnekle çalıştığınız varsayılır.

En azından GitHub Codespaces'ta örnek uygulamayı açın ve komutunu çalıştırarak azd upuygulamayı dağıtın.

GitHub Codespaces'ta aç

Web uygulamanıza MCP sunucusu ekleme

  1. Kod alanı gezgininde src/pyproject.toml dosyasını açın, aşağıdaki örnekte gösterildiği gibi bağımlılık listesine ekleyin mcp[cli] :

    dependencies = [
        ...
        "mcp[cli]",
    ]
    
  2. src/fastapi_app içinde mcp_server.py adlı bir dosya oluşturun ve dosyaya aşağıdaki MCP sunucusu başlatma kodunu yapıştırın:

    import asyncio
    import contextlib
    from contextlib import asynccontextmanager
    
    from mcp.server.fastmcp import FastMCP
    from sqlalchemy.sql import func
    from sqlmodel import Session, select
    
    from .models import Restaurant, Review, engine
    
    # Create a FastMCP server. Use stateless_http=True for simple mounting. Default path is .../mcp
    mcp = FastMCP("RestaurantReviewsMCP", stateless_http=True)
    
    # Lifespan context manager to start/stop the MCP session manager with the FastAPI app
    @asynccontextmanager
    async def mcp_lifespan(app):
        async with contextlib.AsyncExitStack() as stack:
            await stack.enter_async_context(mcp.session_manager.run())
            yield
    
    # MCP tool: List all restaurants with their average rating and review count
    @mcp.tool()
    async def list_restaurants_mcp() -> list[dict]:
        """List restaurants with their average rating and review count."""
    
        def sync():
            with Session(engine) as session:
                statement = (
                    select(
                        Restaurant,
                        func.avg(Review.rating).label("avg_rating"),
                        func.count(Review.id).label("review_count"),
                    )
                    .outerjoin(Review, Review.restaurant == Restaurant.id)
                    .group_by(Restaurant.id)
                )
                results = session.exec(statement).all()
                rows = []
                for restaurant, avg_rating, review_count in results:
                    r = restaurant.dict()
                    r["avg_rating"] = float(avg_rating) if avg_rating is not None else None
                    r["review_count"] = review_count
                    r["stars_percent"] = (
                        round((float(avg_rating) / 5.0) * 100) if review_count > 0 and avg_rating is not None else 0
                    )
                    rows.append(r)
                return rows
    
        return await asyncio.to_thread(sync)
    
    # MCP tool: Get a restaurant and all its reviews by restaurant_id
    @mcp.tool()
    async def get_details_mcp(restaurant_id: int) -> dict:
        """Return the restaurant and its related reviews as objects."""
    
        def sync():
            with Session(engine) as session:
                restaurant = session.exec(select(Restaurant).where(Restaurant.id == restaurant_id)).first()
                if restaurant is None:
                    return None
                reviews = session.exec(select(Review).where(Review.restaurant == restaurant_id)).all()
                return {"restaurant": restaurant.dict(), "reviews": [r.dict() for r in reviews]}
    
        return await asyncio.to_thread(sync)
    
    # MCP tool: Create a new review for a restaurant
    @mcp.tool()
    async def create_review_mcp(restaurant_id: int, user_name: str, rating: int, review_text: str) -> dict:
        """Create a new review for a restaurant and return the created review dict."""
    
        def sync():
            with Session(engine) as session:
                review = Review()
                review.restaurant = restaurant_id
                review.review_date = __import__("datetime").datetime.now()
                review.user_name = user_name
                review.rating = int(rating)
                review.review_text = review_text
                session.add(review)
                session.commit()
                session.refresh(review)
                return review.dict()
    
        return await asyncio.to_thread(sync)
    
    # MCP tool: Create a new restaurant
    @mcp.tool()
    async def create_restaurant_mcp(restaurant_name: str, street_address: str, description: str) -> dict:
        """Create a new restaurant and return the created restaurant dict."""
    
        def sync():
            with Session(engine) as session:
                restaurant = Restaurant()
                restaurant.name = restaurant_name
                restaurant.street_address = street_address
                restaurant.description = description
                session.add(restaurant)
                session.commit()
                session.refresh(restaurant)
                return restaurant.dict()
    
        return await asyncio.to_thread(sync)
    

    FastMCP() başlatıcısı, MCP Python SDK'sında durum bilgisi olmayan mod desenini kullanarak bir MCP sunucusu oluşturur. Varsayılan olarak, akışla aktarılabilir HTTP uç noktası alt yola ayarlanır /mcp .

    • Dekoratör, @mcp.tool() MCP sunucusuna uygulamasıyla bir araç ekler.
    • Araç işlevinin açıklaması, çağıran aracının aracın ve parametrelerinin nasıl kullanılacağını anlamasına yardımcı olur.

    Araçlar, form tabanlı FastAPI web uygulamasındaki mevcut restoran gözden geçirme işlevlerini yineler. İsterseniz, güncelleştirme ve silme işlevselliği için daha fazla araç ekleyebilirsiniz.

  3. src/fastapi_app/app.py'da (24. satır) satırını app = FastAPI() bulun ve aşağıdaki kodla değiştirin:

    from .mcp_server import mcp, mcp_lifespan
    app = FastAPI(lifespan=mcp_lifespan)
    app.mount("/mcp", mcp.streamable_http_app())
    

    Bu kod, MCP sunucusunun akışla aktarılabilir HTTP uç noktasını yolundaki /mcpmevcut FastAPI uygulamasına bağlar. Akışla aktarılabilir HTTP uç noktasının varsayılan yolu ile birlikte tam yol şeklindedir /mcp/mcp.

MCP sunucusunu yerel olarak test edin

  1. Codespace terminalinde aşağıdaki komutlarla uygulamayı çalıştırın:

    python3 -m venv .venv
    source .venv/bin/activate
    pip install -r src/requirements.txt
    pip install -e src
    python3 src/fastapi_app/seed_data.py
    python3 -m uvicorn fastapi_app:app --reload --port=8000
    
  2. Tarayıcıda Aç'ı seçin, ardından birkaç restoran ve inceleme ekleyin.

    Koşmaya devam edin uvicorn . MCP sunucunuz şu anda http://localhost:8000/mcp/mcp çalışıyor.

  3. Codespace'a geri dönün, Copilot Sohbeti'ni açın ve ardından istem kutusunda Aracı modu'nu seçin.

  4. Araçlar düğmesini ve ardından açılan listenin sağ üst köşesindeki MCP Sunucusu Ekle simgesini seçin.

    GitHub Copilot Sohbet aracı modunda MCP sunucusu eklemeyi gösteren ekran görüntüsü.

  5. HTTP (HTTP veya Server-Sent Olayları) öğesini seçin.

  6. Sunucu URL'sini Girin alanına yazınhttp://localhost:8000/mcp/mcp.

  7. Sunucu Kimliğini Girin alanına restaurant_ratings veya istediğiniz adı yazın.

  8. Çalışma Alanı Ayarları'nı seçin.

  9. Yeni bir Copilot Sohbet penceresine "Restoran derecelendirmelerini göster" gibi bir şey yazın.

  10. Varsayılan olarak, Bir MCP sunucusunu çağırdığınızda GitHub Copilot size bir güvenlik onayı gösterir. Devamtuşuna basın.

    GitHub Copilot Chat'teki bir MCP çağrısından gelen varsayılan güvenlik iletisini gösteren ekran görüntüsü.

    Şimdi MCP araç çağrısının başarılı olduğunu belirten bir yanıt görmeniz gerekir.

    MCP aracından gelen yanıtın GitHub Copilot Sohbet penceresinde çağırdığını gösteren ekran görüntüsü.

MCP sunucunuzu App Service'e dağıtma

  1. Kod alanı terminalinde, değişikliklerinizi işleyerek (GitHub Actions yöntemi) veya çalıştırarak azd up (Azure Geliştirici CLI yöntemi) değişikliklerinizi dağıtın.

  2. AZD çıkışında uygulamanızın URL'sini bulun. URL, AZD çıkışında şöyle görünür:

     Deploying services (azd deploy)
    
       (✓) Done: Deploying service web
       - Endpoint: <app-url>
     
  3. İşlem tamamlandıktan sonra azd up.vscode/mcp.jsondosyasını açın. URL'yi olarak <app-url>/mcp/mcpdeğiştirin.

  4. Değiştirilen MCP sunucu yapılandırmanızın üst kısmındaki Başlat'ı seçin.

    McP sunucusunu yerel mcp.json dosyasından el ile başlatmayı gösteren ekran görüntüsü.

  5. Yeni bir GitHub Copilot Sohbet penceresi başlatın. Copilot aracısında restoran derecelendirmelerini görüntülemenin yanı sıra yeni restoranlar ve yeni derecelendirmeler oluşturabilmeniz gerekir.

En iyi güvenlik uygulamaları

MCP sunucunuz büyük dil modelleri (LLM) tarafından desteklenen bir aracı tarafından çağrıldığında , istem ekleme saldırılarına dikkat edin. Aşağıdaki en iyi güvenlik uygulamalarını göz önünde bulundurun:

  • Kimlik Doğrulaması ve Yetkilendirme: Araçlarınıza yalnızca yetkili kullanıcıların veya aracıların erişebildiğinden emin olmak için MCP sunucunuzun güvenliğini Microsoft Entra kimlik doğrulaması ile sağlayın. Adım adım kılavuz için bkz. Microsoft Entra kimlik doğrulaması ile Visual Studio Code'dan Azure App Service'e Güvenli Model Bağlam Protokolü çağrıları .
  • Giriş Doğrulama ve Temizleme: Geçersiz veya kötü amaçlı girişi önlemek için her zaman gelen verileri doğrulayın. Python uygulamalarında, ayrılmış giriş modelleriyle (RestaurantCreate ve ReviewCreate gibi) veri doğrulama kurallarını zorunlu kılmak için Pydantic gibi kitaplıkları kullanın. En iyi yöntemler ve uygulama ayrıntıları için belgelerine bakın.
  • HTTPS: Örnek, varsayılan olarak HTTPS'yi zorlayan ve aktarımdaki verileri şifrelemek için ücretsiz TLS/SSL sertifikaları sağlayan Azure App Service'e dayanır.
  • En Az Ayrıcalık İlkesi: Yalnızca kullanım örneğininiz için gerekli araçları ve verileri kullanıma sunma. Gerekli olmadıkça hassas işlemleri ortaya çıkarmaktan kaçının.
  • Hız Sınırlama ve Azaltma: Kötüye kullanım ve hizmet reddi saldırılarını önlemek için API Management veya özel ara yazılım kullanın.
  • Günlük ve İzleme: Denetim ve anomali algılama için MCP uç noktalarının günlük erişimi ve kullanımı. Şüpheli etkinliği izleyin.
  • CORS Yapılandırması: MCP sunucunuza tarayıcılardan erişiliyorsa, çıkış noktaları arası istekleri güvenilen etki alanlarıyla kısıtlayın. Daha fazla bilgi için bkz. CORS'yi etkinleştirme.
  • Düzenli Güncelleştirmeler: Bilinen güvenlik açıklarını azaltmak için bağımlılıklarınızı güncel tutun.

Daha fazla kaynak

Yapay zekayı Azure App Service uygulamalarınızla tümleştirme