/**
* Server Response Formatter — converts raw JSON to readable markdown
*
* Transforms server tool JSON responses into:
* - Markdown tables for arrays of flat objects
* - Bold key-value pairs for single objects
* - JSON fences for complex nested data
*/
// ============================================================================
// COLUMN PRIORITIES — per tool category
// ============================================================================
const PRIORITY_COLUMNS: Record<string, string[]> = {
analytics: ["name", "revenue", "quantity", "total", "count", "average", "period"],
products: ["name", "sku", "status", "price", "category", "stock_quantity"],
inventory: ["name", "product_name", "quantity", "location", "location_name", "status"],
customers: ["first_name", "last_name", "email", "phone", "status", "loyalty_tier"],
orders: ["order_number", "status", "total", "customer_name", "created_at"],
supply_chain: ["name", "status", "quantity", "supplier", "location", "expected_delivery_date"],
workflows: ["name", "status", "trigger_type", "created_at", "last_run"],
email: ["subject", "to", "status", "sent_at", "category"],
};
// Keys that are always deprioritized (shown last or hidden)
const LOW_PRIORITY_KEYS = new Set([
"id", "store_id", "created_at", "updated_at", "deleted_at",
"created_by", "updated_by", "metadata", "raw_data",
]);
// ============================================================================
// FORMATTERS
// ============================================================================
function isNarrow(): boolean {
return (process.stdout.columns || 80) < 90;
}
function truncateUuid(val: string): string {
// UUID pattern: 8-4-4-4-12 hex chars
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(val)) {
return val.slice(0, 8);
}
return val;
}
function formatValue(val: unknown): string {
if (val === null || val === undefined) return "—";
if (typeof val === "boolean") return val ? "\u2713" : "\u2715";
if (typeof val === "number") return val.toLocaleString();
if (typeof val === "string") {
// Money detection
if (/^\d+\.\d{2}$/.test(val) && parseFloat(val) > 0) {
return `$${parseFloat(val).toLocaleString(undefined, { minimumFractionDigits: 2 })}`;
}
// UUID truncation
const truncated = truncateUuid(val);
// Date formatting
if (/^\d{4}-\d{2}-\d{2}T/.test(val)) {
return val.slice(0, 10);
}
// Truncate long strings
if (truncated.length > 40) return truncated.slice(0, 37) + "...";
return truncated;
}
if (Array.isArray(val)) return `[${val.length} items]`;
if (typeof val === "object") return "{...}";
return String(val);
}
function formatMoneyValue(val: unknown): string {
if (typeof val === "number") {
return `$${val.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
}
return formatValue(val);
}
function isMoneyKey(key: string): boolean {
return /price|cost|revenue|total|amount|subtotal|tax|discount|budget/i.test(key);
}
function prettifyKey(key: string): string {
return key
.replace(/_/g, " ")
.replace(/\bid\b/gi, "ID")
.replace(/\b\w/g, c => c.toUpperCase());
}
// ============================================================================
// COLUMN SELECTION
// ============================================================================
function selectColumns(rows: Record<string, unknown>[], toolName?: string): string[] {
if (rows.length === 0) return [];
// Collect all keys from first few rows
const allKeys = new Set<string>();
for (const row of rows.slice(0, 5)) {
for (const key of Object.keys(row)) allKeys.add(key);
}
// Find matching priority list
const maxCols = isNarrow() ? 4 : 6;
let priority: string[] = [];
if (toolName) {
// Match tool name to category
for (const [category, cols] of Object.entries(PRIORITY_COLUMNS)) {
if (toolName.toLowerCase().includes(category)) {
priority = cols;
break;
}
}
}
// Build ordered column list: priority first, then remaining non-low-priority
const selected: string[] = [];
for (const col of priority) {
if (allKeys.has(col) && selected.length < maxCols) {
selected.push(col);
}
}
// Fill remaining slots with non-priority, non-low-priority keys
for (const key of allKeys) {
if (selected.length >= maxCols) break;
if (selected.includes(key)) continue;
if (LOW_PRIORITY_KEYS.has(key)) continue;
// Skip nested objects/arrays in table columns
const sample = rows[0][key];
if (typeof sample === "object" && sample !== null && !Array.isArray(sample)) continue;
selected.push(key);
}
return selected;
}
// ============================================================================
// TABLE BUILDER
// ============================================================================
function buildTable(rows: Record<string, unknown>[], columns: string[]): string {
if (columns.length === 0 || rows.length === 0) return "";
const headers = columns.map(prettifyKey);
// Calculate column widths
const widths = columns.map((col, i) => {
let max = headers[i].length;
for (const row of rows) {
const val = isMoneyKey(col) ? formatMoneyValue(row[col]) : formatValue(row[col]);
max = Math.max(max, val.length);
}
return Math.min(max, 30); // Cap individual column width
});
// Header row
const headerRow = columns.map((_, i) => headers[i].padEnd(widths[i])).join(" | ");
const separator = widths.map(w => "-".repeat(w)).join(" | ");
// Data rows
const dataRows = rows.map(row =>
columns.map((col, i) => {
const val = isMoneyKey(col) ? formatMoneyValue(row[col]) : formatValue(row[col]);
// Right-align numbers and money
const isNum = typeof row[col] === "number" || isMoneyKey(col);
return isNum ? val.padStart(widths[i]) : val.padEnd(widths[i]);
}).join(" | ")
);
return [
`| ${headerRow} |`,
`| ${separator} |`,
...dataRows.map(r => `| ${r} |`),
].join("\n");
}
// ============================================================================
// MAIN FORMATTER
// ============================================================================
function detectToolCategory(toolName?: string): string | undefined {
if (!toolName) return undefined;
const name = toolName.toLowerCase();
for (const category of Object.keys(PRIORITY_COLUMNS)) {
if (name.includes(category)) return category;
}
return undefined;
}
function isFlatObject(obj: unknown): obj is Record<string, unknown> {
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) return false;
for (const val of Object.values(obj)) {
if (typeof val === "object" && val !== null && !Array.isArray(val)) return false;
}
return true;
}
/**
* Format a server tool response as readable markdown.
*
* @param data - The raw response data (parsed JSON)
* @param toolName - Optional tool name for smart column selection
* @returns Formatted markdown string
*/
export function formatServerResponse(data: unknown, toolName?: string): string {
// String passthrough
if (typeof data === "string") return data;
// Null/undefined
if (data === null || data === undefined) return "No data returned.";
// Empty array
if (Array.isArray(data) && data.length === 0) return "No results found.";
// Array of flat objects → markdown table
if (Array.isArray(data) && data.length > 0 && typeof data[0] === "object" && data[0] !== null) {
const rows = data as Record<string, unknown>[];
const columns = selectColumns(rows, toolName);
if (columns.length > 0) {
const category = detectToolCategory(toolName);
const label = category ? prettifyKey(category) : "Results";
const header = `**${label}** (${rows.length} result${rows.length !== 1 ? "s" : ""})`;
const table = buildTable(rows, columns);
return `${header}\n\n${table}`;
}
}
// Single flat object → bold key-value pairs
if (isFlatObject(data)) {
const entries = Object.entries(data as Record<string, unknown>)
.filter(([key]) => !LOW_PRIORITY_KEYS.has(key));
if (entries.length > 0 && entries.length <= 20) {
return entries
.map(([key, val]) => {
const fmtVal = isMoneyKey(key) ? formatMoneyValue(val) : formatValue(val);
return `**${prettifyKey(key)}**: ${fmtVal}`;
})
.join("\n");
}
}
// Object with a data/results/items array (common API wrapper pattern)
if (typeof data === "object" && data !== null && !Array.isArray(data)) {
const obj = data as Record<string, unknown>;
for (const key of ["data", "results", "items", "rows", "records"]) {
if (Array.isArray(obj[key]) && (obj[key] as unknown[]).length > 0) {
// Format the nested array and prepend any summary fields
const summaryFields: string[] = [];
for (const [k, v] of Object.entries(obj)) {
if (k === key) continue;
if (typeof v !== "object" || v === null) {
summaryFields.push(`**${prettifyKey(k)}**: ${formatValue(v)}`);
}
}
const arrayResult = formatServerResponse(obj[key], toolName);
return summaryFields.length > 0
? `${summaryFields.join(" | ")}\n\n${arrayResult}`
: arrayResult;
}
}
}
// Fallback: JSON fence
const json = JSON.stringify(data, null, 2);
return "```json\n" + json + "\n```";
}