Skip to main content
Glama

Convex MCP server

Official
by get-convex
middlewareUtils.ts6.39 kB
import { ObjectType, PropertyValidators } from "convex/values"; import { ArgsArray, UnvalidatedFunction, ValidatedFunction, RegisteredQuery, RegisteredMutation, RegisteredAction, } from "convex/server"; import { ActionCtx, MutationCtx, QueryCtx, action, mutation, query, } from "../_generated/server"; export type MergeArgs< Args extends ArgsArray, Other extends { [k: string]: any }, > = Args extends [] ? [Other] : [Args[0] & Other]; export type MergeArgsForRegistered< Args extends ArgsArray, Other extends { [k: string]: any }, > = MergeArgs<Args, Other>[0]; export function splitArgs< ConsumedArgsValidator extends PropertyValidators, Args extends Record<string, any>, >( consumedArgsValidator: ConsumedArgsValidator, args: Args & ObjectType<ConsumedArgsValidator>, ): { rest: Args; consumed: ObjectType<ConsumedArgsValidator> } { const rest: Record<string, any> = {}; const consumed: Record<string, any> = {}; for (const arg in args) { if (arg in consumedArgsValidator) { consumed[arg] = args[arg]; } else { rest[arg] = args[arg]; } } return { rest, consumed, } as any; } export const generateMiddlewareContextOnly = < OriginalCtx extends Record<string, any>, TransformedCtx extends Record<string, any>, ConsumedArgsValidator extends PropertyValidators, >( consumedArgsValidator: ConsumedArgsValidator, transformContext: ( ctx: OriginalCtx, args: ObjectType<ConsumedArgsValidator>, ) => Promise<TransformedCtx>, ) => { function withFoo< ExistingArgsValidator extends PropertyValidators, Output, Ctx, >( fn: ValidatedFunction< Ctx & TransformedCtx, ExistingArgsValidator, Promise<Output> >, ): ValidatedFunction< Ctx & OriginalCtx, ConsumedArgsValidator & ExistingArgsValidator, Promise<Output> >; function withFoo<ExistingArgs extends ArgsArray, Output, Ctx>( fn: UnvalidatedFunction< Ctx & TransformedCtx, ExistingArgs, Promise<Output> >, ): UnvalidatedFunction< Ctx & OriginalCtx, MergeArgs<ExistingArgs, ObjectType<ConsumedArgsValidator>>, Promise<Output> >; function withFoo(fn: any): any { if (fn.args) { const handler = fn.handler; return { args: { ...fn.args, ...consumedArgsValidator, }, handler: async (ctx: any, allArgs: any) => { const { rest, consumed } = splitArgs(consumedArgsValidator, allArgs); const transformedCtx = await transformContext(ctx, consumed); return await handler(transformedCtx, rest); }, }; } const handler = fn.handler ?? fn; return { handler: async (ctx: any, allArgs: any) => { const { rest, consumed } = splitArgs(consumedArgsValidator, allArgs); const transformedCtx = await transformContext(ctx, consumed); return await handler(transformedCtx, rest); }, }; } return withFoo; }; export const generateQueryWithMiddleware = < TransformedCtx extends Record<string, any>, ConsumedArgsValidator extends PropertyValidators, >( consumedArgsValidator: ConsumedArgsValidator, transformContext: ( ctx: QueryCtx, args: ObjectType<ConsumedArgsValidator>, ) => Promise<TransformedCtx>, ) => { const withFoo = generateMiddlewareContextOnly( consumedArgsValidator, transformContext, ); function queryWithFoo< ExistingArgsValidator extends PropertyValidators, Output, >( fn: ValidatedFunction< TransformedCtx, ExistingArgsValidator, Promise<Output> >, ): RegisteredQuery< "public", ObjectType<ExistingArgsValidator> & ObjectType<ConsumedArgsValidator>, Output >; function queryWithFoo<ExistingArgs extends ArgsArray, Output>( fn: UnvalidatedFunction<TransformedCtx, ExistingArgs, Promise<Output>>, ): RegisteredQuery< "public", MergeArgsForRegistered<ExistingArgs, ObjectType<ConsumedArgsValidator>>, Output >; function queryWithFoo(fn: any): any { query(withFoo(fn)); } return queryWithFoo; }; export const generateMutationWithMiddleware = < TransformedCtx extends Record<string, any>, ConsumedArgsValidator extends PropertyValidators, >( consumedArgsValidator: ConsumedArgsValidator, transformContext: ( ctx: MutationCtx, args: ObjectType<ConsumedArgsValidator>, ) => Promise<TransformedCtx>, ) => { const withFoo = generateMiddlewareContextOnly( consumedArgsValidator, transformContext, ); function mutationWithFoo< ExistingArgsValidator extends PropertyValidators, Output, >( fn: ValidatedFunction< TransformedCtx, ExistingArgsValidator, Promise<Output> >, ): RegisteredMutation< "public", ObjectType<ExistingArgsValidator> & ObjectType<ConsumedArgsValidator>, Output >; function mutationWithFoo<ExistingArgs extends ArgsArray, Output>( fn: UnvalidatedFunction<TransformedCtx, ExistingArgs, Promise<Output>>, ): RegisteredMutation< "public", MergeArgsForRegistered<ExistingArgs, ObjectType<ConsumedArgsValidator>>, Output >; function mutationWithFoo(fn: any): any { mutation(withFoo(fn)); } return mutationWithFoo; }; export const generateActionWithMiddleware = < TransformedCtx extends Record<string, any>, ConsumedArgsValidator extends PropertyValidators, >( consumedArgsValidator: ConsumedArgsValidator, transformContext: ( ctx: ActionCtx, args: ObjectType<ConsumedArgsValidator>, ) => Promise<TransformedCtx>, ) => { const withFoo = generateMiddlewareContextOnly( consumedArgsValidator, transformContext, ); function actionWithFoo< ExistingArgsValidator extends PropertyValidators, Output, >( fn: ValidatedFunction< TransformedCtx, ExistingArgsValidator, Promise<Output> >, ): RegisteredAction< "public", ObjectType<ExistingArgsValidator> & ObjectType<ConsumedArgsValidator>, Output >; function actionWithFoo<ExistingArgs extends ArgsArray, Output>( fn: UnvalidatedFunction<TransformedCtx, ExistingArgs, Promise<Output>>, ): RegisteredAction< "public", MergeArgsForRegistered<ExistingArgs, ObjectType<ConsumedArgsValidator>>, Output >; function actionWithFoo(fn: any): any { action(withFoo(fn)); } return actionWithFoo; };

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