Skip to main content
Glama
graphql-server.ts•4.91 kB
import { ApolloServer } from '@apollo/server'; import { expressMiddleware } from '@apollo/server/express4'; import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer'; import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default'; import { makeExecutableSchema } from '@graphql-tools/schema'; import cors from 'cors'; import express from 'express'; import { graphqlUploadExpress } from 'graphql-upload-ts'; import { useServer } from 'graphql-ws/use/ws'; import http from 'http'; import { WebSocketServer } from 'ws'; import { authMiddleware, extractTokenFromExpressRequest, validateToken } from '../auth/auth.js'; import { DataStore } from '../datastore/types.js'; import { mcpHandler } from '../mcp/mcp-server.js'; import { logMessage } from "../utils/logs.js"; import { createTelemetryPlugin, telemetryMiddleware } from '../utils/telemetry.js'; import { resolvers, typeDefs } from './graphql.js'; import { GraphQLRequestContext, WorkerPools } from './types.js'; import { generateTraceId, traceIdMiddleware } from '../utils/trace-id.js'; export const DEFAULT_QUERY = ` query Query { listRuns(limit: 10) { items { id status createdAt } total } }`; export async function startGraphqlServer(datastore: DataStore, workerPools: WorkerPools) { const PORT = process.env.GRAPHQL_PORT ? parseInt(process.env.GRAPHQL_PORT) : 3000; // Create the schema const schema = makeExecutableSchema({ typeDefs, resolvers }); // Context Configuration const buildContextFromRequest = async ({ req }: { req: any }): Promise<GraphQLRequestContext> => { const context: GraphQLRequestContext = { datastore: datastore, workerPools: workerPools, traceId: req.traceId, orgId: req.orgId || '', userId: req.authInfo?.userId, orgName: req.authInfo?.orgName, orgRole: req.authInfo?.orgRole, toMetadata: function() { return { traceId: this.traceId, orgId: this.orgId }; } }; return context; }; // Express App Setup const app = express(); const httpServer = http.createServer(app); // WebSocket Server Setup const wsServer = new WebSocketServer({ server: httpServer, path: '/', }); // Setup graphql-ws server const serverCleanup = useServer({ schema, onConnect: async (ctx: any) => { ctx.traceId = generateTraceId();; }, context: async (ctx: any, msg, args): Promise<GraphQLRequestContext | boolean> => { const traceId = ctx.traceId; const token = extractTokenFromExpressRequest(ctx); const authResult = await validateToken(token); if (!authResult.success) { logMessage('warn', `GraphQL Server: Websocket Subscription authentication failed for token: ${token?.slice(0, 10) ?? 'none'}...`, { traceId }); return false; } const context: GraphQLRequestContext = { datastore, workerPools, traceId, orgId: authResult.orgId, userId: authResult.userId, orgName: authResult.orgName, orgRole: authResult.orgRole, toMetadata: function() { return { traceId: this.traceId, orgId: this.orgId }; } }; return context; }, onDisconnect(ctx: any, code, reason) { logMessage('debug', `GraphQL Server: Websocket Subscription disconnected. code=${code} reason=${reason}`, { traceId: ctx.traceId }); }, }, wsServer); // Apollo Server Configuration const server = new ApolloServer({ schema, introspection: true, csrfPrevention: false, plugins: [ ApolloServerPluginDrainHttpServer({ httpServer }), { async serverWillStart() { return { async drainServer() { await serverCleanup.dispose(); }, }; }, }, ApolloServerPluginLandingPageLocalDefault({ footer: false, embed: true, document: DEFAULT_QUERY }), createTelemetryPlugin() ], }); await server.start(); // Apply Middleware app.use(cors<cors.CorsRequest>()); app.use(express.json({ limit: '1024mb' })); app.use(traceIdMiddleware); app.use(authMiddleware); app.use(telemetryMiddleware); app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 1, })); app.post('/mcp', mcpHandler); app.get('/mcp', mcpHandler); app.delete('/mcp', mcpHandler); app.use('/', expressMiddleware(server, { context: buildContextFromRequest })); try { await new Promise<void>((resolve) => httpServer.listen({ port: PORT }, resolve)); logMessage('info', `🚀 Express GraphQL server ready at http://localhost:${PORT}/ and ws://localhost:${PORT}/`); } catch (error) { logMessage('error', `Failed to start GraphQL server: ${error}`); throw error; } return { server, httpServer, app }; }

Latest Blog Posts

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/superglue-ai/superglue'

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