Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,192
  • Linux
  • Apple
app.ts4.7 kB
import timers from 'node:timers/promises' import { normalizeJsonProtocolValues, QueryEvent, QueryInterpreter, QueryPlanNode, safeJsonStringify, TransactionInfo, TransactionManager, TransactionOptions, } from '@prisma/client-engine-runtime' import { ConnectionInfo, Provider, SqlDriverAdapter } from '@prisma/driver-adapter-utils' import * as log from '../log/facade' import { Options } from '../options' import { TracingHandler } from '../tracing/handler' import { runInActiveSpan, tracer } from '../tracing/tracer' import { createAdapter } from './adapter' import { ResourceLimitError, ResourceLimits } from './resource-limits' /** * Entry point for the application logic. */ export class App { readonly #db: SqlDriverAdapter readonly #transactionManager: TransactionManager readonly #tracingHandler: TracingHandler constructor(db: SqlDriverAdapter, transactionManager: TransactionManager, tracingHandler: TracingHandler) { this.#db = db this.#transactionManager = transactionManager this.#tracingHandler = tracingHandler } /** * Connects to the database and initializes the application logic. */ static async start(options: Options): Promise<App> { const connector = createAdapter(options.databaseUrl) const db = await runInActiveSpan('connect', () => connector.connect()) const tracingHandler = new TracingHandler(tracer) const transactionManager = new TransactionManager({ driverAdapter: db, transactionOptions: { timeout: options.maxTransactionTimeout.total('milliseconds'), maxWait: options.maxTransactionWaitTime.total('milliseconds'), }, tracingHelper: tracingHandler, onQuery: logQuery, }) return new App(db, transactionManager, tracingHandler) } /** * Cancels all active transactions and disconnects from the database. */ async shutdown(): Promise<void> { try { await this.#transactionManager.cancelAllTransactions() } finally { await this.#db.dispose() } } /** * Executes a query plan and returns the result. */ async query( queryPlan: QueryPlanNode, placeholderValues: Record<string, unknown>, resourceLimits: ResourceLimits, transactionId: string | null, ): Promise<unknown> { return await this.#tracingHandler.runInChildSpan('query', async () => { const queryable = transactionId !== null ? await this.#transactionManager.getTransaction({ id: transactionId }, 'query') : this.#db const queryInterpreter = QueryInterpreter.forSql({ placeholderValues, tracingHelper: this.#tracingHandler, transactionManager: transactionId === null ? { enabled: true, manager: this.#transactionManager } : { enabled: false }, onQuery: logQuery, }) const result = await Promise.race([ queryInterpreter.run(queryPlan, queryable), timers.setTimeout(resourceLimits.queryTimeout.total('milliseconds'), undefined, { ref: false }).then(() => { throw new ResourceLimitError('Query timeout exceeded') }), ]) return normalizeJsonProtocolValues(result) }) } /** * Starts a new transaction. */ async startTransaction(options: TransactionOptions, resourceLimits: ResourceLimits): Promise<TransactionInfo> { return await this.#tracingHandler.runInChildSpan('start_transaction', () => { const timeout = Math.min(options.timeout ?? Infinity, resourceLimits.maxTransactionTimeout.total('milliseconds')) return this.#transactionManager.startTransaction({ ...options, timeout, }) }) } /** * Commits a transaction. */ async commitTransaction(transactionId: string): Promise<void> { return await this.#tracingHandler.runInChildSpan('commit_transaction', () => this.#transactionManager.commitTransaction(transactionId), ) } /** * Rolls back a transaction. */ async rollbackTransaction(transactionId: string): Promise<void> { return await this.#tracingHandler.runInChildSpan('rollback_transaction', () => this.#transactionManager.rollbackTransaction(transactionId), ) } /** * Retrieves connection information necessary for building the queries. */ getConnectionInfo(): { provider: Provider; connectionInfo: ConnectionInfo } { const connectionInfo = this.#db.getConnectionInfo?.() ?? { supportsRelationJoins: false } return { provider: this.#db.provider, connectionInfo } } } function logQuery(event: QueryEvent): void { log.query('Query', { ...event, timestamp: Number(event.timestamp), params: safeJsonStringify(event.params), }) }

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/prisma/prisma'

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