UNPKG

synaptra

Version:

A high-performance Model Context Protocol server for GraphQL APIs with advanced features, type-safety, and developer experience improvements

125 lines 4.81 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handleQueryGraphQL = exports.queryGraphQLTool = void 0; const types_1 = require("../types"); const logger_1 = require("../utils/logger"); exports.queryGraphQLTool = { name: 'query-graphql', description: 'Execute GraphQL queries, mutations, or subscriptions against the configured endpoint. Supports validation and dry-run mode.', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'The GraphQL query, mutation, or subscription to execute', }, variables: { type: 'object', description: 'Variables to pass to the GraphQL operation', additionalProperties: true, }, operationName: { type: 'string', description: 'The name of the operation to execute (if query contains multiple operations)', }, validate: { type: 'boolean', default: true, description: 'Validate the query against the schema before execution', }, dryRun: { type: 'boolean', default: false, description: 'Parse and validate the query without executing it', }, headers: { type: 'object', description: 'HTTP headers to include with the request (e.g., Authorization)', additionalProperties: { type: 'string' }, }, }, required: ['query'], }, }; const handleQueryGraphQL = async (args, client, allowMutations = false, allowSubscriptions = false) => { const logger = (0, logger_1.getLogger)(); const startTime = Date.now(); try { // Validate and parse arguments const params = types_1.QueryGraphQLParamsSchema.parse(args); logger.debug('Starting GraphQL query execution', { operationName: params.operationName, validate: params.validate, dryRun: params.dryRun, hasVariables: !!params.variables, hasHeaders: !!params.headers, }); // Log the query if query logging is enabled logger.query(params.query, params.variables); // Check operation type for security const operationType = detectOperationType(params.query); if (operationType === 'mutation' && !allowMutations) { throw new Error('Mutations are disabled. Set allowMutations to true to enable them.'); } if (operationType === 'subscription' && !allowSubscriptions) { throw new Error('Subscriptions are disabled. Set allowSubscriptions to true to enable them.'); } // Execute the query const queryInfo = { query: params.query, }; if (params.variables) { queryInfo.variables = params.variables; } if (params.operationName) { queryInfo.operationName = params.operationName; } if (params.headers) { queryInfo.headers = params.headers; } const result = await client.executeQuery(queryInfo, params.dryRun); const duration = Date.now() - startTime; logger.performance('GraphQL query execution', duration, { operationType, operationName: params.operationName, dryRun: params.dryRun, hasErrors: !!result.errors?.length, }); return result; } catch (error) { const duration = Date.now() - startTime; logger.error('GraphQL query execution failed', { error: error instanceof Error ? error.message : 'Unknown error', duration, }); throw error; } }; exports.handleQueryGraphQL = handleQueryGraphQL; // Helper function to detect operation type from query string function detectOperationType(query) { const trimmedQuery = query.trim().toLowerCase(); if (trimmedQuery.startsWith('mutation')) { return 'mutation'; } else if (trimmedQuery.startsWith('subscription')) { return 'subscription'; } else if (trimmedQuery.startsWith('query') || trimmedQuery.startsWith('{')) { return 'query'; } // Try to parse for more complex cases try { const { parse } = require('graphql'); const doc = parse(query); const operationDef = doc.definitions.find((def) => def.kind === 'OperationDefinition'); return operationDef?.operation || 'query'; } catch { return 'query'; // Default to query if we can't parse } } //# sourceMappingURL=query-graphql.js.map