MadgicxMCP Docs

LangGraph

Connect Madgicx MCP to LangGraph agents using client credentials authentication.

LangGraph

Build ReAct agents with LangGraph and LangChain MCP Adapters that have access to all Madgicx MCP tools.

Prerequisites

Installation

pip install langgraph langchain-openai langchain-mcp-adapters httpx python-dotenv requests

Setup

1. Configure environment variables

# .env
MADGICX_CLIENT_ID=your_client_id
MADGICX_CLIENT_SECRET=your_client_secret
MADGICX_TOKEN_URL=https://mcp.madgicx.com/oauth/token
MADGICX_MCP_URL=https://mcp.madgicx.com/mcp
 
# LLM provider
OPENAI_API_KEY=your_openai_key

2. Add the auth helper

Copy the MadgicxConfidentialClientAuth helper into your project as auth.py. You can also create a custom auth handler if your setup requires different authentication logic.

3. Create the agent

import asyncio
import os
 
from dotenv import load_dotenv
 
load_dotenv()
 
import httpx
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
 
from auth import MadgicxConfidentialClientAuth
 
MADGICX_MCP_URL = os.getenv("MADGICX_MCP_URL", "https://mcp.madgicx.com/mcp")
 
 
def _create_httpx_factory(auth: MadgicxConfidentialClientAuth):
    """Return an httpx_client_factory that injects a fresh Bearer token."""
 
    def factory(**kwargs):
        headers = {**(kwargs.pop("headers", None) or {}), **auth.headers}
        return httpx.AsyncClient(headers=headers, **kwargs)
 
    return factory
 
 
async def main():
    auth = MadgicxConfidentialClientAuth()
 
    llm = ChatOpenAI(
        model="gpt-4o",
        temperature=0,
    )
 
    mcp_client = MultiServerMCPClient(
        {
            "madgicx": {
                "url": MADGICX_MCP_URL,
                "transport": "streamable_http",
                "httpx_client_factory": _create_httpx_factory(auth),
            }
        }
    )
 
    tools = await mcp_client.get_tools()
    agent = create_react_agent(llm, tools)
 
    result = await agent.ainvoke({
        "messages": [("human", "What ad accounts do I have access to?")]
    })
    print(result["messages"][-1].content)
 
 
if __name__ == "__main__":
    asyncio.run(main())

How It Works

  1. MadgicxConfidentialClientAuth obtains an access token using your client credentials
  2. The httpx_client_factory injects the Bearer token into every HTTP request made by the MCP client
  3. MultiServerMCPClient discovers all Madgicx tools and converts them to LangChain tools
  4. create_react_agent builds a ReAct agent that reasons about which tools to call

Auth injection pattern

LangGraph's MCP adapter uses httpx under the hood. The httpx_client_factory pattern ensures every request carries a fresh access token — the auth helper handles renewal automatically.

Conversational Mode

To maintain conversation history across multiple turns:

messages = []
 
while True:
    question = input("You: ").strip()
    messages.append(("human", question))
 
    result = await agent.ainvoke({"messages": messages})
    messages = result["messages"]
 
    print(f"Agent: {messages[-1].content}")

Dependencies

[project]
requires-python = ">=3.10,<3.14"
dependencies = [
    "langgraph>=0.2.0",
    "langchain-openai>=0.3.0",
    "langchain-mcp-adapters>=0.1.0",
    "httpx>=0.27.0",
    "python-dotenv>=1.0.0",
    "requests>=2.31.0",
]

On this page