Skip to main content
Glama

Convex MCP server

Official
by get-convex
InviteMemberForm.tsx4.22 kB
import { Button } from "@ui/Button"; import { Tooltip } from "@ui/Tooltip"; import { Combobox } from "@ui/Combobox"; import { Sheet } from "@ui/Sheet"; import { TextInput } from "@ui/TextInput"; import { toast } from "@common/lib/utils"; import { useFormik } from "formik"; import { useCreateInvite } from "api/invitations"; import { Team, CreateInvitationArgs, TeamMemberResponse } from "generatedApi"; import * as Yup from "yup"; import Link from "next/link"; import { roleOptions } from "./TeamMemberListItem"; export type InviteMemberFormProps = { team: Team; members: TeamMemberResponse[]; hasAdminPermissions: boolean; }; export function InviteMemberForm({ team, members, hasAdminPermissions, }: InviteMemberFormProps) { const InviteSchema = Yup.object().shape({ inviteEmail: Yup.string() .email("Must be a valid email.") .notOneOf( members.map((member) => member.email) || [], "Email is already a member of this team.", ) .max(254, "Email must be at most 254 characters long."), role: Yup.string().oneOf(["developer", "admin"]), }); const createInvite = useCreateInvite(team.id); const formState = useFormik<{ inviteEmail: string; role: CreateInvitationArgs["role"]; }>({ initialValues: { // Define the form value as "inviteEmail" to avoid browser extensions thinking this is a login form. inviteEmail: "", role: "developer", }, validationSchema: InviteSchema, onSubmit: async (values) => { if (!hasAdminPermissions) { return; } const validation = await formState.validateForm(); if (Object.keys(validation).length) { toast("success", "Invalid email", "email"); return; } await createInvite({ email: values.inviteEmail, role: values.role, }); await formState.setFieldValue("inviteEmail", ""); }, }); return ( <Sheet className="min-w-fit text-sm"> <h3 className="mb-4">Invite Member</h3> <form onSubmit={formState.handleSubmit} aria-label="Invite team member"> <div className="mb-6 flex w-full grow flex-wrap gap-4 sm:flex-nowrap"> <Tooltip tip={ !hasAdminPermissions ? "You do not have permission to invite team members" : undefined } className="w-full" > <TextInput label="Email address" labelHidden placeholder="Email address" type="email" onChange={formState.handleChange} value={formState.values.inviteEmail} error={ formState.touched ? formState.errors.inviteEmail : undefined } onBlur={formState.handleBlur} id="inviteEmail" aria-label="Email address" disabled={!hasAdminPermissions} /> </Tooltip> {hasAdminPermissions && ( <Combobox buttonClasses="w-fit" disableSearch label="Role" buttonProps={{ tip: ( <span> Select a{" "} <Link href="https://docs.convex.dev/dashboard/teams#roles-and-permissions" className="underline" > team role </Link>{" "} for the new member. </span> ), tipSide: "top", }} options={roleOptions} selectedOption={formState.values.role} setSelectedOption={async (role) => { if (!role) { return; } await formState.setFieldValue("role", role); }} /> )} <Button disabled={ !formState.dirty || formState.isSubmitting || !formState.isValid } type="submit" aria-label="submit" > Send Invite </Button> </div> </form> </Sheet> ); }

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/get-convex/convex-backend'

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