The Model Context Protocol (MCP) is an open standard that lets you give Claude direct access to tools and data sources: your own APIs, databases, file systems, or any service you can call from Python. Instead of copying and pasting output from your tools into a chat window, Claude connects to them directly and can query, reason over, and act on real live data. Here is a minimal MCP server that exposes IT infrastructure data: Intune device compliance, Entra ID sign-ins, and Defender alerts.

What MCP actually is

An MCP server is a lightweight process that exposes tools (functions Claude can call), resources (data Claude can read), and prompts (reusable templates). Claude discovers what tools are available and decides when to call them based on the conversation. You define the tools; Claude decides when to use them.

Prerequisites

Install the MCP Python SDK and the Microsoft Graph SDK. Claude Desktop (or any MCP-compatible client) handles the connection automatically when you register your server.

pip install mcp msgraph-sdk azure-identity

Building a simple IT infrastructure MCP server

This server exposes three tools: look up a device in Intune, check a user’s last sign-in in Entra ID, and list open high-severity alerts in Defender. Once connected, you can ask Claude questions like “has jsmith’s laptop been compliant in the last 7 days?” and it will call the appropriate tools to find out.

import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
from msgraph import GraphServiceClient
from azure.identity import ClientSecretCredential

credential = ClientSecretCredential(
    tenant_id=TENANT_ID, client_id=CLIENT_ID, client_secret=CLIENT_SECRET
)
graph = GraphServiceClient(credential)
app = Server("it-infra")

@app.list_tools()
async def list_tools():
    return [
        types.Tool(
            name="get_device_compliance",
            description="Get Intune compliance status for a device by name or serial number",
            inputSchema={"type":"object","properties":{"device_name":{"type":"string"}},"required":["device_name"]}
        ),
        types.Tool(
            name="get_user_last_signin",
            description="Get the last sign-in time and risk level for an Entra ID user",
            inputSchema={"type":"object","properties":{"upn":{"type":"string"}},"required":["upn"]}
        ),
        types.Tool(
            name="list_defender_alerts",
            description="List open Defender for Endpoint alerts filtered by severity",
            inputSchema={"type":"object","properties":{"severity":{"type":"string","enum":["high","medium","low"]}},"required":["severity"]}
        )
    ]

@app.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "get_device_compliance":
        devices = await graph.device_management.managed_devices.get(
            request_configuration=lambda c: setattr(
                c, "query_parameters",
                {"filter": f"deviceName eq '{arguments['device_name']}'", "select": ["deviceName","complianceState","lastSyncDateTime","userPrincipalName"]}
            )
        )
        if devices.value:
            d = devices.value[0]
            return [types.TextContent(type="text", text=f"Device: {d.device_name}\nCompliance: {d.compliance_state}\nLast sync: {d.last_sync_date_time}\nUser: {d.user_principal_name}")]
        return [types.TextContent(type="text", text="Device not found")]

async def main():
    async with stdio_server() as (read, write):
        await app.run(read, write, app.create_initialization_options())

asyncio.run(main())

Registering the server with Claude Desktop

Add your server to ~/.config/claude/claude_desktop_config.json (macOS/Linux) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "it-infra": {
      "command": "python",
      "args": ["C:/tools/mcp/it_infra_server.py"],
      "env": {
        "TENANT_ID": "your-tenant-id",
        "CLIENT_ID": "your-client-id",
        "CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

What you can ask Claude once it is connected

With this server running, Claude can answer questions that previously required you to open three different portals:

  • “Is LAPTOP-0042 compliant? When did it last sync?”
  • “Has anyone with a high-risk sign-in logged in today?”
  • “Show me all open high-severity Defender alerts and summarise what they have in common”
  • “Which devices owned by the Finance team have not synced in the last 72 hours?”

MCP turns Claude from a chat assistant into an agent that can directly query your infrastructure. The pattern scales well: once you have a working server, adding tools for patch compliance, asset inventory, or log correlation takes minutes. Start with one tool that solves a real problem, prove the value, and expand from there.