Scrapers:
- atgbics.ts: PlaywrightCrawler for UK vendor ATGBICS (Shopify store),
scrapes SFP/SFP+/SFP28/QSFP+/QSFP28/QSFP-DD in GBP, max 50 pages/run
- prolabs.ts: HttpCrawler for ProLabs (Legrand subsidiary), USD pricing,
category-driven crawl with reach/fiber/speed detection
- Both registered in scheduler (every 8h, staggered) and index.ts CLI
MCP HTTP Server:
- packages/mcp-server/src/http-server.ts: Express + SSEServerTransport
- Exposes all 12 TIP tools via GET /sse + POST /message
- Bearer token auth (MCP_SECRET env), CORS-configurable
- GET /health → { status: "ok", tools: 12 }
- Port: MCP_HTTP_PORT (default 3201)
SQL + tools:
- sql/006-009: seed scripts for whitebox switches, vendors, assets
- switch-docs.ts: MCP tool for switch documentation queries
70 lines
4.6 KiB
SQL
70 lines
4.6 KiB
SQL
-- TIP: Transceiver Intelligence Platform
|
|
-- Migration 008: Product Assets (Images, Datasheets, Manuals)
|
|
--
|
|
-- Adds columns for product images, datasheet PDFs, and manual/guide links
|
|
-- to both switches and transceivers tables.
|
|
|
|
-- ═══════════════════════════════════════════════════════
|
|
-- SWITCHES: Product assets
|
|
-- ═══════════════════════════════════════════════════════
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS image_url TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS image_local_path TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS datasheet_url TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS datasheet_local_path TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS manual_urls JSONB DEFAULT '[]'::jsonb;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS quick_start_url TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS cli_reference_url TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS release_notes_url TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS product_page_url TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS eol_url TEXT;
|
|
ALTER TABLE switches ADD COLUMN IF NOT EXISTS assets_scraped_at TIMESTAMPTZ;
|
|
|
|
-- ═══════════════════════════════════════════════════════
|
|
-- TRANSCEIVERS: Product assets
|
|
-- ═══════════════════════════════════════════════════════
|
|
ALTER TABLE transceivers ADD COLUMN IF NOT EXISTS image_url TEXT;
|
|
ALTER TABLE transceivers ADD COLUMN IF NOT EXISTS image_local_path TEXT;
|
|
ALTER TABLE transceivers ADD COLUMN IF NOT EXISTS datasheet_url TEXT;
|
|
ALTER TABLE transceivers ADD COLUMN IF NOT EXISTS datasheet_local_path TEXT;
|
|
ALTER TABLE transceivers ADD COLUMN IF NOT EXISTS manual_urls JSONB DEFAULT '[]'::jsonb;
|
|
ALTER TABLE transceivers ADD COLUMN IF NOT EXISTS product_page_url TEXT;
|
|
ALTER TABLE transceivers ADD COLUMN IF NOT EXISTS assets_scraped_at TIMESTAMPTZ;
|
|
|
|
-- ═══════════════════════════════════════════════════════
|
|
-- VENDORS: Documentation portal URLs
|
|
-- ═══════════════════════════════════════════════════════
|
|
ALTER TABLE vendors ADD COLUMN IF NOT EXISTS docs_portal_url TEXT;
|
|
ALTER TABLE vendors ADD COLUMN IF NOT EXISTS datasheet_library_url TEXT;
|
|
ALTER TABLE vendors ADD COLUMN IF NOT EXISTS image_cdn_base TEXT;
|
|
ALTER TABLE vendors ADD COLUMN IF NOT EXISTS support_portal_url TEXT;
|
|
|
|
-- ═══════════════════════════════════════════════════════
|
|
-- DOCUMENTS table for downloaded PDFs (datasheets, manuals)
|
|
-- ═══════════════════════════════════════════════════════
|
|
CREATE TABLE IF NOT EXISTS product_documents (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
switch_id UUID REFERENCES switches(id) ON DELETE CASCADE,
|
|
transceiver_id UUID REFERENCES transceivers(id) ON DELETE CASCADE,
|
|
vendor_id UUID REFERENCES vendors(id) ON DELETE SET NULL,
|
|
doc_type TEXT NOT NULL CHECK (doc_type IN ('datasheet', 'manual', 'quick_start', 'cli_reference', 'release_notes', 'installation_guide', 'compatibility_matrix', 'eol_notice')),
|
|
title TEXT NOT NULL,
|
|
source_url TEXT NOT NULL,
|
|
local_path TEXT,
|
|
r2_key TEXT,
|
|
file_size_bytes BIGINT,
|
|
content_hash TEXT,
|
|
page_count INTEGER,
|
|
language TEXT DEFAULT 'en',
|
|
extracted_text TEXT,
|
|
indexed_at TIMESTAMPTZ,
|
|
downloaded_at TIMESTAMPTZ DEFAULT NOW(),
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
CONSTRAINT chk_doc_ref CHECK (switch_id IS NOT NULL OR transceiver_id IS NOT NULL)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_product_docs_switch ON product_documents(switch_id) WHERE switch_id IS NOT NULL;
|
|
CREATE INDEX IF NOT EXISTS idx_product_docs_transceiver ON product_documents(transceiver_id) WHERE transceiver_id IS NOT NULL;
|
|
CREATE INDEX IF NOT EXISTS idx_product_docs_type ON product_documents(doc_type);
|
|
CREATE INDEX IF NOT EXISTS idx_product_docs_vendor ON product_documents(vendor_id);
|
|
CREATE INDEX IF NOT EXISTS idx_product_docs_hash ON product_documents(content_hash);
|