@gorizond/mcp-rancher-multi
Version:
MCP server for multiple Rancher Manager backends with Fleet GitOps support
77 lines (76 loc) • 2.78 kB
JavaScript
import { resolveToken } from './utils.js';
// Minimal Rancher client (v3 + k8s proxy)
export class RancherClient {
baseUrl;
token;
insecure;
caCertPemBase64;
constructor(cfg) {
this.baseUrl = cfg.baseUrl.replace(/\/$/, "");
this.token = resolveToken(cfg.token);
this.insecure = !!cfg.insecureSkipTlsVerify;
this.caCertPemBase64 = cfg.caCertPemBase64;
}
headers(extra) {
const h = {
"Authorization": `Bearer ${this.token}`,
"Accept": "application/json",
...extra,
};
return h;
}
async requestJSON(url, init) {
const res = await fetch(url, {
...init,
headers: this.headers(init?.headers),
});
if (!res.ok) {
const text = await res.text().catch(() => "");
throw new Error(`HTTP ${res.status} ${res.statusText} — ${url}
${text}`);
}
return (await res.json());
}
async listClusters() {
const url = `${this.baseUrl}/v3/clusters`;
const res = await this.requestJSON(url);
return res.data;
}
async listNodes(clusterId) {
const p = clusterId ? `?clusterId=${encodeURIComponent(clusterId)}` : "";
const url = `${this.baseUrl}/v3/nodes${p}`;
const res = await this.requestJSON(url);
return res.data;
}
async listProjects(clusterId) {
const url = `${this.baseUrl}/v3/projects?clusterId=${encodeURIComponent(clusterId)}`;
const res = await this.requestJSON(url);
return res.data;
}
async generateKubeconfig(clusterId) {
const url = `${this.baseUrl}/v3/clusters/${encodeURIComponent(clusterId)}?action=generateKubeconfig`;
const res = await this.requestJSON(url, { method: "POST", headers: { "content-type": "application/json" } });
return res.config;
}
async k8s(clusterId, k8sPath, init) {
const pathClean = k8sPath.startsWith("/") ? k8sPath : `/${k8sPath}`;
const url = `${this.baseUrl}/k8s/clusters/${encodeURIComponent(clusterId)}${pathClean}`;
const res = await fetch(url, {
...init,
headers: this.headers({ "Accept": "application/json", ...init?.headers }),
});
if (!res.ok) {
const text = await res.text().catch(() => "");
throw new Error(`K8s proxy HTTP ${res.status} ${res.statusText} — ${url}
${text}`);
}
const ct = res.headers.get("content-type") || "";
if (ct.includes("application/json"))
return res.json();
return res.text();
}
async listNamespaces(clusterId) {
const out = await this.k8s(clusterId, "/api/v1/namespaces");
return out?.items ?? out;
}
}