/** * Compatibility & template tools: suggest_alternatives, get_templates */ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { pool } from "../db.js"; export async function registerCompatibilityTools(server: McpServer): Promise { // --- Tool: suggest_alternatives --- server.tool( "suggest_alternatives", "Suggest alternative transceivers with similar specs. Useful for finding cheaper or more available options.", { part_number: z.string().describe("Part number, slug, or standard name"), optimize_for: z.enum(["price", "availability", "performance"]).default("price"), }, async ({ part_number, optimize_for }) => { // Find the reference transceiver const refResult = await pool.query( `SELECT t.id, t.slug, t.standard_name, t.form_factor, t.speed_gbps, t.reach_meters, t.fiber_type, t.wdm_type, t.connector FROM transceivers t WHERE t.slug ILIKE $1 OR t.part_number ILIKE $1 OR t.standard_name ILIKE $1 LIMIT 1`, [`%${part_number}%`] ); if (refResult.rows.length === 0) { return { content: [{ type: "text", text: `Reference transceiver not found: "${part_number}"` }], }; } const ref = refResult.rows[0]; // Find alternatives: same form_factor + speed, similar reach const altResult = await pool.query( `SELECT t.id, t.slug, t.standard_name, t.form_factor, t.speed, t.reach_label, t.fiber_type, t.connector, v.name as vendor, (SELECT MIN(po.price) FROM price_observations po WHERE po.transceiver_id = t.id AND po.time > NOW() - INTERVAL '7 days' ) as min_price, (SELECT COUNT(DISTINCT po.source_vendor_id) FROM price_observations po WHERE po.transceiver_id = t.id AND po.stock_level = 'in_stock' AND po.time > NOW() - INTERVAL '7 days' ) as vendor_count FROM transceivers t LEFT JOIN vendors v ON v.id = t.vendor_id WHERE t.form_factor = $1 AND t.speed_gbps = $2 AND t.fiber_type = $3 AND ABS(t.reach_meters - $4) <= $4 * 0.2 AND t.id != $5 ORDER BY CASE $6 WHEN 'price' THEN (SELECT MIN(po.price) FROM price_observations po WHERE po.transceiver_id = t.id) WHEN 'availability' THEN -(SELECT COUNT(DISTINCT po.source_vendor_id) FROM price_observations po WHERE po.transceiver_id = t.id AND po.stock_level = 'in_stock') ELSE t.power_consumption_w END ASC NULLS LAST LIMIT 10`, [ref.form_factor, ref.speed_gbps, ref.fiber_type, ref.reach_meters, ref.id, optimize_for] ); return { content: [{ type: "text", text: JSON.stringify({ reference: { slug: ref.slug, standard: ref.standard_name, form_factor: ref.form_factor, speed_gbps: ref.speed_gbps, reach_meters: ref.reach_meters, }, optimize_for, alternatives: altResult.rows, }, null, 2), }], }; } ); // --- Tool: get_templates --- server.tool( "get_templates", "Find FlexBox coding templates or switch configuration templates for specific vendor/technology combinations.", { type: z.enum(["flexbox_coding", "switch_config"]).describe("Template type"), switch_vendor: z.string().optional().describe("Switch vendor, e.g. 'Cisco', 'Juniper', 'Arista'"), transceiver_type: z.string().optional().describe("e.g. 'SFP+', 'QSFP28', '10G', '100G'"), technology: z.string().optional().describe("CWDM, DWDM, BiDi, SR, LR, ER, ZR, etc."), }, async ({ type, switch_vendor, transceiver_type, technology }) => { const conditions = [`t.template_type = $1`]; const values: unknown[] = [type]; let idx = 2; if (switch_vendor) { conditions.push(`t.switch_vendor ILIKE $${idx}`); values.push(`%${switch_vendor}%`); idx++; } if (transceiver_type) { conditions.push(`t.transceiver_type ILIKE $${idx}`); values.push(`%${transceiver_type}%`); idx++; } if (technology) { conditions.push(`t.technology ILIKE $${idx}`); values.push(`%${technology}%`); idx++; } const result = await pool.query( `SELECT t.id, t.name, t.template_type, t.switch_vendor, t.transceiver_type, t.technology, t.content, t.description, t.notes, t.verified, t.firmware_version FROM templates t WHERE ${conditions.join(" AND ")} ORDER BY t.verified DESC, t.name ASC LIMIT 20`, values ); if (result.rows.length === 0) { return { content: [{ type: "text", text: `No ${type} templates found for the given criteria. Templates are added as they are verified in the field.`, }], }; } return { content: [{ type: "text", text: JSON.stringify({ templates: result.rows, count: result.rows.length }, null, 2), }], }; } ); }