In this article, I just want to share my implementation of a F5 MCP server, that can interact with a F5 device to list/show, create, modify/update or delete an object like: vip, pool, profile, irule.
The F5 MCP server is designed to interact with F5 devices using the iControl REST API. It provides a set of tools to manage F5 objects such as virtual servers (VIPs), pools, iRules, and profiles that an LLM can use. The server is implemented using the FastMCP framework and exposes functionalities for creating, updating, listing, and deleting F5 objects.
I’ve started thinking that I have to build a function for each object(vip,pool,etc) and each action (list,create,update,delete). It worked, but it was too complicated. The LLM only needed a way to interact with the device for those specific actions. So using some careful chosen arguments I’ve managed to build a simpler code that provides a tool/function for an action no matter what the object is.
Features
- Tool-Based API: The project defines tools (list_tool, create_tool, update_tool, delete_tool) that encapsulate operations on F5 devices.
- REST API Integration: Uses Python’s requests library to communicate with F5 devices via the iControl REST API.
- Environment Configuration: Sensitive information like IP addresses and authorization strings are managed through environment variables loaded from a .env file.
- Extensibility: Modular design allows additional tools or functionalities to be added easily.
- Transport Support: The server runs using the stdio transport, making it compatible with various client integrations.
- Dockerfile: If you want to run this as a Docker container
Key Files
- F5MCPserver.py: The main server file that initializes the MCP server and defines the tools.
- Tools/F5object.py: A utility class for performing CRUD operations on F5 objects.
I already had some Python scripts built for these actions on F5 objects using iControl REST API, so all I had to do is use/convert them into tools.
For example, here is a list/show tool for an F5 object(you can find it in F5MCPserver.py):
@mcp.tool()
def list_tool(object_name: str, object_type: str):
""" This tool lists object on an F5 device using the iControl REST API.
Args:
object_name is the name of the object.
object_type can be : vip,pool,irule or profile
"""
list = F5_object(object_name = object_name, object_type = object_type)
return list.list()
And the function that the tool calls(you can find it in F5object.py):
def list(self):
ย ย ย ย """This tool lists an object on an F5 device using the iControl REST API. ย ย ย ย ย
ย ย ย
ย ย ย ย Args:
ย ย ย ย ย ย object_name is the name of the object.ย
ย ย ย ย ย ย object_type is the type of the object to be created. It can be : vip,pool,irule or profile.
ย ย ย ย ย ย ย ย ย ย ย
ย ย ย ย """
ย ย ย ย url = f"https://{IP_ADDRESS}/mgmt/tm/ltm/{self.object_type}/{self.object_name}"
ย ย ย ย # Convert input_data dictionary to JSON string
ย ย ย ย #json_payload = str(self.payload).replace("'", '"') ย # Ensures proper JSON formatting
ย ย ย ย try:
ย ย ย ย ย ย response = requests.request("GET", url, headers=headers, verify=False, timeout=20)
ย ย ย ย ย ย response.raise_for_status() ย ย
ย ย ย ย except requests.exceptions.HTTPError:
ย ย ย ย ย ย if (response.status_code == 400 or response.status_code == 404):
ย ย ย ย ย ย ย ย return f"An error occurred while making the request: {response.text}"
ย ย ย ย except requests.exceptions.RequestException as e:
ย ย ย ย ย ย return f"An error occurred while making the request: {e}"
ย ย ย ย else:
ย ย ย ย ย ย return response.text
Very important are the arguments and their description using docstrings. These will be used by LLM to understand what data it needs to provide to the tool. If, for example the tool above would have an argument named url_body instead of object_name, the LLM would try to put whatever name it finds in your prompt in the url_body. And assuming these url_body it is the payload of the API call, it would put the name in the payload. This will not give you the result you want.
In other functions/tools, you will see I’ve used url_body argument, but in those cases, this was necessary because they are for creating and updating/modifying an object, and the configuration needs to be in the payload of an API call.
In the end, it was not hard to build an MCP server. It is pretty easy if you already have some Python scripts. You just need to turn them into tools and use docstrings to explain the arguments of the tool. The LLM model will do the rest. Pretty amazing, don’t you think?
Test
This MCP server was tested using the Claude Desktop app on a Windows 11 machine using WSL.
Here is a screenshot of how Claude sees the tools:

Claude needs to be configured to connect the the MCP server(it is a Python file, not a VM or container). Here is an example of claude_desktop_config.json file :
{
ย ย "mcpServers": {
ย ย ย ย "F5McpServer": {
ย ย ย ย ย ย "command": "wsl.exe",
ย ย ย ย ย ย "args": [
ย ย ย ย ย ย ย ย "bash",ย
ย ย ย ย ย ย ย ย "-c",
ย ย ย ย ย ย ย ย "source /full/path/.venv/bin/activate && python /full/path/F5MCPserver.py"
ย ย ย ย ย ย ย ]
ย ย ย ย }
ย ย }
}
wsl.exe is used because I am using a Windows 11 machine in Ubuntu in WSL. The rest are the commands to run the Python script of the MCP server.
I’ve also tested this with a local LLM, llama3.1, using Ollama. But in this case, it was slow, as I do not have enough resources for this (a laptop without a dedicated GPU). It works, but it is slow. But also it is PRIVATE.
Code:
You can find this example of a F5 MCP server here: