Skip to main content
Glama

Convex MCP server

Official
by get-convex
filePaths.ts5.68 kB
/* ~/.cache/convex binaries 0.0.1 convex-local-backend[.exe] // convex-local-backend.exe on windows 0.0.2 convex-local-backend[.exe] dashboard config.json out // if present, output files from building the self-hosted dashboard which can // be served using `npx serve` index.html ~/.convex convex-backend-state local-my_team-chess config.json // contains `LocalDeploymentConfig` convex_local_storage convex_local_backend.sqlite3 local-my_team-whisper config.json convex_local_storage convex_local_backend.sqlite3 anonymous-convex-backend-state config.json // contains { uuid: <uuid> }, used to identify the anonymous user anonymous-chess config.json convex_local_storage convex_local_backend.sqlite3 */ import path from "path"; import { cacheDir, rootDirectory } from "../utils/utils.js"; import { Context } from "../../../bundler/context.js"; import { logVerbose } from "../../../bundler/log.js"; import { recursivelyDelete } from "../fsUtils.js"; import crypto from "crypto"; // Naming is hard, but "local" refers to deployments linked to a Convex project // and "anonymous" refers to deployments that are not linked to a Convex project // (but in both cases they are running locally). export type LocalDeploymentKind = "local" | "anonymous"; export function rootDeploymentStateDir(kind: LocalDeploymentKind) { return path.join( rootDirectory(), kind === "local" ? "convex-backend-state" : "anonymous-convex-backend-state", ); } export function deploymentStateDir( deploymentKind: LocalDeploymentKind, deploymentName: string, ) { return path.join(rootDeploymentStateDir(deploymentKind), deploymentName); } export type LocalDeploymentConfig = { ports: { cloud: number; site: number; }; backendVersion: string; adminKey: string; // If not present, use the default instance secret for local backends instanceSecret?: string; }; export function loadDeploymentConfig( ctx: Context, deploymentKind: LocalDeploymentKind, deploymentName: string, ): LocalDeploymentConfig | null { const dir = deploymentStateDir(deploymentKind, deploymentName); const configFile = path.join(dir, "config.json"); if (!ctx.fs.exists(dir) || !ctx.fs.stat(dir).isDirectory()) { logVerbose(`Deployment ${deploymentName} not found`); return null; } if (ctx.fs.exists(configFile)) { const content = ctx.fs.readUtf8File(configFile); try { return JSON.parse(content); } catch (e) { logVerbose(`Failed to parse local deployment config: ${e as any}`); return null; } } return null; } export function saveDeploymentConfig( ctx: Context, deploymentKind: LocalDeploymentKind, deploymentName: string, config: LocalDeploymentConfig, ) { const dir = deploymentStateDir(deploymentKind, deploymentName); const configFile = path.join(dir, "config.json"); if (!ctx.fs.exists(dir)) { ctx.fs.mkdir(dir, { recursive: true }); } ctx.fs.writeUtf8File(configFile, JSON.stringify(config)); } export function binariesDir() { return path.join(cacheDir(), "binaries"); } export function dashboardZip() { return path.join(dashboardDir(), "dashboard.zip"); } export function versionedBinaryDir(version: string) { return path.join(binariesDir(), version); } export function executablePath(version: string) { return path.join(versionedBinaryDir(version), executableName()); } export function executableName() { const ext = process.platform === "win32" ? ".exe" : ""; return `convex-local-backend${ext}`; } export function dashboardDir() { return path.join(cacheDir(), "dashboard"); } export async function resetDashboardDir(ctx: Context) { const dir = dashboardDir(); if (ctx.fs.exists(dir)) { await recursivelyDelete(ctx, dir); } ctx.fs.mkdir(dir, { recursive: true }); } export function dashboardOutDir() { return path.join(dashboardDir(), "out"); } export type DashboardConfig = { port: number; apiPort: number; version: string; }; export function loadDashboardConfig(ctx: Context) { const configFile = path.join(dashboardDir(), "config.json"); if (!ctx.fs.exists(configFile)) { return null; } const content = ctx.fs.readUtf8File(configFile); try { return JSON.parse(content); } catch (e) { logVerbose(`Failed to parse dashboard config: ${e as any}`); return null; } } export function saveDashboardConfig(ctx: Context, config: DashboardConfig) { const configFile = path.join(dashboardDir(), "config.json"); if (!ctx.fs.exists(dashboardDir())) { ctx.fs.mkdir(dashboardDir(), { recursive: true }); } ctx.fs.writeUtf8File(configFile, JSON.stringify(config)); } export function loadUuidForAnonymousUser(ctx: Context) { const configFile = path.join( rootDeploymentStateDir("anonymous"), "config.json", ); if (!ctx.fs.exists(configFile)) { return null; } const content = ctx.fs.readUtf8File(configFile); try { const config = JSON.parse(content); return config.uuid ?? null; } catch (e) { logVerbose(`Failed to parse uuid for anonymous user: ${e as any}`); return null; } } export function ensureUuidForAnonymousUser(ctx: Context) { const uuid = loadUuidForAnonymousUser(ctx); if (uuid) { return uuid; } const newUuid = crypto.randomUUID(); const anonymousDir = rootDeploymentStateDir("anonymous"); if (!ctx.fs.exists(anonymousDir)) { ctx.fs.mkdir(anonymousDir, { recursive: true }); } ctx.fs.writeUtf8File( path.join(anonymousDir, "config.json"), JSON.stringify({ uuid: newUuid }), ); return newUuid; }

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