Skip to main content
Glama
jmandel

Smart EHR MCP Server

by jmandel
portal.js4.49 kB
/* ------------------------------------------------------------------ Front‑end bridge for a SINGLE tool iframe. • default tool = /tool-sample/ • override via ?tool=https://other.example.dev • same ?token=… param still used for WebSocket auth -------------------------------------------------------------------*/ const p = new URLSearchParams(location.search); let config = p.get("config") || ""; // mutable – can be changed via form const urlArg = p.get("tool"); // optional override const DEFAULT_TOOL = "/tool-sample/"; // No mandatory param. When ?config is absent we default to "global" on the server. /* DOM helpers */ const urlInput = document.getElementById("toolUrl"); const configInput = document.getElementById("configVal"); const loadBtn = document.getElementById("loadBtn"); const host = document.getElementById("iframeHost"); const logEl = document.getElementById("log"); const loaderUI = document.getElementById("loader"); function log(m){ logEl.append(m+"\n"); logEl.scrollTo(0, 9e9); } let ws = null; function openWebSocket(){ if (ws && ws.readyState === WebSocket.OPEN){ ws.close(4000, "reopening with new config"); } const wsURL = new URL("/ws", location.origin); if (config) wsURL.searchParams.set("config", config); ws = new WebSocket(wsURL); ws.onopen = () => log("WS connected"); ws.onerror = err => log("WS error "+err); ws.onclose = () => log("WS closed"); ws.onmessage = ev => { const iframe = host.querySelector("iframe"); if (iframe) { if (isToolServerReady) { // Tool ready - send immediately iframe.contentWindow.postMessage(ev.data, "*"); } else { // Tool not ready - queue for later delivery toolReadyQueue.push(ev.data); log(`Queued message from WS (tool not ready yet). Queue size: ${toolReadyQueue.length}`); } } else { log("iframe not yet loaded – message dropped"); } }; } // initial WS openWebSocket(); // Queue of messages to be delivered when tool's MCP server is ready let toolReadyQueue = []; let isToolServerReady = false; /* iframe → WS relay */ window.addEventListener("message", ev => { try { // Messages FROM iframe TO server/proxy if (typeof ev.data === 'string') { const msg = JSON.parse(ev.data); // Handle special server_ready notification from intralib.js if (msg.method === 'server_ready') { log("Tool MCP server ready - can now deliver queued messages"); isToolServerReady = true; // Flush any queued messages to the now-ready iframe if (toolReadyQueue.length > 0) { const iframe = host.querySelector('iframe'); if (iframe) { log(`Flushing ${toolReadyQueue.length} queued messages to tool`); toolReadyQueue.forEach(m => iframe.contentWindow.postMessage(m, '*')); toolReadyQueue = []; } } return; } } // Forward all other messages to WebSocket if (ws && ws.readyState === WebSocket.OPEN) ws.send(ev.data); } catch(e) { log(`Error processing message: ${e.message}`); } }); /* Create / replace iframe */ function makeIframe(src){ // Reset ready state and queue when loading a new iframe isToolServerReady = false; toolReadyQueue = []; host.innerHTML = ""; const fr = document.createElement("iframe"); let iframeSrc = src; if (config){ try{ const urlObj = new URL(src, location.origin); urlObj.searchParams.set("config", config); iframeSrc = urlObj.pathname + urlObj.search + urlObj.hash; }catch{ iframeSrc = src + (src.includes("?") ? "&" : "?") + "config="+encodeURIComponent(config); } } fr.src = iframeSrc; host.append(fr); log("iframe loaded: "+iframeSrc); } /* Button / manual entry */ loadBtn.onclick = () => { const u = urlInput.value.trim(); // Update config from form (overrides URL param) const newConfig = (configInput.value || "").trim(); if (newConfig !== config){ config = newConfig; openWebSocket(); } if (u) makeIframe(u); }; /* Init: set default or auto‑load */ if (configInput) configInput.value = config; // pre-fill if (urlArg){ loaderUI.style.display = "none"; // hide form entirely makeIframe(urlArg); } else { urlInput.value = DEFAULT_TOOL; makeIframe(DEFAULT_TOOL); // Auto-load the default tool }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jmandel/health-record-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server