PageSourceSearch

https://ee.show/assets/js/MCPConnections.tsx-DjJXLErl.js

js ee.show collected 2026-10-02 15:25:47 UTC 17,552 bytes, 1 lines download raw bytes

1import{o as e}from"./chunk-C_JJxWoe.js";import{Bt as s,Ht as a,Mr as t,Rr as n,Rt as r,Ut as l,Wt as i,Yn as c,zt as o}from"../index-DkGUPYoQ.js";import{n as d}from"./chunk-BM0pDCyk2.js";import{a as x,i as m,n as h,o as u,r as j,t as p}from"./chunk-Dwh9rESY2.js";import{t as v}from"./chunk-BQ3lwMr52.js";import{t as g}from"./chunk-D1FDdKOe.js";import{t as f}from"./chunk-CJ1Dl5N5.js";import{t as N}from"./chunk-HpbWOqlt.js";import{t as b}from"./chunk-DwB2fjsg.js";import{i as k,n as y,r as _,t as C}from"./chunk-647lud5-.js";var w=e(n(),1),S=t(),O={low:"bg-emerald-500/10 text-emerald-600 border-emerald-500/30",medium:"bg-amber-500/10 text-amber-600 border-amber-500/30",high:"bg-orange-500/10 text-orange-600 border-orange-500/30",perimeter:"bg-red-500/10 text-red-600 border-red-500/30"},z={allowed:"text-emerald-600",refused:"text-red-600",rate_limited:"text-amber-600",perimeter_block:"text-red-700 font-semibold",revoked:"text-muted-foreground",error:"text-orange-600"},A="ppdlqxsqcftkadidhiuv",T=`https://${A}.supabase.co/functions/v1/mcp-backstage/mcp`,R=`https://${A}.supabase.co/functions/v1/mcp-backstage`;function E(){const[e,t]=(0,w.useState)([]),[n,x]=(0,w.useState)(null),[m,h]=(0,w.useState)([]),[u,j]=(0,w.useState)([]),[p,g]=(0,w.useState)(!0),[f,N]=(0,w.useState)([]),[A,E]=(0,w.useState)(!1),[I,L]=(0,w.useState)(null),M=async()=>{g(!0);const{data:e}=await d.from("mcp_connections").select("*").order("created_at",{ascending:!1});t(e??[]),e&&e.length&&!n&&x(e[0].id),g(!1)},B=async e=>{const[{data:s},{data:a}]=await Promise.all([d.from("mcp_tool_grants").select("*").eq("connection_id",e).order("tool_name"),d.from("mcp_connection_audit").select("id, tool_name, verdict, error, duration_ms, created_at").eq("connection_id",e).order("created_at",{ascending:!1}).limit(50)]);h(s??[]),j(a??[])};(0,w.useEffect)(()=>{M(),(async()=>{const{data:{session:e}}=await d.auth.getSession();if(!e)return;const s=await fetch(`${R}/admin/tools`,{headers:{Authorization:`Bearer ${e.access_token}`}});if(s.ok){const e=await s.json();N(e.tools??[])}})()},[]),(0,w.useEffect)(()=>{n&&B(n)},[n]);const U=u.filter(e=>"allowed"!==e.verdict).length;return(0,S.jsxs)("div",{className:"p-6 space-y-6 max-w-7xl mx-auto",children:[(0,S.jsxs)("div",{className:"flex items-start justify-between gap-4",children:[(0,S.jsxs)("div",{children:[(0,S.jsx)("h1",{className:"text-2xl font-bold",children:"MCP Backstage — Constitution of Attention"}),(0,S.jsxs)("p",{className:"text-muted-foreground mt-1 text-sm max-w-3xl",children:["Remote MCP server hosted on Supabase Edge. Mint auth keys with scoped tool grants, hand them to Claude/Codex/Cline, and every call leaves a hash-chained receipt. This is a ",(0,S.jsx)("strong",{children:"transport surface"}),", not an authority surface — forbidden perimeter tools cannot be enabled here."]})]}),(0,S.jsx)(i,{onClick:()=>E(!0),children:"Issue new key"})]}),(0,S.jsxs)(C,{defaultValue:"connections",children:[(0,S.jsxs)(_,{children:[(0,S.jsx)(k,{value:"connections",children:"Connections"}),(0,S.jsx)(k,{value:"install",children:"Install & Connect"}),(0,S.jsxs)(k,{value:"catalog",children:["Tool catalog (",f.length,")"]})]}),(0,S.jsx)(y,{value:"connections",className:"mt-6",children:(0,S.jsxs)("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-6",children:[(0,S.jsxs)(r,{className:"lg:col-span-1",children:[(0,S.jsx)(a,{children:(0,S.jsx)(l,{className:"text-base",children:"Connections"})}),(0,S.jsxs)(o,{className:"space-y-2",children:[p&&(0,S.jsx)("p",{className:"text-sm text-muted-foreground",children:"Loading…"}),!p&&0===e.length&&(0,S.jsxs)("p",{className:"text-sm text-muted-foreground",children:["No connections yet. Click ",(0,S.jsx)("em",{children:"Issue new key"}),"."]}),e.map(e=>(0,S.jsxs)("button",{onClick:()=>x(e.id),className:"w-full text-left p-3 rounded-md border transition "+(n===e.id?"border-primary bg-primary/5":"border-border hover:bg-muted/30"),children:[(0,S.jsxs)("div",{className:"flex items-center justify-between",children:[(0,S.jsx)("span",{className:"font-medium text-sm",children:e.client_name}),(0,S.jsx)(v,{variant:"active"===e.status?"default":"secondary",children:e.status})]}),(0,S.jsxs)("div",{className:"text-xs text-muted-foreground mt-1",children:["last seen ",e.last_seen_at?new Date(e.last_seen_at).toLocaleStr
1ing():"never"]})]},e.id))]})]}),(0,S.jsx)("div",{className:"lg:col-span-2 space-y-6",children:n&&(0,S.jsxs)(S.Fragment,{children:[(0,S.jsxs)(r,{children:[(0,S.jsxs)(a,{className:"flex flex-row items-center justify-between",children:[(0,S.jsxs)("div",{children:[(0,S.jsxs)(l,{className:"text-base",children:["Tool grants (",m.length,")"]}),(0,S.jsx)(s,{children:"Per-tool toggles. Forbidden tools are blocked at the perimeter — they cannot be enabled from here."})]}),(0,S.jsx)(i,{variant:"destructive",size:"sm",onClick:()=>{const s=e.find(e=>e.id===n);s&&(async e=>{if(!confirm(`Revoke connection "${e.client_name}"? Active sessions will be terminated. Receipt will be written.`))return;const{error:s}=await d.from("mcp_connections").update({status:"revoked",revoked_at:(new Date).toISOString(),revoke_reason:"admin_ui"}).eq("id",e.id);s?c.error(s.message):(c.success("Revoked"),M())})(s)},children:"Revoke connection"})]}),(0,S.jsx)(o,{children:(0,S.jsx)("div",{className:"space-y-1 max-h-96 overflow-y-auto",children:m.map(e=>(0,S.jsxs)("div",{className:"flex items-center justify-between p-2 rounded hover:bg-muted/30",children:[(0,S.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,S.jsxs)("div",{className:"flex items-center gap-2",children:[(0,S.jsx)("code",{className:"text-xs",children:e.tool_name}),(0,S.jsx)(v,{variant:"outline",className:O[e.risk_band]??"",children:e.risk_band}),e.require_human_review&&(0,S.jsx)(v,{variant:"outline",children:"HV"})]}),(0,S.jsxs)("div",{className:"text-xs text-muted-foreground",children:[e.max_calls_per_hour,"/h"]})]}),(0,S.jsx)(b,{checked:e.allowed,onCheckedChange:s=>(async(e,s)=>{const{error:a}=await d.from("mcp_tool_grants").update({allowed:s}).eq("id",e.id);a?c.error(a.message):(c.success(`${e.tool_name}: ${s?"enabled":"disabled"}`),n&&B(n))})(e,s)})]},e.id))})})]}),(0,S.jsxs)(r,{children:[(0,S.jsxs)(a,{children:[(0,S.jsxs)(l,{className:"text-base",children:["Audit tail",(0,S.jsxs)("span",{className:"ml-2 text-sm text-muted-foreground font-normal",children:["(",u.length," recent · ",U," non-allowed)"]})]}),(0,S.jsx)(s,{children:"Append-only, hash-chained. Refusals survive — the hinge, not the slammed door."})]}),(0,S.jsx)(o,{children:(0,S.jsxs)("div",{className:"space-y-1 max-h-96 overflow-y-auto text-xs font-mono",children:[0===u.length&&(0,S.jsx)("p",{className:"text-muted-foreground font-sans",children:"No calls yet. Zero here means absence of traffic, not health."}),u.map(e=>(0,S.jsxs)("div",{className:"grid grid-cols-12 gap-2 py-1 border-b border-border/30",children:[(0,S.jsx)("span",{className:"col-span-3 text-muted-foreground",children:new Date(e.created_at).toLocaleTimeString()}),(0,S.jsx)("span",{className:"col-span-5 truncate",children:e.tool_name}),(0,S.jsx)("span",{className:`col-span-2 ${z[e.verdict]??""}`,children:e.verdict}),(0,S.jsxs)("span",{className:"col-span-2 text-right text-muted-foreground",children:[e.duration_ms??"—","ms"]}),e.error&&(0,S.jsxs)("span",{className:"col-span-12 text-red-600 pl-3 truncate",children:["↳ ",e.error]})]},e.id))]})})]})]})})]})}),(0,S.jsx)(y,{value:"install",className:"mt-6 space-y-6",children:(0,S.jsx)(q,{mcpUrl:T})}),(0,S.jsx)(y,{value:"catalog",className:"mt-6",children:(0,S.jsxs)(r,{children:[(0,S.jsxs)(a,{children:[(0,S.jsx)(l,{className:"text-base",children:"Grantable tools"}),(0,S.jsx)(s,{children:"These are the tools an issued key can be scoped to. Perimeter-forbidden tools are excluded."})]}),(0,S.jsx)(o,{children:(0,S.jsx)("div",{className:"space-y-2 max-h-[600px] overflow-y-auto",children:f.map(e=>(0,S.jsxs)("div",{className:"p-3 rounded border border-border",children:[(0,S.jsxs)("div",{className:"flex items-center gap-2 flex-wrap",children:[(0,S.jsx)("code",{className:"text-xs font-semibold",children:e.name}),(0,S.jsx)(v,{variant:"outline",className:O[e.risk_level]??"",children:e.risk_level}),(0,S.jsx)(v,{variant:"outline",children:e.kind}),!e.reversible&&(0,S.jsx)(v,{variant:"outline",className:"border-orange-500/40 text-orange-600",children:"irreversible"}),(0,S.jsx)(v,{variant:"outline",children:e.blast_radius})]}),(0,S.jsx)("p",{className:"text-xs text-muted-foreground mt-1",children:e.description})]},e.name))})})]})})]}),(0,S.jsx)($,{open:A,onOpenChange:E,catalog:f,onIssued:e=>{L(e),E(!1),M()}}),(0,S.jsx)(P,{issued:I,onClose:()=>L(null),mcpUrl:T})]})}function $({open:e,onOpenChange:s,catalog:a,onIssued:t}){const[n,r]=(0,w.useState)(""),[l,o]=(0,w.useState)(90),[f,k]=(0,w.useState)(60),[y,_]=(0,w.useState)(!0),[C,z]=(0,w.useState)({}),[A,T]=(0,w.useState)(!1);(0,w.useEffect)(()=>
1{if(e){const e={};a.forEach(s=>{e[s.name]="high"!==s.risk_level}),z(e)}},[e,a]);const E=(0,w.useMemo)(()=>Object.entries(C).filter(([,e])=>e).map(([e])=>e),[C]);return(0,S.jsx)(p,{open:e,onOpenChange:s,children:(0,S.jsxs)(h,{className:"max-w-2xl",children:[(0,S.jsxs)(x,{children:[(0,S.jsx)(u,{children:"Issue MCP access key"}),(0,S.jsx)(j,{children:"Mints a long-lived personal access token bound to a new connection with the tools you select. The token is shown once."})]}),(0,S.jsxs)("div",{className:"space-y-4",children:[(0,S.jsxs)("div",{className:"grid grid-cols-3 gap-3",children:[(0,S.jsxs)("div",{className:"col-span-3",children:[(0,S.jsx)(N,{children:"Label"}),(0,S.jsx)(g,{value:n,onChange:e=>r(e.target.value),placeholder:"claude-desktop-laptop"})]}),(0,S.jsxs)("div",{children:[(0,S.jsx)(N,{children:"Expires (days)"}),(0,S.jsx)(g,{type:"number",min:1,max:365,value:l,onChange:e=>o(Number(e.target.value))})]}),(0,S.jsxs)("div",{children:[(0,S.jsx)(N,{children:"Rate limit / hour"}),(0,S.jsx)(g,{type:"number",min:1,max:1e4,value:f,onChange:e=>k(Number(e.target.value))})]}),(0,S.jsxs)("div",{className:"flex items-end gap-2",children:[(0,S.jsx)(b,{checked:y,onCheckedChange:_,id:"hv"}),(0,S.jsx)(N,{htmlFor:"hv",className:"text-xs",children:"Require HV on high-risk"})]})]}),(0,S.jsxs)("div",{children:[(0,S.jsxs)("div",{className:"flex items-center justify-between mb-2",children:[(0,S.jsxs)(N,{children:["Tools (",E.length," of ",a.length,")"]}),(0,S.jsxs)("div",{className:"flex gap-2",children:[(0,S.jsx)(i,{size:"sm",variant:"outline",onClick:()=>{const e={};a.forEach(s=>e[s.name]=!0),z(e)},children:"All"}),(0,S.jsx)(i,{size:"sm",variant:"outline",onClick:()=>{const e={};a.forEach(s=>e[s.name]="low"===s.risk_level),z(e)},children:"Low-risk only"}),(0,S.jsx)(i,{size:"sm",variant:"outline",onClick:()=>z({}),children:"None"})]})]}),(0,S.jsx)("div",{className:"max-h-72 overflow-y-auto space-y-1 border rounded p-2",children:a.map(e=>(0,S.jsxs)("label",{className:"flex items-start gap-2 p-1 hover:bg-muted/30 rounded cursor-pointer",children:[(0,S.jsx)("input",{type:"checkbox",className:"mt-1",checked:!!C[e.name],onChange:s=>z(a=>({...a,[e.name]:s.target.checked}))}),(0,S.jsxs)("div",{className:"min-w-0",children:[(0,S.jsxs)("div",{className:"flex items-center gap-2",children:[(0,S.jsx)("code",{className:"text-xs",children:e.name}),(0,S.jsx)(v,{variant:"outline",className:O[e.risk_level]??"",children:e.risk_level})]}),(0,S.jsx)("p",{className:"text-xs text-muted-foreground truncate",children:e.description})]})]},e.name))})]})]}),(0,S.jsxs)(m,{children:[(0,S.jsx)(i,{variant:"outline",onClick:()=>s(!1),children:"Cancel"}),(0,S.jsx)(i,{onClick:async()=>{if(n.trim())if(0!==E.length){T(!0);try{const{data:{session:e}}=await d.auth.getSession();if(!e)throw new Error("Not signed in");const s=await fetch(`${R}/admin/keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e.access_token}`},body:JSON.stringify({label:n.trim(),tools:E,expires_in_days:l,max_calls_per_hour:f,require_human_review_for_high:y})}),a=await s.json();if(!s.ok)throw new Error(a.error??"Issue failed");t(a),r("")}catch(e){c.error(e.message)}finally{T(!1)}}else c.error("Select at least one tool");else c.error("Label required")},disabled:A,children:A?"Issuing…":"Mint key"})]})]})})}function P({issued:e,onClose:s,mcpUrl:a}){if(!e)return null;const t=JSON.stringify({mcpServers:{"ee-backstage":{type:"http",url:a,headers:{Authorization:`Bearer ${e.access_token}`}}}},null,2),n=e=>{navigator.clipboard.writeText(e),c.success("Copied")};return(0,S.jsx)(p,{open:!0,onOpenChange:e=>!e&&s(),children:(0,S.jsxs)(h,{className:"max-w-2xl",children:[(0,S.jsxs)(x,{children:[(0,S.jsx)(u,{children:"Key issued — copy now, this is shown once"}),(0,S.jsxs)(j,{children:["Label ",(0,S.jsx)("strong",{children:e.label})," · expires ",new Date(e.expires_at).toLocaleString()," · ",e.tools_granted.length," tools granted"]})]}),(0,S.jsxs)("div",{className:"space-y-4",children:[(0,S.jsxs)("div",{children:[(0,S.jsx)(N,{children:"Access token"}),(0,S.jsxs)("div",{className:"flex gap-2 mt-1",children:[(0,S.jsx)(g,{readOnly:!0,value:e.access_token,className:"font-mono text-xs"}),(0,S.jsx)(i,{variant:"outline",onClick:()=>n(e.access_token),children:"Copy"})]})]}),(0,S.jsxs)("div",{children:[(0,S.jsx)(N,{children:"MCP server URL"}),(0,S.jsxs)("div",{className:"flex gap-2 mt-1",children:[(0,S.jsx)(g,{readOnly:!0,value:a,className:"font-mono text-xs"}),(0,S.jsx)(i,{variant:"outline",onClick:()=>n(a),children:"Copy"})]})]}),(0,S.jsxs)("div",{children:[(0,S.jsx)(N,{children:"Claude Desktop / Codex config snippet"}),(0,S.jsxs)("div",{className:"relative mt-1",children:[(0,S.jsx)(f,{readOnly:!0,value:t,className:"font-mono text-xs h-40"}),(0,S.jsx)(i,{size:"sm",variant:"outline",className:"absolute top-2 right-2",onClick:()=>n(t),children:"Copy"})]})]})]}),(0,S.jsx)(m,{children:(0,S.jsx)(i,{onClick:s,children:"I saved it"})})]})})}function q({mcpUrl:e}){const t=e=>{navigator.clipboard.writeText(e),c.success("Copied")},n=JSON.stringify({mcpServers:{"ee-backstage":{type:"http",url:e,headers:{Authorization:"Bearer <YOUR_KEY>"}}}},null,2),d=`# ~/.codex/config.toml\n[mcp_servers.ee-backstage]\ntransport = "http"\nurl = "${e}"\nheaders = { Authorization = "Bearer <YOUR_KEY>" }`,x=`# .cline/mcp.json\n${n}`,m=`curl -sS -X POST '${e}' \\\n  -H 'Authorization: Bearer <YOUR_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'`;return(0,S.jsxs)(S.Fragment,{children:[(0,S.jsxs)(r,{children:[(0,S.jsxs)(a,{children:[(0,S.jsx)(l,{className:"text-base",children:"Endpoint"}),(0,S.jsx)(s,{children:"Streamable HTTP MCP. Bearer auth via issued key."})]}),(0,S.jsxs)(o,{className:"space-y-2 text-sm",children:[(0,S.jsxs)("div",{className:"flex gap-2 items-center",children:[(0,S.jsx)("span",{className:"text-muted-foreground w-24",children:"URL"}),(0,S.jsx)("code",{className:"text-xs bg-muted px-2 py-1 rounded flex-1 truncate",children:e}),(0,S.jsx)(i,{size:"sm",variant:"outline",onClick:()=>t(e),children:"Copy"})]}),(0,S.jsxs)("div",{className:"flex gap-2 items-center",children:[(0,S.jsx)("span",{className:"text-muted-foreground w-24",children:"Transport"}),(0,S.jsx)("code",{className:"text-xs",children:"HTTP (Streamable, spec 2024-11-05)"})]}),(0,S.jsxs)("div",{className:"flex gap-2 items-center",children:[(0,S.jsx)("span",{className:"text-muted-foreground w-24",children:"Auth header"}),(0,S.jsx)("code",{className:"text-xs",children:"Authorization: Bearer <token>"})]}),(0,S.jsxs)("div",{className:"flex gap-2 items-center",children:[(0,S.jsx)("span",{className:"text-muted-foreground w-24",children:"Required Accept"}),(0,S.jsx)("code",{className:"text-xs",children:"application/json, text/event-stream"})]})]})]}),(0,S.jsxs)(r,{children:[(0,S.jsxs)(a,{children:[(0,S.jsx)(l,{className:"text-base",children:"Claude Desktop / Claude Code"}),(0,S.jsxs)(s,{children:["Drop into ",(0,S.jsx)("code",{children:"~/Library/Application Support/Claude/claude_desktop_config.json"})," (macOS) or the equivalent on your platform, then restart Claude."]})]}),(0,S.jsx)(o,{children:(0,S.jsxs)("div",{className:"relative",children:[(0,S.jsx)(f,{readOnly:!0,value:n,className:"font-mono text-xs h-40"}),(0,S.jsx)(i,{size:"sm",variant:"outline",className:"absolute top-2 right-2",onClick:()=>t(n),children:"Copy"})]})})]}),(0,S.jsxs)(r,{children:[(0,S.jsx)(a,{children:(0,S.jsx)(l,{className:"text-base",children:"OpenAI Codex CLI"})}),(0,S.jsx)(o,{children:(0,S.jsxs)("div",{className:"relative",children:[(0,S.jsx)(f,{readOnly:!0,value:d,className:"font-mono text-xs h-32"}),(0,S.jsx)(i,{size:"sm",variant:"outline",className:"absolute top-2 right-2",onClick:()=>t(d),children:"Copy"})]})})]}),(0,S.jsxs)(r,{children:[(0,S.jsx)(a,{children:(0,S.jsx)(l,{className:"text-base",children:"Cline / other MCP-aware clients"})}),(0,S.jsx)(o,{children:(0,S.jsxs)("div",{className:"relative",children:[(0,S.jsx)(f,{readOnly:!0,value:x,className:"font-mono text-xs h-40"}),(0,S.jsx)(i,{size:"sm",variant:"outline",className:"absolute top-2 right-2",onClick:()=>t(x),children:"Copy"})]})})]}),(0,S.jsxs)(r,{children:[(0,S.jsxs)(a,{children:[(0,S.jsx)(l,{className:"text-base",children:"Sanity check via curl"}),(0,S.jsx)(s,{children:"Should return the granted tool list."})]}),(0,S.jsx)(o,{children:(0,S.jsxs)("div",{className:"relative",children:[(0,S.jsx)(f,{readOnly:!0,value:m,className:"font-mono text-xs h-32"}),(0,S.jsx)(i,{size:"sm",variant:"outline",className:"absolute top-2 right-2",onClick:()=>t(m),children:"Copy"})]})})]})]})}export{E as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.