Skip to main content
Glama

Huntress-MCP-Server

#!/usr/bin/env node import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import axios, { AxiosInstance } from 'axios'; // Configuration schema for Smithery export const configSchema = z.object({ huntressApiKey: z.string().describe("Your Huntress API Key"), huntressApiSecret: z.string().describe("Your Huntress API Secret"), debug: z.boolean().default(false).describe("Enable debug logging") }); export default function ({ config }: { config: z.infer<typeof configSchema> }) { const server = new McpServer({ name: 'Huntress MCP Server', version: '1.0.0' }); // Lazy-loaded axios instance let axiosInstance: AxiosInstance | null = null; let lastRequestTime = 0; let requestCount = 0; // Initialize axios instance only when needed const getAxiosInstance = () => { if (!axiosInstance) { axiosInstance = axios.create({ baseURL: 'https://api.huntress.io/v1', headers: { Authorization: `Basic ${Buffer.from(`${config.huntressApiKey}:${config.huntressApiSecret}`).toString('base64')}`, }, }); } return axiosInstance; }; // Rate limiting helper const checkRateLimit = async () => { const now = Date.now(); if (now - lastRequestTime >= 60000) { requestCount = 0; lastRequestTime = now; } else if (requestCount >= 60) { const waitTime = 60000 - (now - lastRequestTime); await new Promise(resolve => setTimeout(resolve, waitTime)); requestCount = 0; lastRequestTime = Date.now(); } requestCount++; }; // API request helper const makeRequest = async (endpoint: string, params: any = {}) => { await checkRateLimit(); const client = getAxiosInstance(); try { const response = await client.get(endpoint, { params }); return response.data; } catch (error: any) { if (axios.isAxiosError(error)) { throw new Error(`Huntress API error: ${error.response?.data?.message || error.message}`); } throw error; } }; // Health check tool (works without full config for discovery) server.tool( 'health_check', 'Check server status and authentication configuration', {}, async () => { const hasCredentials = !!(config.huntressApiKey && config.huntressApiSecret); return { content: [{ type: 'text', text: `Huntress MCP Server Health Check\n\n` + `Status: ${hasCredentials ? 'Ready' : 'Requires Configuration'}\n` + `Version: 1.0.0\n` + `Timestamp: ${new Date().toISOString()}\n\n` + `${hasCredentials ? 'Server is properly configured and ready to execute tools.' : 'Missing required configuration:\n' + '- huntressApiKey: Your Huntress API Key\n' + '- huntressApiSecret: Your Huntress API Secret\n\n' + 'For setup instructions, visit: https://docs.huntress.com/api' }` }] }; } ); // Get account information server.tool( 'get_account_info', 'Get information about the current account', {}, async () => { const data = await makeRequest('/account'); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); // List organizations server.tool( 'list_organizations', 'List organizations in the account', { page: z.number().min(1).default(1).describe('Page number (starts at 1)'), limit: z.number().min(1).max(500).default(50).describe('Number of results per page (1-500)') }, async ({ page, limit }) => { const data = await makeRequest('/organizations', { page, limit }); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); // Get organization details server.tool( 'get_organization', 'Get details of a specific organization', { organization_id: z.number().describe('Organization ID') }, async ({ organization_id }) => { const data = await makeRequest(`/organizations/${organization_id}`); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); // List agents server.tool( 'list_agents', 'List agents in the account', { page: z.number().min(1).default(1).describe('Page number (starts at 1)'), limit: z.number().min(1).max(500).default(50).describe('Number of results per page (1-500)') }, async ({ page, limit }) => { const data = await makeRequest('/agents', { page, limit }); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); // Get agent details server.tool( 'get_agent', 'Get details of a specific agent', { agent_id: z.number().describe('Agent ID') }, async ({ agent_id }) => { const data = await makeRequest(`/agents/${agent_id}`); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); // List incidents server.tool( 'list_incidents', 'List incidents in the account', { page: z.number().min(1).default(1).describe('Page number (starts at 1)'), limit: z.number().min(1).max(500).default(50).describe('Number of results per page (1-500)'), status: z.enum(['active', 'resolved', 'ignored']).optional().describe('Filter by incident status') }, async ({ page, limit, status }) => { const params: any = { page, limit }; if (status) params.status = status; const data = await makeRequest('/incidents', params); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); // Get incident details server.tool( 'get_incident', 'Get details of a specific incident', { incident_id: z.number().describe('Incident ID') }, async ({ incident_id }) => { const data = await makeRequest(`/incidents/${incident_id}`); return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } ); return server.server; }

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/DynamicEndpoints/huntress-mcp-server'

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