@mcp-layer/graphql 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@mcp-layer/graphql",
3
+ "version": "0.1.0",
4
+ "description": "Fastify GraphQL plugin and schema builder for MCP catalogs with shared gateway runtime primitives.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/3rd-Eden/mcp-layer"
8
+ },
9
+ "type": "module",
10
+ "keywords": [
11
+ "mcp",
12
+ "mcp-layer",
13
+ "graphql",
14
+ "fastify",
15
+ "mercurius",
16
+ "schema",
17
+ "adapter",
18
+ "gateway"
19
+ ],
20
+ "main": "src/index.js",
21
+ "exports": {
22
+ ".": {
23
+ "import": "./src/index.js",
24
+ "default": "./src/index.js"
25
+ },
26
+ "./package.json": "./package.json"
27
+ },
28
+ "files": [
29
+ "src",
30
+ "LICENSE"
31
+ ],
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "dependencies": {
36
+ "@graphql-tools/schema": "^10.0.31",
37
+ "fastify-plugin": "^5.0.0",
38
+ "graphql": "^16.12.0",
39
+ "graphql-type-json": "^0.3.2",
40
+ "mercurius": "^16.7.0",
41
+ "uri-template": "^2.0.0",
42
+ "@mcp-layer/gateway": "0.1.0",
43
+ "@mcp-layer/error": "0.2.0"
44
+ },
45
+ "peerDependencies": {
46
+ "fastify": "^5.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "fastify": "^5.7.4",
50
+ "@mcp-layer/manager": "0.2.0",
51
+ "@mcp-layer/test-server": "1.0.1",
52
+ "@mcp-layer/attach": "1.1.1"
53
+ },
54
+ "scripts": {
55
+ "test": "node --test --experimental-test-coverage ./test/**/*.test.js"
56
+ }
57
+ }
@@ -0,0 +1,24 @@
1
+ import { defaults as runtimeDefaults } from '@mcp-layer/gateway';
2
+
3
+ const base = runtimeDefaults('mcp-layer-graphql');
4
+
5
+ /**
6
+ * Default configuration values for the GraphQL plugin.
7
+ * @type {{ prefix: string | undefined, validation: { trustSchemas: 'auto' | true | false, maxSchemaDepth: number, maxSchemaSize: number, maxPatternLength: number, maxToolNameLength: number, maxTemplateParamLength: number }, resilience: { enabled: boolean, timeout: number, errorThresholdPercentage: number, resetTimeout: number, volumeThreshold: number }, telemetry: { enabled: boolean, serviceName: string, metricPrefix: string, api?: import('@opentelemetry/api') }, errors: { exposeDetails: boolean }, endpoint: string, ide: { enabled: boolean, path: string }, operations: { generated: boolean, generic: boolean } }}
8
+ */
9
+ export const DEFAULTS = {
10
+ ...base,
11
+ telemetry: {
12
+ ...base.telemetry,
13
+ metricPrefix: 'graphql'
14
+ },
15
+ endpoint: '/graphql',
16
+ ide: {
17
+ enabled: false,
18
+ path: '/graphiql'
19
+ },
20
+ operations: {
21
+ generated: true,
22
+ generic: true
23
+ }
24
+ };
@@ -0,0 +1,76 @@
1
+ import { validateRuntimeOptions } from '@mcp-layer/gateway';
2
+ import { LayerError } from '@mcp-layer/error';
3
+ import { DEFAULTS } from './defaults.js';
4
+
5
+ /**
6
+ * Test whether a value is a plain object.
7
+ * @param {unknown} value - Candidate value.
8
+ * @returns {value is Record<string, unknown>}
9
+ */
10
+ function isRecord(value) {
11
+ return Boolean(value && typeof value === 'object' && !Array.isArray(value));
12
+ }
13
+
14
+ /**
15
+ * Validate GraphQL adapter options.
16
+ * @param {Record<string, unknown>} opts - User options.
17
+ * @returns {{ session: unknown, manager?: { get: (request: import('fastify').FastifyRequest) => Promise<import('@mcp-layer/session').Session>, close?: () => Promise<void> }, prefix?: string | ((version: string, info: Record<string, unknown> | undefined, name: string) => string), validation: { trustSchemas: 'auto' | true | false, maxSchemaDepth: number, maxSchemaSize: number, maxPatternLength: number, maxToolNameLength: number, maxTemplateParamLength: number }, resilience: { enabled: boolean, timeout: number, errorThresholdPercentage: number, resetTimeout: number, volumeThreshold: number }, telemetry: { enabled: boolean, serviceName: string, metricPrefix: string, api?: import('@opentelemetry/api') }, errors: { exposeDetails: boolean }, endpoint: string, ide: { enabled: boolean, path: string }, operations: { generated: boolean, generic: boolean } }}
18
+ */
19
+ export function validateOptions(opts) {
20
+ const base = validateRuntimeOptions(opts, {
21
+ name: 'graphql',
22
+ serviceName: DEFAULTS.telemetry.serviceName
23
+ });
24
+
25
+ const input = isRecord(opts) ? opts : {};
26
+ const endpoint = typeof input.endpoint === 'string' && input.endpoint.length > 0
27
+ ? input.endpoint
28
+ : DEFAULTS.endpoint;
29
+
30
+ if (!endpoint.startsWith('/')) {
31
+ throw new LayerError({
32
+ name: 'graphql',
33
+ method: 'validateOptions',
34
+ message: 'endpoint must start with "/".'
35
+ });
36
+ }
37
+
38
+ const ideInput = isRecord(input.ide) ? input.ide : {};
39
+ const ide = {
40
+ enabled: ideInput.enabled === undefined ? DEFAULTS.ide.enabled : Boolean(ideInput.enabled),
41
+ path: typeof ideInput.path === 'string' && ideInput.path.length > 0 ? ideInput.path : DEFAULTS.ide.path
42
+ };
43
+
44
+ if (!ide.path.startsWith('/')) {
45
+ throw new LayerError({
46
+ name: 'graphql',
47
+ method: 'validateOptions',
48
+ message: 'ide.path must start with "/".'
49
+ });
50
+ }
51
+
52
+ const operationsInput = isRecord(input.operations) ? input.operations : {};
53
+ const operations = {
54
+ generated: operationsInput.generated === undefined ? DEFAULTS.operations.generated : Boolean(operationsInput.generated),
55
+ generic: operationsInput.generic === undefined ? DEFAULTS.operations.generic : Boolean(operationsInput.generic)
56
+ };
57
+
58
+ if (!operations.generated && !operations.generic) {
59
+ throw new LayerError({
60
+ name: 'graphql',
61
+ method: 'validateOptions',
62
+ message: 'operations.generated and operations.generic cannot both be false.'
63
+ });
64
+ }
65
+
66
+ return {
67
+ ...base,
68
+ telemetry: {
69
+ ...base.telemetry,
70
+ metricPrefix: 'graphql'
71
+ },
72
+ endpoint,
73
+ ide,
74
+ operations
75
+ };
76
+ }
package/src/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { default, plugin } from './plugin.js';
2
+ export { schema } from './schema.js';
3
+ export { map } from './mapping.js';
package/src/mapping.js ADDED
@@ -0,0 +1,12 @@
1
+ import { createMap } from '@mcp-layer/gateway';
2
+
3
+ /**
4
+ * Build deterministic GraphQL mapping metadata from a catalog.
5
+ * @param {{ items?: Array<Record<string, unknown>> }} catalog - Extracted catalog.
6
+ * @param {Record<string, unknown>} [options] - Reserved for future mapping customization.
7
+ * @returns {ReturnType<typeof createMap>}
8
+ */
9
+ export function map(catalog, options = {}) {
10
+ void options;
11
+ return createMap(catalog);
12
+ }