Rhys SullivanAdd scoped MCP toolkits0a7c6a84 months agoHistory
152 lines · 5.2 KB · TypeScript
RawDownload
import { createRootRoute, Outlet, useRouterState } from "@tanstack/react-router";import { useEffect, useState, type ReactNode } from "react"; import { ExecutorProvider } from "@executor-js/react/api/provider";import { ExecutorPluginsProvider } from "@executor-js/sdk/client";import { OrganizationProvider } from "@executor-js/react/api/organization-context";import { OrgSlugGate } from "@executor-js/react/multiplayer/org-slug-gate";import { Toaster } from "@executor-js/react/components/sonner";import { AuthProvider, useAuth } from "@executor-js/react/multiplayer/auth-context";import { Shell, defaultShellNavItems } from "@executor-js/react/multiplayer/shell";import { plugins as clientPlugins } from "virtual:executor/plugins-client"; import { authClient } from "../auth-client";import { DevicePage } from "../chromeless/device-page";import { McpConsentPage } from "../chromeless/mcp-consent-page";import { LoginPage } from "../login";import { SetupPage } from "../setup";import { fetchNeedsSetup } from "../setup-status"; // ---------------------------------------------------------------------------// Self-host root: the SHARED multiplayer composition with Better Auth as the// provider. Same shell, pages, and account surface as cloud — the only// self-host specifics are the login form (email/password) and sign-out (Better// Auth), injected here. No billing, Sentry, or PostHog.// --------------------------------------------------------------------------- export const Route = createRootRoute({  component: RootComponent,}); // Self-host adds the account's API keys and the instance Admin page (members +// invite links) to the shared nav. The Admin page and its API gate to// owner/admin, so a non-admin who opens it just sees the access notice.const selfHostNavItems = [  ...defaultShellNavItems,  { to: "/api-keys", label: "API keys" },  { to: "/admin", label: "Admin" },]; const signOut = async () => {  await authClient.signOut();  window.location.href = "/";}; const Loading = () => (  <div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">    Loading…  </div>); function AuthGate({ children }: { children: ReactNode }) {  const auth = useAuth();  // When unauthenticated, decide between first-run setup and sign-in by asking  // the server whether the instance still has zero members. `null` = checking.  const [needsSetup, setNeedsSetup] = useState<boolean | null>(null);  useEffect(() => {    if (auth.status !== "unauthenticated") return;    let alive = true;    void fetchNeedsSetup().then((value) => {      if (alive) setNeedsSetup(value);    });    return () => {      alive = false;    };  }, [auth.status]);   if (auth.status === "loading") return <Loading />;  if (auth.status === "unauthenticated") {    if (needsSetup === null) return <Loading />;    return needsSetup ? <SetupPage /> : <LoginPage />;  }  return <>{children}</>;} function AuthenticatedApp() {  const auth = useAuth();  const organization = auth.status === "authenticated" ? (auth.organization ?? null) : null;   // Single-org instance: a bare URL canonicalizes onto the instance org's  // slug. There's only ever one org, so no other slug is reachable.  const gated = (    <>      <Shell onSignOut={signOut} navItems={selfHostNavItems} />      <Toaster />    </>  );   return (    <ExecutorProvider>      <ExecutorPluginsProvider plugins={clientPlugins}>        {/* No organizationSlug: the self-host MCP endpoint is the bare /mcp —            a slug-pinned URL would 404, and a single-org instance has nothing            to select anyway. */}        <OrganizationProvider organizationId={organization?.id ?? null}>          {organization ? <OrgSlugGate activeSlug={organization.slug}>{gated}</OrgSlugGate> : gated}        </OrganizationProvider>      </ExecutorPluginsProvider>    </ExecutorProvider>  );} function RootComponent() {  const pathname = useRouterState({ select: (s) => s.location.pathname });   // The join page is public + chromeless: a new user redeeming an invite link  // has no session yet, so it renders outside the auth gate and the shell.  if (pathname.startsWith("/join/")) {    return (      <>        <Outlet />        <Toaster />      </>    );  }   // The MCP OAuth approval screen: chromeless (no shell) but inside the auth  // gate — the user is already signed in (Better Auth's authorize requires a  // session before redirecting here). Rendered directly (static import), not as  // a lazy route, so it can't hit Vite's dynamic-import dep flake.  if (pathname === "/mcp-consent") {    return (      <AuthProvider>        <AuthGate>          <McpConsentPage />          <Toaster />        </AuthGate>      </AuthProvider>    );  }   // The CLI device-login verification page: chromeless, inside the auth gate  // (the user signs in here if needed, then authorizes the code). Same  // static-import + pathname-branch convention as /mcp-consent.  if (pathname === "/device") {    return (      <AuthProvider>        <AuthGate>          <DevicePage />          <Toaster />        </AuthGate>      </AuthProvider>    );  }   return (    <AuthProvider>      <AuthGate>        <AuthenticatedApp />      </AuthGate>    </AuthProvider>  );}