Skip to main content
Glama
RMITBLOG

Parallels RAS MCP Server

by RMITBLOG

ras_farm_get_config

Retrieve Parallels RAS farm configuration settings to review farm setup, verify domain configuration, or check backup scheduling.

Instructions

Get RAS farm configuration settings, including farm name, domain, backup settings, and global options. Use this to review the overall farm setup, verify domain configuration, or check backup scheduling.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The ras_farm_get_config tool registration and handler implementation. The handler is an async function that calls rasClient.get('/api/farm-settings/farm') to retrieve farm configuration data and returns it as JSON text content.
    server.registerTool( "ras_farm_get_config", { title: "Farm Configuration", description: "Get RAS farm configuration settings, including farm name, domain, backup " + "settings, and global options. Use this to review the overall farm setup, " + "verify domain configuration, or check backup scheduling.", annotations: READ_ONLY_ANNOTATIONS, inputSchema: {}, }, async () => { try { const data = await rasClient.get("/api/farm-settings/farm"); return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] }; } catch (err) { return { content: [{ type: "text" as const, text: sanitiseError(err, "Failed to retrieve farm config") }], isError: true }; } } );
  • Helper function sanitiseError that removes sensitive information (auth tokens, passwords) from error messages and truncates excessively long responses to avoid leaking internal details.
    function sanitiseError(err: unknown, context: string): string { const raw = err instanceof Error ? err.message : String(err); // Remove anything that looks like a token or password value let sanitised = raw .replace(/auth_token[=:]\s*\S+/gi, "auth_token=[REDACTED]") .replace(/password[=:]\s*\S+/gi, "password=[REDACTED]"); // Truncate excessively long API response bodies if (sanitised.length > 500) { sanitised = sanitised.substring(0, 500) + "... (truncated)"; } return `${context}: ${sanitised}`; }
  • RasClient class that handles authentication, session management, and GET requests to the RAS API. Includes lazy authentication, automatic retry on 401 responses, and request timeouts.
    class RasClient { private baseUrl: string; private authToken: string | null = null; private headers: Record<string, string> = { "Content-Type": "application/json; api-version=1.0", }; constructor() { this.baseUrl = `https://${RAS_HOST}:${RAS_PORT}`; } /** * Authenticate with the RAS API and cache the auth token. */ private async login(): Promise<void> { if (!RAS_HOST || !RAS_USERNAME || !RAS_PASSWORD) { throw new Error( "Missing required environment variables: RAS_HOST, RAS_USERNAME, RAS_PASSWORD" ); } const response = await fetch(`${this.baseUrl}/api/session/logon`, { method: "POST", headers: this.headers, body: JSON.stringify({ username: RAS_USERNAME, password: RAS_PASSWORD, }), signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), }); if (!response.ok) { const body = await response.text(); throw new Error( `RAS login failed (HTTP ${response.status}): ${body.substring(0, 300)}` ); } const data = await response.json(); this.authToken = data.authToken ?? data.AuthToken ?? null; if (!this.authToken) { throw new Error("RAS login response did not contain an auth token"); } } /** * End the current RAS API session. */ async logoff(): Promise<void> { if (!this.authToken) return; try { await fetch(`${this.baseUrl}/api/session/logoff`, { method: "POST", headers: { ...this.headers, auth_token: this.authToken, }, signal: AbortSignal.timeout(5_000), }); } catch { // Best-effort logoff — ignore errors on shutdown } this.authToken = null; } /** * Make a GET request to the RAS API. * Handles lazy authentication, automatic retry on 401, and request timeouts. */ async get(path: string): Promise<unknown> { // Ensure we have a valid session if (!this.authToken) { await this.login(); } const fetchOptions = { method: "GET" as const, headers: { ...this.headers, auth_token: this.authToken!, }, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), }; let response = await fetch(`${this.baseUrl}${path}`, fetchOptions); // Token may have expired — re-authenticate once and retry if (response.status === 401) { await this.login(); response = await fetch(`${this.baseUrl}${path}`, { ...fetchOptions, headers: { ...this.headers, auth_token: this.authToken!, }, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), }); } if (!response.ok) { const body = await response.text(); throw new Error( `RAS API error (HTTP ${response.status}) on ${path}: ${body.substring(0, 300)}` ); } return response.json(); } }
  • Exported singleton instance of RasClient used by all tools including ras_farm_get_config, and the sanitiseError helper function.
    export const rasClient = new RasClient(); export { sanitiseError };

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/RMITBLOG/ParallelsRAS_MCP'

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