Skip to content

pamelafox/python-mcp-demo

 
 

Repository files navigation

Python MCP Demo

A demonstration project showcasing Model Context Protocol (MCP) implementations using FastMCP, with examples of stdio and HTTP transports, integration with LangChain and Agent Framework, and deployment to Azure Container Apps.

Table of Contents

Getting started

You have a few options for setting up this project. The quickest way to get started is GitHub Codespaces, since it will setup all the tools for you, but you can also set it up locally.

GitHub Codespaces

You can run this project virtually by using GitHub Codespaces. Click the button to open a web-based VS Code instance in your browser:

Open in GitHub Codespaces

Once the Codespace is open, open a terminal window and continue with the deployment steps.

VS Code Dev Containers

A related option is VS Code Dev Containers, which will open the project in your local VS Code using the Dev Containers extension:

  1. Start Docker Desktop (install it if not already installed)
  2. Open the project: Open in Dev Containers
  3. In the VS Code window that opens, once the project files show up (this may take several minutes), open a terminal window.
  4. Continue with the deployment steps.

Local environment

If you're not using one of the above options, then you'll need to:

  1. Make sure the following tools are installed:

  2. Clone the repository and open the project folder.

  3. Create a Python virtual environment and activate it.

  4. Install the dependencies:

    uv sync
  5. Copy .env-sample to .env and configure your environment variables:

    cp .env-sample .env
  6. Edit .env with your API credentials. Choose one of the following providers by setting API_HOST:

    • github - GitHub Models (requires GITHUB_TOKEN)
    • azure - Azure OpenAI (requires Azure credentials)
    • ollama - Local Ollama instance
    • openai - OpenAI API (requires OPENAI_API_KEY)

Run local MCP servers

This project includes MCP servers in the servers/ directory:

File Description
servers/basic_mcp_stdio.py MCP server with stdio transport for VS Code integration
servers/basic_mcp_http.py MCP server with HTTP transport on port 8000
servers/deployed_mcp.py MCP server for Azure deployment with Cosmos DB and optional Keycloak auth

The local servers (basic_mcp_stdio.py and basic_mcp_http.py) implement an "Expenses Tracker" with a tool to add expenses to a CSV file.

Use with GitHub Copilot

The .vscode/mcp.json file configures MCP servers for GitHub Copilot integration:

Available Servers:

  • expenses-mcp: stdio transport server for production use
  • expenses-mcp-debug: stdio server with debugpy on port 5678
  • expenses-mcp-http: HTTP transport server at http://localhost:8000/mcp. You must start this server manually with uv run servers/basic_mcp_http.py before using it.

Switching Servers:

Configure which server GitHub Copilot uses by opening the Chat panel, selecting the tools icon, and choosing the desired MCP server from the list.

Servers selection dialog

Example input:

Use a query like this to test the expenses MCP server:

Log expense for 50 bucks of pizza on my amex today

Example GitHub Copilot Chat Input

Debug with VS Code

The .vscode/launch.json provides a debug configuration to attach to an MCP server.

To debug an MCP server with GitHub Copilot Chat:

  1. Set breakpoints in the MCP server code in servers/basic_mcp_stdio.py
  2. Start the debug server via mcp.json configuration by selecting expenses-mcp-debug
  3. Press Cmd+Shift+D to open Run and Debug
  4. Select "Attach to MCP Server (stdio)" configuration
  5. Press F5 or the play button to start the debugger
  6. Select the expenses-mcp-debug server in GitHub Copilot Chat tools
  7. Use GitHub Copilot Chat to trigger the MCP tools
  8. Debugger pauses at breakpoints

Inspect with MCP inspector

The MCP Inspector is a developer tool for testing and debugging MCP servers.

Note: While HTTP servers can technically work with port forwarding in Codespaces/Dev Containers, the setup for MCP Inspector and debugger attachment is not straightforward. For the best development experience with full debugging capabilities, we recommend running this project locally.

For stdio servers:

npx @modelcontextprotocol/inspector uv run servers/basic_mcp_stdio.py

For HTTP servers:

  1. Start the HTTP server:

    uv run servers/basic_mcp_http.py
  2. In another terminal, run the inspector:

    npx @modelcontextprotocol/inspector http://localhost:8000/mcp

The inspector provides a web interface to:

  • View available tools, resources, and prompts
  • Test tool invocations with custom parameters
  • Inspect server responses and errors
  • Debug server communication

Run local Agents <-> MCP

This project includes example agents in the agents/ directory that demonstrate how to connect AI agents to MCP servers:

File Description
agents/agentframework_learn.py Microsoft Agent Framework integration with MCP
agents/agentframework_http.py Microsoft Agent Framework integration with local Expenses MCP server
agents/langchainv1_http.py LangChain agent with MCP integration
agents/langchainv1_github.py LangChain tool filtering demo with GitHub MCP (requires GITHUB_TOKEN)

To run an agent:

  1. First start the HTTP MCP server:

    uv run servers/basic_mcp_http.py
  2. In another terminal, run an agent:

    uv run agents/agentframework_http.py

The agents will connect to the MCP server and allow you to interact with the expense tracking tools through a chat interface.


Deploy to Azure

This project can be deployed to Azure Container Apps using the Azure Developer CLI (azd). The deployment provisions:

  • Azure Container Apps - Hosts both the MCP server and agent
  • Azure OpenAI - Provides the LLM for the agent
  • Azure Cosmos DB - Stores expenses data
  • Azure Container Registry - Stores container images
  • Log Analytics - Monitoring and diagnostics

Azure account setup

  1. Sign up for a free Azure account and create an Azure Subscription.
  2. Check that you have the necessary permissions:

Deploying with azd

  1. Login to Azure:

    azd auth login

    For GitHub Codespaces users, if the previous command fails, try:

    azd auth login --use-device-code
  2. Create a new azd environment:

    azd env new

    This will create a folder inside .azure with the name of your environment.

  3. Provision and deploy the resources:

    azd up

    It will prompt you to select a subscription and location. This will take several minutes to complete.

  4. Once deployment is complete, a .env file will be created with the necessary environment variables to run the agents locally against the deployed resources.

Costs

Pricing varies per region and usage, so it isn't possible to predict exact costs for your usage.

You can try the Azure pricing calculator for the resources:

  • Azure OpenAI Service: S0 tier, GPT-4o-mini model. Pricing is based on token count. Pricing
  • Azure Container Apps: Consumption tier. Pricing
  • Azure Container Registry: Standard tier. Pricing
  • Azure Cosmos DB: Serverless tier. Pricing
  • Log Analytics (Optional): Pay-as-you-go tier. Costs based on data ingested. Pricing

⚠️ To avoid unnecessary costs, remember to take down your app if it's no longer in use, either by deleting the resource group in the Portal or running azd down.


Deploy to Azure with private networking

To demonstrate enhanced security for production deployments, this project supports deploying with a virtual network (VNet) configuration that restricts public access to Azure resources.

  1. Set these azd environment variables to set up a virtual network and private endpoints for the Container App, Cosmos DB, and OpenAI resources:

    azd env set USE_VNET true
    azd env set USE_PRIVATE_INGRESS true

    The Log Analytics and ACR resources will still have public access enabled, so that you can deploy and monitor the app without needing a VPN. In production, you would typically restrict these as well.

  2. Provision and deploy:

    azd up

Additional costs for private networking

When using VNet configuration, additional Azure resources are provisioned:

  • Virtual Network: Pay-as-you-go tier. Costs based on data processed. Pricing
  • Azure Private DNS Resolver: Pricing per month, endpoints, and zones. Pricing
  • Azure Private Endpoints: Pricing per hour per endpoint. Pricing

Deploy to Azure with Keycloak authentication

This project supports deploying with OAuth 2.0 authentication using Keycloak as the identity provider, implementing the MCP OAuth specification with Dynamic Client Registration (DCR).

What gets deployed

Component Description
Keycloak Container App Keycloak 26.0 with pre-configured realm
HTTP Route Configuration Rule-based routing: /auth/* → Keycloak, /* → MCP Server
OAuth-protected MCP Server FastMCP with JWT validation against Keycloak's JWKS endpoint

Deployment steps

  1. Set the Keycloak admin password (required):

    azd env set KEYCLOAK_ADMIN_PASSWORD "YourSecurePassword123!"
  2. Optionally customize the realm name (default: mcp):

    azd env set KEYCLOAK_REALM_NAME "mcp"
  3. Deploy to Azure:

    azd up

    This will create the Azure Container Apps environment, deploy Keycloak with the pre-configured realm, deploy the MCP server with OAuth validation, and configure HTTP route-based routing.

  4. Verify deployment by checking the outputs:

    azd env get-value MCP_SERVER_URL
    azd env get-value KEYCLOAK_DIRECT_URL
    azd env get-value KEYCLOAK_ADMIN_CONSOLE
  5. Visit the Keycloak admin console to verify the realm is configured:

    https://<your-mcproutes-url>/auth/admin
    

    Login with admin and your configured password.

Testing with the agent

  1. Generate the local environment file (automatically created after azd up):

    ./infra/write_env.sh

    This creates .env with KEYCLOAK_REALM_URL, MCP_SERVER_URL, and Azure OpenAI settings.

  2. Run the agent:

    uv run agents/agentframework_http.py

    The agent automatically detects KEYCLOAK_REALM_URL in the environment and authenticates via DCR + client credentials. On success, it will add an expense and print the result.

Known limitations (demo trade-offs)

Item Current Production Recommendation Why
Keycloak mode start-dev start with proper config Dev mode has relaxed security defaults
Database H2 in-memory PostgreSQL H2 doesn't persist data across restarts
Replicas 1 (due to H2) Multiple with shared DB H2 is in-memory, can't share state
Keycloak access Public (direct URL) Internal only via routes Route URL isn't known until after deployment
DCR Open (anonymous) Require initial access token Any client can register without auth

Note: Keycloak must be publicly accessible because its URL is dynamically generated by Azure. Token issuer validation requires a known URL, but the mcproutes URL isn't available until after deployment. Using a custom domain would fix this.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Bicep 55.4%
  • Python 37.0%
  • Dockerfile 4.1%
  • Shell 2.0%
  • PowerShell 1.5%