Skip to main content
Glama

Palo Alto Networks MCP Server Suite

by packetracer
index.ts12.5 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js'; import axios, { AxiosError } from 'axios'; const API_KEY = process.env.PANOS_API_KEY; const API_BASE_URL = process.env.PANOS_API_BASE_URL || 'https://firewall.example.com/restapi/v11.0'; if (!API_KEY) { throw new Error('PANOS_API_KEY environment variable is required'); } type ResourceCategories = { OBJECTS: string[]; POLICIES: string[]; NETWORK: string[]; DEVICES: string[]; } const RESOURCE_CATEGORIES: ResourceCategories = { OBJECTS: [ 'Addresses', 'AddressGroups', 'Regions', 'DynamicUserGroups', 'Applications', 'ApplicationGroups', 'ApplicationFilters', 'Services', 'ServiceGroups', 'Tags', 'GlobalProtectHIPObjects', 'GlobalProtectHIPProfiles', 'ExternalDynamicLists', 'CustomDataPatterns', 'CustomSpywareSignatures', 'CustomVulnerabilitySignatures', 'CustomURLCategories', 'AntivirusSecurityProfiles', 'AntiSpywareSecurityProfiles', 'VulnerabilityProtectionSecurityProfiles', 'URLFilteringSecurityProfiles', 'FileBlockingSecurityProfiles', 'WildFireAnalysisSecurityProfiles', 'DataFilteringSecurityProfiles', 'DoSProtectionSecurityProfiles', 'SecurityProfileGroups', 'LogForwardingProfiles', 'AuthenticationEnforcements', 'DecryptionProfiles', 'PacketBrokerProfiles', 'SDWANPathQualityProfiles', 'SDWANTrafficDistributionProfiles', 'SDWANSaasQualityProfiles', 'SDWANErrorCorrection', 'Schedules' ], POLICIES: [ 'SecurityRules', 'NATRules', 'QoSRules', 'PolicyBasedForwardingRules', 'DecryptionRules', 'NetworkPacketBrokerRules', 'TunnelInspectionRules', 'ApplicationOverrideRules', 'AuthenticationRules', 'DoSRules', 'SDWANRules' ], NETWORK: [ 'EthernetInterfaces', 'AggregateEthernetInterfaces', 'VLANInterfaces', 'LoopbackInterfaces', 'TunnelIntefaces', 'SDWANInterfaces', 'Zones', 'VLANs', 'VirtualWires', 'VirtualRouters', 'IPSecTunnels', 'GRETunnels', 'DHCPServers', 'DHCPRelays', 'DNSProxies', 'GlobalProtectPortals', 'GlobalProtectGateways', 'GlobalProtectGatewayAgentTunnels', 'GlobalProtectGatewaySatelliteTunnels', 'GlobalProtectGatewayMDMServers', 'GlobalProtectClientlessApps', 'GlobalProtectClientlessAppGroups', 'QoSInterfaces', 'LLDP', 'GlobalProtectIPSecCryptoNetworkProfiles', 'IKEGatewayNetworkProfiles', 'IKECryptoNetworkProfiles', 'MonitorNetworkProfiles', 'InterfaceManagementNetworkProfiles', 'ZoneProtectionNetworkProfiles', 'QoSNetworkProfiles', 'LLDPNetworkProfiles', 'BFDNetworkProfiles', 'SDWANInterfaceProfiles' ], DEVICES: [ 'VirtualSystems', 'SNMPTrapServerProfiles', 'SyslogServerProfiles', 'EmailServerProfiles', 'HttpServerProfiles', 'LDAPServerProfiles' ] }; interface ListResourcesArgs { category: keyof ResourceCategories; resource_type: string; } function isListResourcesArgs(args: unknown): args is ListResourcesArgs { if (typeof args !== 'object' || args === null) return false; const typedArgs = args as Record<string, unknown>; return ( typeof typedArgs.category === 'string' && typeof typedArgs.resource_type === 'string' && Object.keys(RESOURCE_CATEGORIES).includes(typedArgs.category as string) ); } class PaloAltoServer { private server: Server; private axiosInstance; constructor() { this.server = new Server( { name: 'paloalto-server', version: '0.1.0', }, { capabilities: { tools: {}, }, } ); this.axiosInstance = axios.create({ baseURL: API_BASE_URL, headers: { 'X-PAN-KEY': API_KEY, 'Accept': 'application/json' } }); this.setupToolHandlers(); // Error handling this.server.onerror = (error) => console.error('[MCP Error]', error); process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } private setupToolHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'get_system_info', description: 'Get system information from the Palo Alto firewall', inputSchema: { type: 'object', properties: {}, }, }, { name: 'list_resources', description: 'List resources from a specific category', inputSchema: { type: 'object', properties: { category: { type: 'string', enum: Object.keys(RESOURCE_CATEGORIES), description: 'Resource category to list' }, resource_type: { type: 'string', description: 'Specific resource type within the category' } }, required: ['category', 'resource_type'] } }, { name: 'view_config_node_values', description: 'View configuration node values for XPath on the Palo Alto firewall', inputSchema: { type: 'object', properties: { xpath: { type: 'string', description: 'XPath to the configuration node' } }, required: ['xpath'] } }, { name: 'multi_move_clone_configuration', description: 'Multi-Move or Multi-Clone the configuration of the Palo Alto firewall', inputSchema: { type: 'object', properties: { config_paths: { type: 'array', items: { type: 'string' }, description: 'Paths to the configurations to move or clone' }, new_location: { type: 'string', description: 'New location for the configurations' }, action: { type: 'string', enum: ['move', 'clone'], description: 'Action to perform' } }, required: ['config_paths', 'new_location', 'action'] } } ] })); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { switch (request.params.name) { case 'get_system_info': { const response = await this.axiosInstance.get('/Device/VirtualSystems'); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; } case 'list_resources': { const rawArgs = request.params.arguments; if (!isListResourcesArgs(rawArgs)) { throw new McpError( ErrorCode.InvalidParams, 'Invalid arguments for list_resources' ); } const { category, resource_type } = rawArgs; const categoryResources = RESOURCE_CATEGORIES[category]; if (!categoryResources.includes(resource_type)) { throw new McpError( ErrorCode.InvalidParams, `Invalid resource type for category ${category}: ${resource_type}` ); } const response = await this.axiosInstance.get(`/Objects/${resource_type}`); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; } case 'view_config_node_values': { const { xpath } = request.params.arguments as { xpath: string }; const response = await this.axiosInstance.get('/config/xpath', { params: { xpath } }); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; } case 'multi_move_clone_configuration': { const { config_paths, new_location, action } = request.params.arguments as { config_paths: string[], new_location: string, action: 'move' | 'clone' }; const endpoint = action === 'move' ? 'MultiMove' : 'MultiClone'; const response = await this.axiosInstance.post( `/Configuration/${endpoint}`, { config_paths, new_location } ); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; } default: throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } } catch (error) { const axiosError = error as AxiosError; throw new McpError( ErrorCode.InternalError, `Palo Alto API error: ${axiosError.message}` ); } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Palo Alto MCP server running on stdio'); } } const server = new PaloAltoServer(); server.run().catch(console.error);

Latest Blog Posts

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/packetracer/mcpserver'

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