> ## Documentation Index
> Fetch the complete documentation index at: https://genai.codewithsiva.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Model Context Protocol (MCP)

> Explore the requirements, architecture, and client implementations of the Model Context Protocol

As LLM applications scale, developers face a major integration problem: every database, API, and tool requires a custom, bespoke integration wrapper. The **Model Context Protocol (MCP)**, created by Anthropic, is an open standard that acts like a universal "USB port" connecting AI agents to external data sources and tools.

## 1. What Problem Does MCP Solve?

Before MCP, integration was fragmented:

* **The Custom Wrapper Mess**: If you had 5 developer IDEs and 5 databases, you had to write 25 separate integration adapters.
* **Lack of Standardization**: There was no standard format defining how a database should advertise its tables, or how a web search API should register its parameters with an LLM.

**MCP standardizes this interface.** By defining a common protocol, any **MCP-compatible Host** can connect to any **MCP Server** instantly:

```text theme={null}
[ AI App / IDE (MCP Host) ] 
       │
       ▼ (Universal Protocol)
[ Stdio / SSE Transport ]
       │
       ▼
[ Database / GitHub / Search (MCP Server) ]
```

***

## 2. Architecture & Core Components

The Model Context Protocol divides responsibility among three distinct layers:

### 2.1 The Host

The orchestration application that communicates with the LLM and manages security permissions (e.g., Claude Desktop, Antigravity IDE, or your custom Python agent). The Host instantiates the clients.

### 2.2 The Client

A protocol component running inside the Host. It initiates connection sessions to MCP servers and translates tool schemas for the LLM.

### 2.3 The Server

A lightweight background process that exposes resources, prompts, and tools to the client.

* **Resources**: Read-only data sources (like local files, database records, or API responses).
* **Prompts**: Reusable prompt templates (like code review formats).
* **Tools**: Executable actions (like creating a GitHub issue, writing a file, or running a SQL query).

***

## 3. Connecting to an Existing MCP Server

MCP servers communicate with clients using **transports**. The most common transport is **Stdio**, where the host launches the server as a subprocess and communicates via standard input (`stdin`) and standard output (`stdout`).

### Step 1: Install Python MCP SDK

To build MCP clients and servers, install the official SDK:

```bash theme={null}
uv add mcp
```

### Step 2: Configure Client Connection

To query an existing server (like the official GitHub MCP server), we initialize a `stdio_client` connection by launching the server process:

```python theme={null}
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def run_mcp_client():
    # Configure parameters to spawn the GitHub MCP server using Node/npx
    # (Requires GITHUB_PERSONAL_ACCESS_TOKEN to be set in environment)
    server_params = StdioServerParameters(
        command="npx",
        args=["-y", "@modelcontextprotocol/server-github"],
        env={"GITHUB_PERSONAL_ACCESS_TOKEN": "your_github_token_here"}
    )
    
    # Establish stdio communication
    async with stdio_client(server_params) as (read_stream, write_stream):
        async with ClientSession(read_stream, write_stream) as session:
            # Initialize connection handshake
            await session.initialize()
```

### Step 3: Retrieve and Execute Tools

Once connected, the client session queries the server to list its available tools and requests execution:

```python theme={null}
            # List tools registered by the GitHub server
            tools_response = await session.list_tools()
            print("Available Tools:")
            for tool in tools_response.tools:
                print(f"- {tool.name}: {tool.description}")
            
            # Execute a tool to fetch repository information
            result = await session.call_tool(
                "get_user_info",
                arguments={"username": "octocat"}
            )
            print("Output result:")
            print(result.content[0].text)
```

***

## 4. Combined Client Code Project

Below is a complete, runnable script illustrating how to connect to the GitHub MCP server to fetch repository details:

```python theme={null}
import asyncio
import os
from dotenv import load_dotenv
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

load_dotenv()

async def fetch_github_profile():
    # Make sure token is present
    token = os.getenv("GITHUB_PERSONAL_ACCESS_TOKEN")
    if not token:
        print("Error: GITHUB_PERSONAL_ACCESS_TOKEN environment variable not set.")
        return

    # Configure Stdio transport parameters for the GitHub MCP server
    server_params = StdioServerParameters(
        command="npx",
        args=["-y", "@modelcontextprotocol/server-github"],
        env={"GITHUB_PERSONAL_ACCESS_TOKEN": token}
    )

    print("Connecting to GitHub MCP Server...")
    async with stdio_client(server_params) as (read_stream, write_stream):
        async with ClientSession(read_stream, write_stream) as session:
            # Step 1: Handshake
            await session.initialize()
            print("Handshake Complete!\n")

            # Step 2: List available tools
            response = await session.list_tools()
            print("--- Available Server Tools ---")
            for t in response.tools:
                print(f"Tool: {t.name} -> {t.description[:80]}...")

            # Step 3: Call tool to fetch user profile details
            target_username = "octocat"
            print(f"\nCalling 'get_user_info' for username: '{target_username}'...")
            
            result = await session.call_tool(
                name="get_user_info",
                arguments={"username": target_username}
            )

            print("\n--- GitHub API Result ---")
            print(result.content[0].text)

if __name__ == "__main__":
    asyncio.run(fetch_github_profile())
```

***

## 5. Practice Exercises

### Practice 1: Tool Parameters Audit

Explain why the client passes arguments as a dictionary (e.g. `{"username": "octocat"}`) during `session.call_tool()`, and how the server knows what parameters to expect.

<Accordion title="Solution">
  * **Schema Validation**: During the handshake, `session.list_tools()` returns a list of tool objects, each containing an `inputSchema` (defined in JSON Schema format).
  * **API Contract**: The server advertises exactly what keys and data types it expects (e.g., `username` must be a string). The client uses a standard dictionary to structure these arguments, allowing the server to validate them before executing the API request.
</Accordion>
