@hackle-io/hackle-mcp
Version:
Model Context Protocol server for Hackle
108 lines (107 loc) • 3.31 kB
JavaScript
const BASE_URL = "https://admin-api.hackle.io";
const ENVIRONMENT_KEY = process.env.ENVIRONMENT_KEY || "PRODUCTION";
const API_KEY = process.env.API_KEY || "";
// Deprecation notice — this local npm package is deprecated in favor of the remote MCP server.
console.error(
[
'',
'⚠️ [DEPRECATED] The local @hackle-io/hackle-mcp npm package is deprecated.',
' The Hackle MCP server is now available as a remote server (no npm/Node.js setup,',
' auto-updates, and where all new tools ship). This package will no longer receive',
' updates or new tools.',
'',
' ➡️ Remote server URL: https://mcp.hackle.io/mcp',
' ➡️ Migration guide: https://docs.hackle.io/external-link/model-context-protocol/migration',
'',
].join('\n'),
);
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,
"X-Hackle-Client": "hackle-local-mcp"
};
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 !== void 0 && typeof body !== "string") {
throw new Error(`[ERROR] Invalid body type: ${body}`);
}
const response = await nodeFetch(url, {
method,
headers: {
...DEFAULT_HEADERS,
...options.headers
},
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
}
});
}
}
var WebClient_default = WebClient;
export {
WebClient_default as default
};