UNPKG

@hackle-io/hackle-mcp

Version:

Model Context Protocol server for Hackle

90 lines (89 loc) 2.97 kB
const BASE_URL = 'https://admin-api.hackle.io'; const ENVIRONMENT_KEY = process.env.ENVIRONMENT_KEY || 'PRODUCTION'; const API_KEY = process.env.API_KEY || ''; if (!API_KEY) { console.warn('API_KEY environment variable is not set'); } const DEFAULT_HEADERS = { accept: 'application/json', 'Content-Type': 'application/json', 'X-HACKLE-ADMIN-API-KEY': API_KEY, 'X-HACKLE-TIME-ZONE': Intl.DateTimeFormat().resolvedOptions().timeZone, }; class WebClient { static async request(method, path, options = {}) { const url = new URL(`${BASE_URL}${path}`); url.searchParams.set('environmentKey', ENVIRONMENT_KEY); if (typeof fetch === 'undefined') { return WebClient.fetchFallback(method, url, options); } const response = await fetch(url, { method, ...options, headers: { ...DEFAULT_HEADERS, ...options.headers, }, }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Hackle API error! status: ${response.status} - ${errorText}`); } return (await response.json()); } static async fetchFallback(method, url, options) { const { default: nodeFetch } = await import('node-fetch'); const { body, ...otherOptions } = options; if (body !== null && body !== undefined && typeof body !== 'string') { throw new Error(`[ERROR] Invalid body type: ${body}`); } const response = await nodeFetch(url, { method, headers: { ...DEFAULT_HEADERS, ...options.headers, }, body: body, ...otherOptions, }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Hackle API error! status: ${response.status} - ${errorText}`); } return (await response.json()); } static async get(path, options) { return this.request('GET', path, options); } static async post(path, body, options) { return this.request('POST', path, { ...options, body: JSON.stringify(body), headers: { ...options?.headers, }, }); } static async put(path, body, options) { return this.request('PUT', path, { ...options, body: JSON.stringify(body), headers: { ...options?.headers, }, }); } static async delete(path, options) { return this.request('DELETE', path, options); } static async patch(path, body, options) { return this.request('PATCH', path, { ...options, body: JSON.stringify(body), headers: { ...options?.headers, }, }); } } export default WebClient;