Skip to main content
Glama

Convex MCP server

Official
by get-convex
secretSystemTables.ts6.01 kB
import { GenericDataModel, GenericDatabaseReader, SystemDataModel, DefaultFunctionArgs, TableNamesInDataModel, currentSystemUdfInComponent, } from "convex/server"; import { GenericValidator } from "convex/values"; import { query as baseQuery, queryGeneric as baseQueryGeneric } from "./server"; import { Id } from "../_generated/dataModel"; // This set must be kept up-to-date to prevent accidental access to secret // system tables in system UDFs. const VIRTUAL_TABLES: Set<TableNamesInDataModel<SystemDataModel>> = new Set([ "_storage", "_scheduled_functions", ]); function isValidVirtualTable(table: string) { return ( !table.startsWith("_") || VIRTUAL_TABLES.has(table as TableNamesInDataModel<SystemDataModel>) ); } const GUARANTEED_NONEXISTENT_TABLE = "_guaranteed_nonexistent_table_2508b1e2"; /** * System tables can only be queried with `db.system`, but `db.system` uses the public types of virtual tables, * the way we intend to expose system tables to developers. * In order to use system tables types (which we manually keep updated in dashboard/convex/schema.ts) * which are not exposed in `convex/server`, use normal data model types with the db.system at runtime. */ // db.system but filtered to private (non-virtual) system tables. function maskPrivateSystem<T extends GenericDataModel>( db: GenericDatabaseReader<T>, ): GenericDatabaseReader<T> { return { query(tableName: string) { if (isValidVirtualTable(tableName)) { return db.system.query(GUARANTEED_NONEXISTENT_TABLE as any); } return db.system.query(tableName as any); }, async get(id: Id<any>) { for (const validTable of VIRTUAL_TABLES) { if (db.system.normalizeId(validTable, id)) { return null; } } return db.system.get(id); }, normalizeId(tableName: string, id: Id<any>) { if (isValidVirtualTable(tableName)) { return null; } return db.system.normalizeId(tableName as any, id); }, } as typeof db; } // db.system but filtered to public (virtual) system tables. function maskPublicSystem<T extends GenericDataModel>( db: GenericDatabaseReader<T>, ): GenericDatabaseReader<T>["system"] { return { query(tableName: string) { if (!isValidVirtualTable(tableName)) { return db.system.query(GUARANTEED_NONEXISTENT_TABLE as any); } return db.system.query(tableName as any); }, async get(id: Id<TableNamesInDataModel<SystemDataModel>>) { for (const validTable of VIRTUAL_TABLES) { if (db.system.normalizeId(validTable, id)) { return db.system.get(id); } } return null; }, normalizeId( tableName: TableNamesInDataModel<SystemDataModel>, id: Id<TableNamesInDataModel<SystemDataModel>>, ) { if (!isValidVirtualTable(tableName)) { return null; } return db.system.normalizeId(tableName, id); }, } as GenericDatabaseReader<T>["system"]; } type FunctionDefinition = { args: Record<string, GenericValidator>; returns: GenericValidator; handler: (ctx: any, args: DefaultFunctionArgs) => any; }; const queryWithComponent = ((functionDefinition: FunctionDefinition) => { return baseQuery({ args: functionDefinition.args, returns: functionDefinition.returns, handler: async (ctx: any, args: any) => { if ( "componentId" in args && args.componentId !== null && args.componentId !== undefined ) { const ref = currentSystemUdfInComponent(args.componentId); return await ctx.runQuery(ref, { ...args, componentId: null }); } return functionDefinition.handler(ctx, args); }, }); }) as typeof baseQuery; /// `queryPrivateSystem` is for querying private system tables. /// Access private system tables with `db.get/db.query`, not `db.system`, /// although db.system is used under the hood. /// In a `queryPrivateSystem` there is no access to user tables or public system /// tables. For those, use `queryGeneric` instead. export const queryPrivateSystem = ((functionDefinition: FunctionDefinition) => { if (!("args" in functionDefinition)) { throw new Error("args validator required for system udf"); } return queryWithComponent({ args: functionDefinition.args, returns: functionDefinition.returns, handler: (ctx: any, args: any) => { return functionDefinition.handler( { ...ctx, db: maskPrivateSystem(ctx.db) }, args, ); }, }); }) as typeof baseQuery; const queryGenericWithComponent = ((functionDefinition: FunctionDefinition) => { return baseQueryGeneric({ args: functionDefinition.args, returns: functionDefinition.returns, handler: async (ctx: any, args: any) => { if ( "componentId" in args && args.componentId !== null && args.componentId !== undefined ) { const ref = currentSystemUdfInComponent(args.componentId); return await ctx.runQuery(ref, { ...args, componentId: null }); } return functionDefinition.handler(ctx, args); }, }); }) as typeof baseQueryGeneric; /// `queryGeneric` is a query that the developer could write themselves. /// It does not access private system tables, so `db.get` and `db.system.get` /// only operate on user tables and public system tables. export const queryGeneric = ((functionDefinition: FunctionDefinition) => { if (!("args" in functionDefinition)) { throw new Error("args validator required for system udf"); } return queryGenericWithComponent({ args: functionDefinition.args, returns: functionDefinition.returns, handler: (ctx: any, args: any) => { return functionDefinition.handler( { ...ctx, db: { ...ctx.db, system: maskPublicSystem(ctx.db), privateSystem: maskPrivateSystem(ctx.db), }, }, args, ); }, }); }) as typeof baseQueryGeneric;

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