import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
/**
* Custom error codes for Birst-specific errors
*/
export const BirstErrorCode = {
AUTH_REQUIRED: -32001,
FORBIDDEN: -32002,
NOT_FOUND: -32003,
RATE_LIMITED: -32004,
BQL_SYNTAX_ERROR: -32005,
} as const;
/**
* Create an MCP error from a Birst API error
*/
export function createMcpError(
code: number,
message: string,
data?: unknown
): McpError {
return new McpError(code, message, data);
}
/**
* Map HTTP status code to MCP error
*/
export function mapHttpErrorToMcp(
status: number,
message: string,
body?: unknown
): McpError {
switch (status) {
case 400:
return createMcpError(
ErrorCode.InvalidParams,
`Bad request: ${message}`,
body
);
case 401:
return createMcpError(
BirstErrorCode.AUTH_REQUIRED,
`Authentication required: ${message}`,
body
);
case 403:
return createMcpError(
BirstErrorCode.FORBIDDEN,
`Access forbidden: ${message}`,
body
);
case 404:
return createMcpError(
BirstErrorCode.NOT_FOUND,
`Resource not found: ${message}`,
body
);
case 409:
return createMcpError(
ErrorCode.InvalidParams,
`Conflict: ${message}`,
body
);
case 422:
return createMcpError(
BirstErrorCode.BQL_SYNTAX_ERROR,
`Validation error: ${message}`,
body
);
case 429:
return createMcpError(
BirstErrorCode.RATE_LIMITED,
`Rate limited: ${message}`,
body
);
case 500:
case 502:
case 503:
case 504:
return createMcpError(
ErrorCode.InternalError,
`Server error: ${message}`,
body
);
default:
return createMcpError(
ErrorCode.InternalError,
`Unexpected error (${status}): ${message}`,
body
);
}
}
/**
* Extract error message from API response body
*/
export function extractErrorMessage(body: unknown): string {
if (typeof body === "string") {
return body;
}
if (body && typeof body === "object") {
const obj = body as Record<string, unknown>;
// Common error message fields
if (typeof obj.message === "string") return obj.message;
if (typeof obj.error === "string") return obj.error;
if (typeof obj.errorMessage === "string") return obj.errorMessage;
if (typeof obj.detail === "string") return obj.detail;
// Nested error object
if (obj.error && typeof obj.error === "object") {
const errorObj = obj.error as Record<string, unknown>;
if (typeof errorObj.message === "string") return errorObj.message;
}
}
return "Unknown error";
}