@amplis/mcp-server 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +54 -41
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -3446,6 +3446,44 @@ import open from "open";
3446
3446
  var DEFAULT_API_URL2 = "https://app.amplis.com.au";
3447
3447
  var CALLBACK_PORT = 19284;
3448
3448
  var TIMEOUT_MS = 12e4;
3449
+ function renderPage(opts) {
3450
+ const iconSvg = opts.success ? `<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>` : `<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>`;
3451
+ const permissionBadges = opts.permissions ? `<div style="display:flex;gap:8px;justify-content:center;margin-top:16px">${opts.permissions.map((p) => `<span style="padding:4px 12px;border-radius:9999px;font-size:12px;font-weight:500;background:${p === "admin" ? "rgba(251,191,36,0.15)" : p === "write" ? "rgba(74,141,255,0.15)" : "rgba(52,211,153,0.15)"};color:${p === "admin" ? "#f59e0b" : p === "write" ? "#4A8DFF" : "#34d399"}">${p}</span>`).join("")}</div>` : "";
3452
+ const autoCloseScript = opts.autoClose ? `<p id="countdown" style="font-size:13px;color:#64748b;margin-top:20px">This window will close in <span id="secs">5</span>s</p>
3453
+ <script>
3454
+ let s=5;const el=document.getElementById('secs');
3455
+ setInterval(()=>{s--;if(el)el.textContent=String(s);if(s<=0)window.close();},1000);
3456
+ </script>` : "";
3457
+ return `<!DOCTYPE html>
3458
+ <html lang="en">
3459
+ <head>
3460
+ <meta charset="utf-8">
3461
+ <meta name="viewport" content="width=device-width, initial-scale=1">
3462
+ <title>AMPLIS - ${opts.title}</title>
3463
+ <style>
3464
+ *{margin:0;padding:0;box-sizing:border-box}
3465
+ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center;background:#0a0e1a}
3466
+ .card{background:#111827;border:1px solid rgba(255,255,255,0.08);border-radius:16px;padding:48px 40px;max-width:420px;width:100%;text-align:center;box-shadow:0 25px 50px rgba(0,0,0,0.4)}
3467
+ .icon{margin:0 auto 24px}
3468
+ h1{font-size:22px;font-weight:700;color:${opts.success ? "#22c55e" : "#ef4444"};margin-bottom:12px}
3469
+ .msg{font-size:15px;color:#cbd5e1;line-height:1.5}
3470
+ .msg strong{color:#f1f5f9}
3471
+ .hint{font-size:13px;color:#64748b;margin-top:20px}
3472
+ .brand{margin-top:32px;padding-top:20px;border-top:1px solid rgba(255,255,255,0.06);font-size:12px;color:#475569;letter-spacing:0.5px}
3473
+ </style>
3474
+ </head>
3475
+ <body>
3476
+ <div class="card">
3477
+ <div class="icon">${iconSvg}</div>
3478
+ <h1>${opts.title}</h1>
3479
+ <p class="msg">${opts.message}</p>
3480
+ ${permissionBadges}
3481
+ ${opts.success ? `<p class="hint">You can close this window and return to your terminal.</p>${autoCloseScript}` : '<p class="hint">Please close this window and try again.</p>'}
3482
+ <div class="brand">AMPLIS</div>
3483
+ </div>
3484
+ </body>
3485
+ </html>`;
3486
+ }
3449
3487
  async function browserLoginCommand() {
3450
3488
  console.log("\n \u{1F510} AMPLIS MCP Server \u2014 Browser Authentication\n");
3451
3489
  const apiUrl = process.env.AMPLIS_API_URL || DEFAULT_API_URL2;
@@ -3459,40 +3497,22 @@ async function browserLoginCommand() {
3459
3497
  const returnedState = url.searchParams.get("state");
3460
3498
  const error2 = url.searchParams.get("error");
3461
3499
  if (error2) {
3462
- res.writeHead(400, { "Content-Type": "text/html" });
3463
- res.end(`
3464
- <html><body style="font-family: system-ui; padding: 40px; text-align: center;">
3465
- <h1 style="color: #dc2626;">\u274C Authentication Failed</h1>
3466
- <p>${error2}</p>
3467
- <p>You can close this window.</p>
3468
- </body></html>
3469
- `);
3500
+ res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
3501
+ res.end(renderPage({ success: false, title: "Authentication Failed", message: error2 }));
3470
3502
  server.close();
3471
3503
  reject(new Error(error2));
3472
3504
  return;
3473
3505
  }
3474
3506
  if (returnedState !== state) {
3475
- res.writeHead(400, { "Content-Type": "text/html" });
3476
- res.end(`
3477
- <html><body style="font-family: system-ui; padding: 40px; text-align: center;">
3478
- <h1 style="color: #dc2626;">\u274C Invalid State</h1>
3479
- <p>Security validation failed. Please try again.</p>
3480
- <p>You can close this window.</p>
3481
- </body></html>
3482
- `);
3507
+ res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
3508
+ res.end(renderPage({ success: false, title: "Invalid State", message: "Security validation failed. Please try again." }));
3483
3509
  server.close();
3484
3510
  reject(new Error("Invalid state parameter"));
3485
3511
  return;
3486
3512
  }
3487
3513
  if (!code) {
3488
- res.writeHead(400, { "Content-Type": "text/html" });
3489
- res.end(`
3490
- <html><body style="font-family: system-ui; padding: 40px; text-align: center;">
3491
- <h1 style="color: #dc2626;">\u274C Missing Code</h1>
3492
- <p>No authorization code received.</p>
3493
- <p>You can close this window.</p>
3494
- </body></html>
3495
- `);
3514
+ res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
3515
+ res.end(renderPage({ success: false, title: "Missing Code", message: "No authorization code received." }));
3496
3516
  server.close();
3497
3517
  reject(new Error("Missing authorization code"));
3498
3518
  return;
@@ -3508,26 +3528,19 @@ async function browserLoginCommand() {
3508
3528
  throw new Error(errorBody.error || `HTTP ${exchangeResponse.status}`);
3509
3529
  }
3510
3530
  const result = await exchangeResponse.json();
3511
- res.writeHead(200, { "Content-Type": "text/html" });
3512
- res.end(`
3513
- <html><body style="font-family: system-ui; padding: 40px; text-align: center;">
3514
- <h1 style="color: #16a34a;">\u2705 Authentication Successful!</h1>
3515
- <p>Logged in to <strong>${result.orgName}</strong></p>
3516
- <p>You can close this window and return to your terminal.</p>
3517
- <script>setTimeout(() => window.close(), 3000);</script>
3518
- </body></html>
3519
- `);
3531
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
3532
+ res.end(renderPage({
3533
+ success: true,
3534
+ title: "Authentication Successful",
3535
+ message: `Logged in to <strong>${result.orgName}</strong>`,
3536
+ permissions: result.permissions,
3537
+ autoClose: true
3538
+ }));
3520
3539
  server.close();
3521
3540
  resolve(result);
3522
3541
  } catch (err) {
3523
- res.writeHead(500, { "Content-Type": "text/html" });
3524
- res.end(`
3525
- <html><body style="font-family: system-ui; padding: 40px; text-align: center;">
3526
- <h1 style="color: #dc2626;">\u274C Exchange Failed</h1>
3527
- <p>${err instanceof Error ? err.message : "Unknown error"}</p>
3528
- <p>You can close this window.</p>
3529
- </body></html>
3530
- `);
3542
+ res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
3543
+ res.end(renderPage({ success: false, title: "Exchange Failed", message: err instanceof Error ? err.message : "Unknown error" }));
3531
3544
  server.close();
3532
3545
  reject(err);
3533
3546
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amplis/mcp-server",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "MCP server for AMPLIS - connect Claude, Cursor, and other AI tools to your live consulting data",
5
5
  "author": "AMPLIS (https://amplis.com.au)",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "scripts": {
41
41
  "dev": "tsx watch src/index.ts",
42
42
  "build": "tsup src/index.ts --format esm --dts && chmod +x dist/index.js",
43
- "prepare": "npm run build",
43
+ "prepublishOnly": "npm run build",
44
44
  "start": "node dist/index.js",
45
45
  "typecheck": "tsc --noEmit",
46
46
  "test": "vitest run",