Skip to main content
Glama

Convex MCP server

Official
by get-convex
setup.ts7.03 kB
import { setupURL } from "./00_url.js"; import { setupCrypto } from "./00_crypto.js"; import { setupDOMException } from "./01_dom_exception.js"; import { setupConsole } from "./02_console"; import { setupEvent } from "./02_event"; import { setupTimers } from "./02_timers.js"; import { setupAbortSignal } from "./03_abort_signal.js"; import { setupStreams } from "./06_streams.js"; import { setupTextEncoding } from "./08_text_encoding.js"; import { setupBlob } from "./09_file.js"; import { setupHeaders } from "./20_headers.js"; import { setupFormData } from "./21_formdata.js"; import { requestFromConvexJson, setupRequest } from "./23_request.js"; import { convexJsonFromResponse, setupResponse } from "./23_response.js"; import { setupFetch } from "./26_fetch.js"; import { setupSourceMapping } from "./errors.js"; import { throwUncatchableDeveloperError } from "./helpers.js"; import { getBlob, getResponse, storeBlob, storeRequest } from "./storage.js"; import { performOp } from "udf-syscall-ffi"; import { setupStructuredClone } from "./02_structured_clone.js"; /** * Set up the global object for a UDF context with deterministic Convex APIs. * * This initializes certain JS globals, and patches existing globals such as the * `Math.random` function, the `Date` object, and the `console` object. */ export function setup(global: any) { setupSourceMapping(); setupDate(global); // NB: It's important we call into `setupMisc` before the other setup functions // since those may call into 3rd party libraries we bundle, which may then // retain references to globals we modify, like `Date` or `FinalizationRegistry`. setupMisc(global); // These need to be set up in order of the numbers in their filenames (taken // from Deno) since later ones depend on the earlier ones. setupURL(global); setupCrypto(global); setupDOMException(global); setupConsole(global); setupEvent(global); setupStructuredClone(global); setupTimers(global); setupAbortSignal(global); setupStreams(global); setupTextEncoding(global); setupBlob(global); setupHeaders(global); setupFormData(global); setupRequest(global); setupResponse(global); setupFetch(global); global.Convex.jsSyscall = (op: string, args: Record<string, any>) => { switch (op) { case "requestFromConvexJson": return requestFromConvexJson(args as any); case "convexJsonFromResponse": return convexJsonFromResponse(args as any); case "storage/storeBlob": return storeBlob(args as any); case "storage/getBlob": return getBlob(args as any); // Deprecated APIs, used prior to Convex 0.13.0 case "storage/storeFile": return storeRequest(args as any); case "storage/getFile": return getResponse(args as any); default: return throwUncatchableDeveloperError(`Unknown JS syscall: ${op}`); } }; } function setupDate(global) { // Patch `Date` with our own version that returns a consistent result. // We only patch the paths that refer to the current time because for all // other paths, we have already ensured determinism by pinning the system // time to UTC via the TZ environment variable. const originalDate = global.Date; delete global.Date; function Date(...args) { // `Date()` was called directly, not as a constructor. if (!(this instanceof Date)) { const date = new (Date as any)(); return date.toString(); } if (args.length === 0) { const unixTsMs = Date.now(); return new originalDate(unixTsMs); } return new originalDate(...args); } Date.now = function () { return performOp("now"); }; Date.parse = originalDate.parse; Date.UTC = originalDate.UTC; Date.prototype = originalDate.prototype; Date.prototype.constructor = Date; global.Date = Date; } function setupMisc(global) { // Patch `Math.random` with our own deterministic RNG. delete global.Math.random; global.Math.random = function () { return performOp("random"); }; // Proxy process.env. with a syscall that gets the environment variable's value. const handler = { get(_target: any, prop: any, receiver: any) { if (typeof prop === "string") { const value = performOp("environmentVariables/get", prop); // Map null to undefined in case other libraries check explicitly for undefined // Note serde Value enum in rust does not have an undefined variant, only null. if (value === null) { if (prop === "inspect") { return () => "[process.env]"; } return undefined; } return value; } else { return Reflect.get(_target, prop, receiver); } }, }; const env = new Proxy({}, handler); global.process = { env }; // defined in browsers and required by the WinterCG Minimum Common Web Platform API draft // https://common-min-api.proposal.wintercg.org/ global.self = global; // Patch `WeakRef` with a noop implementation since it externalizes non-deterministic GC decisions. delete global.WeakRef; global.WeakRef = WeakRef; // Patch `FinalizationRegistry` with our own version that does nothing. delete global.FinalizationRegistry; global.FinalizationRegistry = FinalizationRegistry; } // No-op implementation of https://tc39.es/ecma262/multipage/managing-memory.html#sec-finalization-registry.prototype.register class FinalizationRegistry { constructor(callbackFn: (heldValue: any) => void) { if (typeof callbackFn !== "function") { throw new TypeError("cleanup must be callable"); } } register(target, heldValue, unregisterToken) { if (!CanBeHeldWeakly(target)) { throw new TypeError("target must be an object"); } if (target === heldValue) { throw new TypeError("target and holdings must not be same"); } if (unregisterToken !== undefined && !CanBeHeldWeakly(unregisterToken)) { throw new TypeError("unregisterToken must be an object"); } } unregister(unregisterToken) { if (!CanBeHeldWeakly(unregisterToken)) { throw new TypeError("unregisterToken must be an object"); } } get [Symbol.toStringTag]() { return "FinalizationRegistry"; } } // Implementation of https://tc39.es/ecma262/multipage/managing-memory.html#sec-weak-ref-objects // that is just a strong reference under the hood. class WeakRef { #target: any; constructor(target) { if (target === undefined || !CanBeHeldWeakly(target)) { throw new TypeError("target must be an object"); } this.#target = target; } deref() { return this.#target; } get [Symbol.toStringTag]() { return "WeakRef"; } } // https://tc39.es/ecma262/multipage/executable-code-and-execution-contexts.html#sec-canbeheldweakly function CanBeHeldWeakly(v: any) { if (typeof v === "object" || typeof v === "function") { return true; } if (typeof v === "symbol" || Symbol.keyFor(v) === undefined) { return true; } return false; }

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