Skip to main content
Glama

BIG-IP MCP Server

by arunhotra
MCP_FEATURES.md66.4 kB
# MCP Features Guide **Purpose:** Learn how Model Context Protocol (MCP) features work through this BIG-IP server implementation. This guide is designed for developers learning MCP. Each section explains a feature, shows the code, and demonstrates how it works in practice. --- ## Table of Contents 1. [What is MCP?](#what-is-mcp) 2. [Feature 1: Tools](#feature-1-tools) (You already know this) 3. [Feature 2: Resources](#feature-2-resources) ⭐ NEW 4. [Feature 3: Prompts](#feature-3-prompts) ⭐ NEW 5. [Feature 4: Context State](#feature-4-context-state) ⭐ NEW 6. [Feature 5: Cross-Server Integration](#feature-5-cross-server-integration) ⭐ NEW 7. [Complete Workflow Diagram](#complete-workflow-diagram) 8. [Code Location Reference](#code-location-reference) 9. [Learning Path](#learning-path) --- ## What is MCP? **Model Context Protocol (MCP)** is a standardized way for AI assistants (like Claude) to interact with external systems. Think of it as an API specifically designed for AI. ### Core Concept ``` ┌─────────────┐ MCP Protocol ┌──────────────────┐ │ │ ◄────────────────────────► │ │ │ Claude │ (JSON-RPC over stdio) │ MCP Server │ │ (AI Agent) │ │ (Your Code) │ │ │ ◄────────────────────────► │ │ └─────────────┘ └──────────────────┘ │ │ Connects to ▼ ┌──────────────────┐ │ BIG-IP Device │ │ (Target System)│ └──────────────────┘ ``` ### Why MCP? - **Standardized**: One protocol for all integrations - **Secure**: Credentials stay in your MCP server, not with Claude - **Composable**: Multiple MCP servers work together - **Stateful**: Session-based interactions with caching --- ## Feature 1: Tools **What:** Functions that Claude can call to perform actions. **When to use:** Any operation that changes state or retrieves dynamic data. ### Example from our codebase ```python @mcp.tool async def list_virtual_servers( device_name: str, ctx: Context = None ) -> str: """List all virtual servers from a BIG-IP device""" # Implementation... ``` **Location in code:** `server.py:937-1067` ### How Claude uses it: **User:** "Show me virtual servers on lab-bigip" **Claude calls:** ```python list_virtual_servers(device_name="lab-bigip") ``` **Result:** Returns formatted table of virtual servers ### All Tools in This Server | Tool Name | Purpose | Line | |-----------|---------|------| | `list_virtual_servers` | Query BIG-IP virtual servers | 937 | | `list_bigip_devices` | Show configured devices | 1069 | | `manage_as3` | Install/upgrade AS3 | 1107 | | `create_as3_app` | Deploy AS3 applications | 1417 | --- ## Feature 2: Resources **What:** Static or semi-static data that Claude can read (like files in a filesystem). **When to use:** Configuration data, templates, catalogs, documentation. **Key difference from Tools:** Resources are **read-only data access**, Tools are **actions**. ### Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Resource URIs │ ├─────────────────────────────────────────────────────────────┤ │ config://server ─► Server metadata │ │ templates://available ─► List of all templates │ │ templates://marketing ─► Specific template content │ │ templates://engineering ─► Specific template content │ └─────────────────────────────────────────────────────────────┘ │ │ Claude reads these like files ▼ ┌─────────────────────────────────────────────────────────────┐ │ "Show me available templates" │ │ "What variables does the marketing template use?" │ │ "Let me see the server configuration" │ └─────────────────────────────────────────────────────────────┘ ``` ### Resource 1: Server Configuration **URI:** `config://server` **Purpose:** Server metadata and capabilities **Code:** `server.py:1684-1697` ```python @mcp.resource("config://server") def get_server_config() -> str: """Get server configuration information""" config = { "name": "BIG-IP MCP Server", "version": "1.0.0", "description": "MCP server for F5 BIG-IP management", "capabilities": [ "List virtual servers", "Token-based authentication", "Credential caching" ] } return json.dumps(config, indent=2) ``` **How to use:** ``` User: "What can this BIG-IP server do?" Claude: [Reads config://server resource] "This server can list virtual servers, uses token authentication, and caches credentials..." ``` ### Resource 2: Template Catalog **URI:** `templates://available` **Purpose:** List all AS3 templates with their variables **Code:** `server.py:1700-1743` ```python @mcp.resource("templates://available") def list_available_templates() -> str: """List all available AS3 application templates""" templates_dir = Path(__file__).parent / "templates" # Scan directory for .json files template_files = list(templates_dir.glob("*.json")) templates = [] for template_file in template_files: # Extract variables like {{VIRTUAL_IP}}, {{POOL_MEMBER_1}} variables = re.findall(r'\{\{([A-Z_]+)\}\}', template_str) templates.append({ "name": template_name, "file": template_file.name, "variables": unique_vars, "description": f"AS3 template for {template_name} applications" }) return json.dumps({"count": len(templates), "templates": templates}, indent=2) ``` **Example output:** ```json { "count": 1, "templates": [ { "name": "marketing", "file": "marketing.json", "variables": ["TENANT_NAME", "APP_NAME", "VIRTUAL_IP", "POOL_MEMBER_1", "POOL_MEMBER_2"], "description": "AS3 template for marketing applications" } ] } ``` **How to use:** ``` User: "What templates are available?" Claude: [Reads templates://available] "I found 1 template: - marketing: Requires TENANT_NAME, APP_NAME, VIRTUAL_IP, POOL_MEMBER_1, POOL_MEMBER_2" ``` ### Resource 3: Specific Template Content **URI Pattern:** `templates://{template_name}` **Purpose:** Get the full content of a specific template **Code:** `server.py:1746-1768` ```python @mcp.resource("templates://{template_name}") def get_template_content(template_name: str) -> str: """Get the content of a specific AS3 template""" template = load_as3_template(template_name) # Extract variables from template template_str = json.dumps(template) variables = re.findall(r'\{\{([A-Z_]+)\}\}', template_str) result = { "name": template_name, "variables": list(set(variables)), "template": template # Full JSON template } return json.dumps(result, indent=2) ``` **How to use:** ``` User: "Show me the marketing template" Claude: [Reads templates://marketing] "Here's the marketing template. It creates an HTTP virtual server with a pool..." [Shows full template JSON] ``` ### Resources vs Tools: When to Use Each | Scenario | Use Resource | Use Tool | |----------|--------------|----------| | List available templates | ✅ `templates://available` | ❌ | | View template content | ✅ `templates://marketing` | ❌ | | Deploy AS3 app | ❌ | ✅ `create_as3_app` tool | | Server capabilities | ✅ `config://server` | ❌ | | List virtual servers | ❌ | ✅ `list_virtual_servers` tool | | Check AS3 status | ❌ | ✅ `manage_as3` tool | **Rule of thumb:** - **Resource** = "Show me what exists" (read-only catalog) - **Tool** = "Do something" (action or dynamic query) --- ## Feature 3: Prompts **What:** Pre-written guidance that Claude can load for contextual help. **When to use:** Complex workflows, onboarding, multi-step processes. **Think of it as:** Built-in documentation that Claude can reference to help users. ### Architecture ``` ┌──────────────────────────────────────────────────────────────┐ │ Prompt System │ ├──────────────────────────────────────────────────────────────┤ │ │ │ User asks: "How do I create an AS3 app?" │ │ │ │ │ ▼ │ │ Claude loads: create_app_workflow prompt │ │ │ │ │ ▼ │ │ Claude reads comprehensive workflow guide │ │ - Step-by-step instructions │ │ - Example interaction │ │ - Prerequisites │ │ - MCP features explained │ │ │ │ │ ▼ │ │ Claude guides user through workflow │ │ │ └──────────────────────────────────────────────────────────────┘ ``` ### Prompt 1: Help Prompt **Name:** `help_prompt` **Purpose:** General server capabilities and usage **Code:** `server.py:1775-1798` ```python @mcp.prompt def help_prompt() -> str: """Get help about available BIG-IP server capabilities""" return """ This BIG-IP MCP server provides tools to manage F5 BIG-IP devices: **Available Tools:** - `list_virtual_servers`: Query all virtual servers from a BIG-IP device - Requires: IP address, username, and password - Caches authentication token for subsequent requests - Returns detailed status of each virtual server **Usage:** Ask Claude to "list virtual servers on my BIG-IP" and provide: - BIG-IP IP address or hostname - Username - Password **Security:** - Authentication tokens are cached per-device - Tokens automatically expire after 19 minutes - SSL verification can be enabled for production """ ``` **How Claude uses it:** ``` User: "How do I use this BIG-IP server?" Claude: [Loads help_prompt] "This server provides tools to manage F5 BIG-IP devices. You can list virtual servers by providing IP, username, and password. Authentication tokens are cached..." ``` ### Prompt 2: Workflow Guide **Name:** `create_app_workflow` **Purpose:** Complete guide for AS3 application creation with cross-MCP integration **Code:** `server.py:1801-1875` ```python @mcp.prompt def create_app_workflow() -> str: """Guide for creating AS3 applications with phpIPAM integration""" return """ # AS3 Application Creation Workflow This workflow demonstrates cross-MCP-server integration. ## Prerequisites - Both phpIPAM and BIG-IP MCP servers connected - AS3 installed on BIG-IP - phpIPAM configured with sections/subnets ## Step-by-Step Process ### 1. List Available Sections (phpIPAM) Ask Claude: "List all sections from phpIPAM" ### 2. Select Your Section Choose section (e.g., "marketing", "engineering") ### 3. Reserve Virtual IP (phpIPAM) Workflow will reserve first available IP ### 4. Get Pool Member IPs (phpIPAM) Ask Claude: "Show me web servers in marketing" ### 5. Create Application (BIG-IP) Claude generates AS3 declaration and deploys ## Example Interaction [Full conversation example with tool calls] ## MCP Features Demonstrated - Cross-Server Orchestration - Resources (templates) - Prompts (this guide) - Context State (cached tokens) - Human-in-the-Loop """ ``` **How Claude uses it:** ``` User: "I want to create a load balancer application" Claude: [Loads create_app_workflow prompt] "Let me guide you through the AS3 application creation workflow. First, we need to list available sections from phpIPAM..." [Follows step-by-step guide] ``` ### Why Prompts Are Powerful **Without prompts:** ``` User: "Help me create an AS3 app" Claude: "I can help with that. What device do you want to use?" [Generic conversation, Claude has to figure it out] ``` **With prompts:** ``` User: "Help me create an AS3 app" Claude: [Loads create_app_workflow] "I'll guide you through the workflow. This involves: 1. Selecting a section from phpIPAM 2. Reserving a virtual IP 3. Choosing pool members 4. Deploying the AS3 configuration Let's start - let me list your available sections..." [Structured, consistent experience] ``` ### Prompts vs Documentation Files | Feature | Prompt | README.md | |---------|--------|-----------| | Claude can load automatically | ✅ | ❌ | | Contextual guidance | ✅ | Limited | | Always up-to-date | ✅ | Requires maintenance | | Searchable by Claude | ✅ | ❌ | | Human-readable | ✅ | ✅ | **Best practice:** Use **both** - Prompts for Claude's guidance - Markdown docs for human reference --- ## Feature 4: Context State **What:** Session-based caching that persists across multiple tool calls. **When to use:** Authentication tokens, user selections, workflow state. **Key benefit:** Avoid re-authenticating or re-querying data within the same session. ### Context State Operations ```python from fastmcp import Context # SET state ctx.set_state(key: str, value: dict) # GET state cached_data = ctx.get_state(key: str) -> dict | None # State persists for the entire conversation session ``` ### Use Case 1: Authentication Token Caching **Problem:** Re-authenticating to BIG-IP on every tool call is slow and wasteful. **Solution:** Cache tokens with expiration tracking. #### Flow Diagram ``` ┌─────────────────────────────────────────────────────────────────┐ │ Token Caching with Context State │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ First Call: list_virtual_servers(device="lab-bigip") │ │ │ │ │ ├─► Check: ctx.get_state("bigip_token_lab-bigip") │ │ │ Result: None (no cached token) │ │ │ │ │ ├─► Authenticate to BIG-IP │ │ │ POST /mgmt/shared/authn/login │ │ │ Response: { token: "XYSABC...", timeout: 1200 } │ │ │ │ │ ├─► Cache token: │ │ │ ctx.set_state("bigip_token_lab-bigip", { │ │ │ "token": "XYSABC...", │ │ │ "expires_at": "2025-10-24T10:30:00" │ │ │ }) │ │ │ │ │ └─► Query virtual servers using token │ │ │ │ ═════════════════════════════════════════════════════════════ │ │ │ │ Second Call: manage_as3(device="lab-bigip", action="status") │ │ │ │ │ ├─► Check: ctx.get_state("bigip_token_lab-bigip") │ │ │ Result: Found! { token: "XYSABC...", │ │ │ expires_at: "2025-10-24T10:30" }│ │ │ │ │ ├─► Check expiration: Still valid ✓ │ │ │ │ │ ├─► Reuse cached token (no re-authentication!) │ │ │ │ │ └─► Check AS3 status using cached token │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` #### Code Implementation **Setting state:** `server.py:997` ```python # After successful authentication token_obj = await authenticate_bigip(credentials) # Cache token with device-specific key ctx.set_state(f"bigip_token_{device_name}", token_obj.model_dump()) await ctx.info("Successfully authenticated to BIG-IP") ``` **Getting state:** `server.py:974` ```python # Check for cached token cached_token = ctx.get_state(f"bigip_token_{device_name}") if cached_token: token_obj = AuthToken(**cached_token) # Check if expired if token_obj.expires_at <= datetime.now(): token_obj = None # Expired, need to re-auth await ctx.info("Cached token expired, will re-authenticate") else: await ctx.info("Using cached authentication token") ``` #### Token Structure ```python class AuthToken(BaseModel): token: str # "XYSABC123..." expires_at: datetime # "2025-10-24T10:30:00" ``` **State key pattern:** `bigip_token_{device_name}` - `bigip_token_lab-bigip` - `bigip_token_prod-lb-01` - `bigip_token_bos-dmz-lb-01` ### Use Case 2: VIP Reservation Caching **Problem:** In guided workflow, user reserves a VIP, then later needs to select pool members. The VIP needs to be remembered. **Solution:** Cache the reserved VIP in context state. #### Flow Diagram ``` ┌─────────────────────────────────────────────────────────────────┐ │ VIP Caching in Multi-Step Workflow │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Step 1: Reserve VIP │ │ User: "Create marketing app" │ │ Claude → phpIPAM: reserve_ip_address(subnet_id=8) │ │ Result: "192.168.50.3" │ │ │ │ │ └─► ctx.set_state("as3_app_marketing", { │ │ "virtual_ip": "192.168.50.3" │ │ }) │ │ │ │ ═══════════════════════════════════════════════════════════ │ │ │ │ Step 2: Select Pool Members (later in conversation) │ │ User: "Use servers 1 and 2" │ │ Claude → create_as3_app(pool_member_selection="1 and 2") │ │ │ │ │ ├─► ctx.get_state("as3_app_marketing") │ │ │ Result: { "virtual_ip": "192.168.50.3" } │ │ │ │ │ └─► Use cached VIP + selected pool members │ │ Deploy AS3 app with both! │ │ │ │ ═══════════════════════════════════════════════════════════ │ │ │ │ Step 3: Clear State After Deployment │ │ ctx.set_state("as3_app_marketing", None) │ │ (Clean up for next app creation) │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` #### Code Implementation **Setting state:** `server.py:1490-1495` (would be set by phpIPAM interaction) ```python state_key = f"as3_app_{section_name}" app_state = ctx.get_state(state_key) if ctx else None if app_state and app_state.get("virtual_ip"): virtual_ip = app_state["virtual_ip"] await ctx.info(f"Using cached VIP: {virtual_ip}") ``` **Clearing state after deployment:** `server.py:1659` ```python # Clear cached state after successful deployment if ctx: ctx.set_state(state_key, None) ``` **State key pattern:** `as3_app_{section_name}` - `as3_app_marketing` - `as3_app_engineering` - `as3_app_finance` ### Context State Best Practices 1. **Use descriptive keys**: `bigip_token_{device_name}` not `token1` 2. **Include expiration**: Don't cache indefinitely 3. **Clear after use**: Clean up state when workflow completes 4. **Namespace by entity**: Device tokens, app state, user selections 5. **Handle missing state**: Always check if `get_state()` returns `None` ### State Lifecycle ``` ┌─────────────────────────────────────────────────────────────┐ │ Context State Lifecycle │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Session Start │ │ │ │ │ ▼ │ │ ┌────────────────┐ │ │ │ Empty Context │ ctx.get_state() → None │ │ └────────────────┘ │ │ │ │ │ │ First tool call │ │ ▼ │ │ ┌────────────────┐ │ │ │ Set State │ ctx.set_state("key", data) │ │ └────────────────┘ │ │ │ │ │ │ Multiple subsequent calls │ │ ▼ │ │ ┌────────────────┐ │ │ │ Get State │ ctx.get_state("key") → data │ │ │ (Reuse cached) │ (No re-computation!) │ │ └────────────────┘ │ │ │ │ │ │ Workflow completes │ │ ▼ │ │ ┌────────────────┐ │ │ │ Clear State │ ctx.set_state("key", None) │ │ └────────────────┘ │ │ │ │ │ │ Session ends │ │ ▼ │ │ ┌────────────────┐ │ │ │ State Destroyed│ All context cleared │ │ └────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` ### Performance Impact **Without Context State:** ``` Call 1: list_virtual_servers() → Authenticate (2s) + Query (0.5s) = 2.5s Call 2: manage_as3() → Authenticate (2s) + Query (0.5s) = 2.5s Call 3: create_as3_app() → Authenticate (2s) + Deploy (3s) = 5s Total: 10 seconds ``` **With Context State:** ``` Call 1: list_virtual_servers() → Authenticate (2s) + Query (0.5s) = 2.5s [Cache token] Call 2: manage_as3() → Reuse token (0s) + Query (0.5s) = 0.5s Call 3: create_as3_app() → Reuse token (0s) + Deploy (3s) = 3s Total: 6 seconds (40% faster!) ``` --- ## Feature 5: Cross-Server Integration **What:** Multiple MCP servers working together, coordinated by Claude. **When to use:** Workflows that span multiple systems (e.g., phpIPAM + BIG-IP). **Key insight:** Claude acts as the orchestrator between servers. ### Architecture ``` ┌──────────────────────────────────────────────────────────────────────┐ │ Cross-Server Orchestration │ ├──────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ │ │ │ │ │ │ │ Claude │ │ │ │ (Orchestrator)│ │ │ │ │ │ │ └───────┬──────┘ │ │ │ │ │ ┌─────────────┴─────────────┐ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ phpIPAM Server │ │ BIG-IP Server │ │ │ ├─────────────────┤ ├─────────────────┤ │ │ │ Tools: │ │ Tools: │ │ │ │ • list_sections │ │ • list_vs │ │ │ │ • reserve_ip │ │ • create_as3_app│ │ │ │ • get_subnets │ │ • manage_as3 │ │ │ └────────┬────────┘ └────────┬────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ phpIPAM DB │ │ BIG-IP Device │ │ │ └─────────────────┘ └─────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────┘ ``` ### Complete Workflow: Creating an AS3 Application This demonstrates all 5 MCP features working together. ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Complete AS3 Application Creation Workflow │ │ (All 5 MCP Features in Action) │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ USER: "Create a load balancer for the marketing department" │ │ │ │ ═══════════════════════════════════════════════════════════════════ │ │ STEP 1: Claude loads guidance │ │ ═══════════════════════════════════════════════════════════════════ │ │ │ │ [Feature: PROMPTS] │ │ Claude loads: create_app_workflow prompt │ │ → Understands: Need to coordinate phpIPAM + BIG-IP │ │ → Knows: 5-step process to follow │ │ │ │ ═══════════════════════════════════════════════════════════════════ │ │ STEP 2: List sections (phpIPAM Server) │ │ ═══════════════════════════════════════════════════════════════════ │ │ │ │ [Feature: CROSS-SERVER] │ │ Claude → phpIPAM: list_sections() │ │ Result: [ │ │ {id: 1, name: "marketing"}, │ │ {id: 2, name: "engineering"} │ │ ] │ │ │ │ Claude: "Found sections: marketing, engineering. Which one?" │ │ User: "Marketing" │ │ │ │ ═══════════════════════════════════════════════════════════════════ │ │ STEP 3: Reserve Virtual IP (phpIPAM Server) │ │ ═══════════════════════════════════════════════════════════════════ │ │ │ │ [Feature: CROSS-SERVER] │ │ Claude → phpIPAM: reserve_ip_address( │ │ subnet_id="8", │ │ hostname="marketing-vip" │ │ ) │ │ Result: "192.168.50.3" │ │ │ │ [Feature: CONTEXT STATE] │ │ BIG-IP ctx.set_state("as3_app_marketing", { │ │ "virtual_ip": "192.168.50.3" │ │ }) │ │ │ │ Claude: "Reserved VIP: 192.168.50.3 ✓" │ │ │ │ ═══════════════════════════════════════════════════════════════════ │ │ STEP 4: Get pool member options (phpIPAM Server) │ │ ═══════════════════════════════════════════════════════════════════ │ │ │ │ [Feature: CROSS-SERVER] │ │ Claude → phpIPAM: get_subnet_details( │ │ subnet_id="7", │ │ include_addresses=true │ │ ) │ │ Result: [ │ │ {ip: "172.16.100.3", hostname: "web-mkt-3"}, │ │ {ip: "172.16.100.4", hostname: "web-mkt-4"}, │ │ {ip: "172.16.100.5", hostname: "web-mkt-5"} │ │ ] │ │ │ │ Claude: "Available servers: │ │ 1. 172.16.100.3 (web-mkt-3) │ │ 2. 172.16.100.4 (web-mkt-4) │ │ 3. 172.16.100.5 (web-mkt-5) │ │ Which ones do you want?" │ │ │ │ User: "Use 1 and 2" │ │ │ │ ═══════════════════════════════════════════════════════════════════ │ │ STEP 5: Check available templates (BIG-IP Server) │ │ ═══════════════════════════════════════════════════════════════════ │ │ │ │ [Feature: RESOURCES] │ │ Claude reads: templates://available │ │ Result: Found "marketing" template │ │ │ │ Claude reads: templates://marketing │ │ Result: Template requires VIRTUAL_IP, POOL_MEMBER_1, POOL_MEMBER_2 │ │ │ │ ═══════════════════════════════════════════════════════════════════ │ │ STEP 6: Create AS3 application (BIG-IP Server) │ │ ═══════════════════════════════════════════════════════════════════ │ │ │ │ [Feature: CONTEXT STATE] │ │ Retrieve cached VIP: ctx.get_state("as3_app_marketing") │ │ → virtual_ip = "192.168.50.3" │ │ │ │ [Feature: TOOLS] │ │ Claude → BIG-IP: create_as3_app( │ │ device_name="lab-bigip", │ │ section_name="marketing", │ │ virtual_ip="192.168.50.3", ← From cached state │ │ pool_members=["172.16.100.3", "172.16.100.4"], │ │ auto_deploy=False ← Preview first │ │ ) │ │ │ │ Tool internally: │ │ 1. [CONTEXT STATE] Check for cached BIG-IP token │ │ ctx.get_state("bigip_token_lab-bigip") │ │ │ │ 2. [RESOURCES] Load template: templates/marketing.json │ │ │ │ 3. Render template with variables: │ │ TENANT_NAME → "Marketing" │ │ APP_NAME → "marketing_app" │ │ VIRTUAL_IP → "192.168.50.3" │ │ POOL_MEMBER_1 → "172.16.100.3" │ │ POOL_MEMBER_2 → "172.16.100.4" │ │ │ │ 4. Return preview │ │ │ │ Claude: "Preview: │ │ Tenant: Marketing │ │ VIP: 192.168.50.3:80 │ │ Pool: 172.16.100.3:80, 172.16.100.4:80 │ │ Ready to deploy?" │ │ │ │ User: "Yes, deploy it" │ │ │ │ ═══════════════════════════════════════════════════════════════════ │ │ STEP 7: Deploy application (BIG-IP Server) │ │ ═══════════════════════════════════════════════════════════════════ │ │ │ │ [Feature: TOOLS] │ │ Claude → BIG-IP: create_as3_app( │ │ ... same parameters ... │ │ auto_deploy=True ← Deploy now! │ │ ) │ │ │ │ Tool internally: │ │ 1. [CONTEXT STATE] Reuse cached token (no re-auth!) │ │ 2. POST AS3 declaration to BIG-IP │ │ 3. Poll deployment status │ │ 4. [CONTEXT STATE] Clear cached VIP state │ │ ctx.set_state("as3_app_marketing", None) │ │ │ │ Result: "✅ Application deployed successfully!" │ │ │ │ ═══════════════════════════════════════════════════════════════════ │ │ │ │ FINAL RESULT: │ │ Marketing load balancer is live! │ │ VIP: 192.168.50.3 │ │ Pool: web-mkt-3, web-mkt-4 │ │ │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### Feature Interactions Summary | Step | Tools | Resources | Prompts | Context State | Cross-Server | |------|-------|-----------|---------|---------------|--------------| | 1. Load guidance | | | ✅ | | | | 2. List sections | ✅ | | | | ✅ | | 3. Reserve VIP | ✅ | | | ✅ Set | ✅ | | 4. Get pool IPs | ✅ | | | | ✅ | | 5. Check templates | | ✅ | | | | | 6. Preview app | ✅ | ✅ | | ✅ Get | | | 7. Deploy app | ✅ | | | ✅ Get/Clear | | **Every feature is used at least once!** ### Cross-Server Communication Pattern **Key concept:** MCP servers cannot directly call each other. Claude is the orchestrator. #### Anti-Pattern (Won't Work) ```python # In BIG-IP server.py - WRONG! @mcp.tool def create_as3_app(...): # Trying to call phpIPAM directly - NOT POSSIBLE vip = phpipam_server.reserve_ip(subnet_id) # ❌ No direct access ``` #### Correct Pattern ```python # In BIG-IP server.py - CORRECT @mcp.tool def create_as3_app(...): if not virtual_ip: # Return instructions for Claude return """ To proceed, please use the phpIPAM MCP server to reserve a VIP: Call phpIPAM's reserve_ip_address tool with: - subnet_id: "8" - hostname: "marketing-vip" Then call this tool again with the reserved IP. """ ``` **Claude sees this and:** 1. Calls phpIPAM server's `reserve_ip_address` tool 2. Gets result: "192.168.50.3" 3. Calls BIG-IP server's `create_as3_app` tool with `virtual_ip="192.168.50.3"` ### Direct Mode vs Guided Mode This server supports **both** patterns: **Guided Mode** (Claude orchestrates) ```python # Step 1 create_as3_app(device="lab-bigip", section="marketing") → "Please reserve VIP from phpIPAM subnet 8" # Claude calls phpIPAM, gets "192.168.50.3" # Step 2 create_as3_app(device="lab-bigip", section="marketing", pool_member_selection="1 and 2") → "Preview: VIP 192.168.50.3, Pool: ..." ``` **Direct Mode** (User provides IPs) ```python # Single call create_as3_app( device="lab-bigip", section="marketing", virtual_ip="192.168.50.3", pool_members=["172.16.100.3", "172.16.100.4"], auto_deploy=True ) → "✅ Deployed!" ``` --- ## Complete Workflow Diagram This diagram shows how all 5 features work together in the AS3 application creation workflow. ``` ┌──────────────────────────────────────────────────────────────────────────────────┐ │ Complete MCP Feature Workflow │ │ (Creating AS3 App with Cross-Server Integration) │ ├──────────────────────────────────────────────────────────────────────────────────┤ │ │ │ USER starts conversation │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────┐ │ │ │ Feature 3: PROMPTS │ │ │ │ Claude loads workflow guide │ │ │ └────────────┬────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 5: CROSS-SERVER (phpIPAM) │ │ │ │ Tool: list_sections() → ["marketing", ...] │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ │ User selects: "marketing" │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 5: CROSS-SERVER (phpIPAM) │ │ │ │ Tool: reserve_ip_address(subnet=8) │ │ │ │ Result: "192.168.50.3" │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 4: CONTEXT STATE (BIG-IP) │ │ │ │ ctx.set_state("as3_app_marketing", │ │ │ │ {"virtual_ip": "192.168.50.3"}) │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 5: CROSS-SERVER (phpIPAM) │ │ │ │ Tool: get_subnet_details(subnet=7) │ │ │ │ Shows: Available web servers │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ │ User selects: "1 and 2" │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 2: RESOURCES (BIG-IP) │ │ │ │ Read: templates://available │ │ │ │ Read: templates://marketing │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 1: TOOLS (BIG-IP) │ │ │ │ Call: create_as3_app( │ │ │ │ device="lab-bigip", │ │ │ │ section="marketing", │ │ │ │ pool_member_selection="1 and 2" │ │ │ │ ) │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ │ Tool internally does: │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 4: CONTEXT STATE (BIG-IP) │ │ │ │ ctx.get_state("as3_app_marketing") │ │ │ │ → Retrieves VIP: "192.168.50.3" │ │ │ │ │ │ │ │ ctx.get_state("bigip_token_lab-bigip") │ │ │ │ → Retrieves cached auth token │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Load template, render, generate preview │ │ │ │ Show preview to user │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ │ User: "Deploy it" │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 1: TOOLS (BIG-IP) │ │ │ │ Call: create_as3_app(..., auto_deploy=True) │ │ │ │ → POST AS3 declaration to BIG-IP │ │ │ │ → Poll deployment status │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Feature 4: CONTEXT STATE (BIG-IP) │ │ │ │ ctx.set_state("as3_app_marketing", None) │ │ │ │ → Clear cached VIP after deployment │ │ │ └────────────────┬───────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ✅ SUCCESS! │ │ Application deployed to BIG-IP │ │ │ └──────────────────────────────────────────────────────────────────────────────────┘ FEATURE USAGE COUNT: ┌──────────────────┬───────┐ │ Tools │ 3× │ │ Resources │ 2× │ │ Prompts │ 1× │ │ Context State │ 4× │ │ Cross-Server │ 3× │ └──────────────────┴───────┘ ``` --- ## Code Location Reference Quick reference for finding each MCP feature in the codebase. ### Tools (4 total) | Tool Name | Line | Description | |-----------|------|-------------| | `list_virtual_servers` | 937-1067 | Query BIG-IP virtual servers | | `list_bigip_devices` | 1069-1105 | List configured devices | | `manage_as3` | 1107-1415 | Install/upgrade AS3 | | `create_as3_app` | 1417-1682 | Create AS3 applications | **Declaration pattern:** ```python @mcp.tool async def tool_name(param: type, ctx: Context = None) -> str: """Tool description""" ``` ### Resources (3 total) | Resource URI | Line | Description | |--------------|------|-------------| | `config://server` | 1684-1697 | Server metadata | | `templates://available` | 1700-1743 | List all templates | | `templates://{template_name}` | 1746-1768 | Specific template content | **Declaration pattern:** ```python @mcp.resource("resource://uri") def resource_name() -> str: """Resource description""" return json.dumps(data, indent=2) ``` ### Prompts (2 total) | Prompt Name | Line | Description | |-------------|------|-------------| | `help_prompt` | 1775-1798 | General server help | | `create_app_workflow` | 1801-1875 | AS3 workflow guide | **Declaration pattern:** ```python @mcp.prompt def prompt_name() -> str: """Prompt description""" return """ Multi-line prompt content... """ ``` ### Context State (Usage locations) | Operation | Lines | Description | |-----------|-------|-------------| | Set token | 997, 1174, 1589 | Cache BIG-IP auth token | | Get token | 974, 1151, 1577 | Retrieve cached token | | Set VIP | 1490-1495 | Cache reserved VIP (intended) | | Get VIP | 1490-1495 | Retrieve cached VIP | | Clear state | 1659 | Clean up after deployment | **Usage pattern:** ```python # Set ctx.set_state(key: str, value: dict) # Get data = ctx.get_state(key: str) # Returns dict or None # Clear ctx.set_state(key: str, None) ``` ### Helper Functions | Function | Line | Purpose | |----------|------|---------| | `load_as3_template` | 697-716 | Load JSON template from file | | `render_as3_template` | 719-740 | Replace {{VARIABLES}} in template | | `validate_as3_declaration` | 743-760 | Validate AS3 JSON structure | | `deploy_as3_declaration` | 800-851 | POST declaration to BIG-IP | | `authenticate_bigip` | 177-215 | Get auth token from BIG-IP | --- ## Learning Path Recommended order to study and understand MCP features: ### Level 1: Fundamentals 1. **Start with Tools** (You already know this!) - Read: `list_virtual_servers` (server.py:937-1067) - Understand: Tool declaration, parameters, return values - Practice: Call the tool via Claude ### Level 2: Data Access 2. **Study Resources** - Read: `list_available_templates` (server.py:1700-1743) - Read: `get_template_content` (server.py:1746-1768) - Understand: Read-only data access pattern - Practice: "Show me available templates" - Compare: When to use Resource vs Tool ### Level 3: User Guidance 3. **Explore Prompts** - Read: `create_app_workflow` (server.py:1801-1875) - Understand: How Claude uses prompts for guidance - Practice: Ask Claude "How do I create an AS3 app?" - Experiment: Try different phrasings to trigger the prompt ### Level 4: State Management 4. **Master Context State** - Read: Token caching logic (server.py:974-998) - Read: VIP caching logic (server.py:1490-1495) - Understand: State lifecycle (set → get → clear) - Practice: Make multiple tool calls, observe caching - Experiment: Time tool calls with/without caching ### Level 5: Advanced Integration 5. **Understand Cross-Server** - Read: `create_as3_app` tool (server.py:1417-1682) - Read: phpIPAM helper functions (server.py:763-930) - Understand: How Claude orchestrates between servers - Practice: Full workflow (guided mode) - Experiment: Try direct mode vs guided mode ### Level 6: Synthesis 6. **Complete Workflow** - Run the full AS3 application creation workflow - Observe all 5 features working together - Trace the execution through this guide - Identify each feature usage in the flow --- ## Additional Resources ### Official Documentation - **MCP Specification**: https://modelcontextprotocol.io/docs/specification - **FastMCP 2.0 Docs**: https://gofastmcp.com/ ### This Codebase - **README.md**: Project overview and setup - **TEMPLATES.md**: Template system documentation - **CONFIGURATION.md**: Device configuration guide - **CLAUDE.md**: Usage examples ### Experimentation Tips 1. **Enable verbose logging**: See exactly what MCP calls Claude makes 2. **Use Claude Desktop devtools**: Monitor MCP communication 3. **Modify prompts**: See how it changes Claude's behavior 4. **Add new resources**: Practice exposing data 5. **Track state**: Add logging to see cache hits/misses --- ## Summary This BIG-IP MCP server demonstrates **all major MCP features**: | Feature | What It Does | Why It Matters | |---------|--------------|----------------| | **Tools** | Execute actions | Core functionality | | **Resources** | Expose data catalogs | Efficient data access | | **Prompts** | Guide Claude | Consistent UX | | **Context State** | Cache session data | Performance + UX | | **Cross-Server** | Coordinate systems | Complex workflows | **Key Takeaway:** MCP is more than just tools. It's a complete protocol for building AI-powered integrations with performance, usability, and composability built in. **Next Steps:** 1. Follow the [Learning Path](#learning-path) above 2. Experiment with each feature 3. Build your own MCP server using these patterns 4. Combine multiple MCP servers for complex workflows Happy learning! 🚀

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/arunhotra/mcp-bigip'

If you have feedback or need assistance with the MCP directory API, please join our Discord server