How to Build an MCP Server From Your Network Automation Scripts
A hands-on tutorial with six Cisco Nexus leafs and LangChain
Overview
Over the years I’ve written many network automation scripts for my own lab and for production networks. For this tutorial I’m using one of my more basic scripts. It checks which interfaces are up on six Cisco Nexus leafs. I’ve kept the check simple so we can spend more time on how to make it available to an AI agent.
The idea is to keep the Python script responsible for the network check. I’ll put the six management addresses in a YAML file and run the script from Ubuntu first, so we know what it returns. Then I’ll build a Model Context Protocol (MCP) server that exposes the same Python function as a tool.
I’ll use LangChain to connect the agent to the MCP server. The model can interpret my question in plain English and request the tool. The server runs the check and returns the switch data. At the end, I’ll compare that tool result with the standalone output so you can follow the answer all the way back to the script.
1 The network Automation Script
The six leafs in this example are the switches that connect devices such as servers to the data centre network. The physical or logical connections on each switch are its interfaces. To check them, the script first needs the management address of each leaf.
I start with leafs.yaml, a plain text file with one line for each leaf. On each line I put the name alongside its management address. I’ve used documentation addresses below. For my own lab I’d put in the six management addresses I can reach from Ubuntu. However you can easily add more nexus switches management IPs, making this script versatile.

Figure 1. The six leaf management addresses in leafs.yaml.
I put leafs.yaml, nexus_check.py, mcp_server.py and agent.py in the same folder. I’ve included all three Python files in the screenshots and split the longer ones across two views so you can follow the code in order.
2 Prepare the environment
First I need the Nexus switches running NX-OS with NX-API enabled over HTTPS. If I were checking this on a switch myself, I’d run show interface brief and read the names and states. NX-API lets Python send the same command to the switch over an encrypted HTTPS connection. Cisco NX-API CLI guide
I tested these files with Python 3.12.14 and the versions in requirements.txt. That file is in the source bundle alongside the four lab files. To try it yourself, go into that folder, create a virtual environment and install the packages.
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
In the same terminal I set the username for the account I use on all six switches. The read command lets me enter the password without showing it on screen. I use export so Python and the MCP server process can pick up both values.
export NEXUS_USERNAME=’your-read-only-user’
read -rsp ‘Nexus password: ‘ NEXUS_PASSWORD
export NEXUS_PASSWORD
Before I run the script, I set NEXUS_USERNAME and NEXUS_PASSWORD in Ubuntu so Python can read them. I’m using one authorised account across all six switches. If I’ve signed their HTTPS certificates with my lab’s certificate authority (CA), I point REQUESTS_CA_BUNDLE at that CA certificate in PEM format so Python can verify the switches.
I tested with requests==2.34.2, PyYAML==6.0.3, mcp==1.30.0, langchain==1.4.9, langchain-core==1.7.6, langchain-mcp-adapters==0.2.2 and langchain-ollama==1.1.0. These are the pinned versions I used for the client API in the example.
3 Run the stand-alone automation interface check
The first part of nexus_check.py reads my list of switches and builds the request. I use Path(__file__) because the YAML file sits beside the script. The script can find it there even if the MCP client starts the server from another folder.

Figure 2. The inventory, credentials and fixed show command in nexus_check.py.
Collect interface states through NX-API
For each leaf I take its management address and build the HTTPS /ins URL. I check the HTTP status and the command status before using the reply. The reply comes back as JSON, so I can read the named fields and keep the interfaces in the up state. A single row can come back as an object, so I put it in a list and apply the same check. Cisco interface table reference

Figure 3. The loop, up filter, per-leaf errors and terminal entry point.
I go into the lab folder and run python nexus_check.py. I can run it with no arguments because the switch addresses are already in the inventory. I get one line per leaf with the interfaces that are up.

Figure 4. Example output from all six configured leafs in Ubuntu.
Read the automation standalone results
If you look at the up list, you’ll see mgmt0 in the example. That’s the management interface, and the switch reported it as up too. I’m checking the leafs one at a time, so those results are collected over the course of the run.
There’s a difference between a check that came back empty and one that failed. If the switch returns a valid table with no up interfaces, I get {“up”: []}. If the request fails, I get an error field. For example, {“error”: “HTTP status 401”} tells me the credentials were rejected. I can still see what the other leafs returned because the script carries on.
4 Build the MCP server and register the tool
At this stage I can run the check myself. How do I get the agent to use it? I create mcp_server.py and import get_up_interfaces() from the script I’ve just run. MCP gives the agent a standard way to find that check and ask my server to run it.

Figure 5. The complete MCP server exposes check_leaf_interfaces.
I use @mcp.tool() to register the function as check_leaf_interfaces. The description is what tells the model when it might want to use it. There are no input arguments here. The script already has the inventory in YAML and checks for every up interface, returning the result by leaf name. MCP Python SDK
The last line runs the server over stdio. In practice, the client starts the server process on Ubuntu and they exchange MCP messages through its input and output streams. When the tool is called, the Python function inside that process makes the HTTPS requests to the six switches.
5 Connect the MCP server to LangChain
I’m using LangChain to put the model and the tool together. In agent.py, the MCP client starts mcp_server.py with the current Python interpreter and passes it the environment settings. I call client.get_tools() to find the tool and make it available to LangChain. LangChain MCP adapter

Figure 6. The first part of agent.py starts the client and selects the model.
For the model I’m using Qwen3, which I run locally through Ollama. Once Ollama is installed and running, I pull the model with ollama pull qwen3:4b. Ollama listens on port 11434 locally by default. The model gets my question and the tool description, then decides whether to call it. Qwen3 on Ollama
When I run nexus_check.py directly, the if __name__ == “__main__” block prints the standalone result. When the server imports the function, it calls it and returns the data through MCP. This keeps the terminal printout out of the MCP message stream.
Let the agent call the tool
I pass the model and the tool to create_agent() and ask which interfaces are up across the six leafs. The model can ask for check_leaf_interfaces with {} as the input. LangChain passes that call to the MCP client. The server runs my script and sends the result back so the model has something to work with when it answers.

Figure 7. The rest of agent.py asks the question and prints the actual tool messages.
I want to see what the agent actually checked. So I print the tool call, the arguments and what came back for each leaf before I print the answer. If the model skips the tool, the script raises an error. 
6 Compare the agent and stand-alone automation results
From the same folder I run python agent.py. The client starts the server, so I can do the whole run in one terminal. I look for the discovered tool first, then the call with {} and the results for the six leafs.

Figure 8. Example LangChain run with the MCP call, six-leaf result and answer.
If you compare the six lines under Tool result with the earlier Ubuntu output, you’ll see they match. In this example I get 21 up interface entries across the six leafs, including their management interfaces. The model may word its reply differently on another run. I can check what it says against the data the tool returned for each leaf.
Conclusion
The part I find most useful is how much of this comes from work I’d already done. The Python function knows which switches to query, what command to send and how to read the reply. The MCP server gives the agent a way to call that function.
I can run the check myself from Ubuntu or ask for it in plain English through the agent. If you already have network automation that returns a result you can check directly, you can follow the same steps with your own script.
Here the result tells me which interfaces the switches reported as up. If I also wanted to check whether a server could reach its gateway, I’d use a separate check and register it as another tool on the same server.
Use the MCP server with another agent framework
I used LangChain in this example. If I wanted to use the Claude Agent SDK, I could launch the server using mcp_servers. With the OpenAI Agents SDK I’d use MCPServerStdio. Either way I’d give the SDK the Python command, the path to mcp_server.py and the environment settings so it can discover and call the tool. Claude Agent SDK MCP guide · OpenAI Agents SDK MCP guide





Leave a Reply