/**
* AI-friendly structured error responses for Rippling MCP tools.
*/
export class RipplingApiError extends Error {
constructor(
message: string,
public readonly statusCode: number,
public readonly endpoint: string,
public readonly detail?: string
) {
super(message);
this.name = "RipplingApiError";
}
toToolResult() {
const parts = [`Error: ${this.message}`];
if (this.detail) parts.push(`Detail: ${this.detail}`);
parts.push(`Endpoint: ${this.endpoint}`);
parts.push(`Status: ${this.statusCode}`);
if (this.statusCode === 401) {
parts.push(
"Action: Check your RIPPLING_API_TOKEN or OAuth credentials. The token may be expired or invalid."
);
} else if (this.statusCode === 403) {
parts.push(
"Action: Your token lacks the required scope for this operation. Check Rippling API token permissions."
);
} else if (this.statusCode === 429) {
parts.push(
"Action: Rate limit exceeded. Wait a few seconds before retrying."
);
} else if (this.statusCode === 404) {
parts.push(
"Action: The requested resource was not found. Verify the ID is correct."
);
}
return {
content: [{ type: "text" as const, text: parts.join("\n") }],
isError: true,
};
}
}
export class RipplingConfigError extends Error {
constructor(message: string) {
super(message);
this.name = "RipplingConfigError";
}
toToolResult() {
return {
content: [
{
type: "text" as const,
text: `Configuration Error: ${this.message}\n\nTo fix: Set RIPPLING_API_TOKEN in your environment or .env file. Get a token from Rippling > Settings > API Tokens.`,
},
],
isError: true,
};
}
}