@mcp-layer/graphql 0.2.0 → 0.2.2

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/README.md CHANGED
@@ -88,8 +88,9 @@ Options:
88
88
 
89
89
  | Option | Type | Default | Description |
90
90
  | --- | --- | --- | --- |
91
- | `session` | `Session` or `Session[]` | required | Bootstrap session(s) used for catalog extraction and static mode. |
92
- | `manager` | `{ get(request), close?() }` | optional | Per-request session manager (requires bootstrap `session`). |
91
+ | `session` | `Session` or `Session[]` | required unless using `manager` + `catalog` | Bootstrap session(s) used for catalog extraction and static mode. |
92
+ | `catalog` | `{ server?, items? }` | optional | Precomputed bootstrap catalog used when the live session should only be resolved lazily. |
93
+ | `manager` | `{ get(request), close?() }` | optional | Per-request session manager (requires bootstrap `session` or `catalog`). |
93
94
  | `prefix` | `string` or `(version, info, name) => string` | derived | Per-session route prefix. |
94
95
  | `endpoint` | `string` | `"/graphql"` | GraphQL POST endpoint path under prefix. |
95
96
  | `ide.enabled` | `boolean` | `false` | Enables GraphiQL route. |
@@ -599,7 +600,7 @@ Thrown from: `validateRuntimeOptions` (via `@mcp-layer/gateway`)
599
600
  This happens when `manager` is provided while `session` is an array.
600
601
 
601
602
  Step-by-step resolution:
602
- 1. In manager mode, pass one bootstrap `session`.
603
+ 1. In manager mode, pass one bootstrap `session` or one bootstrap `catalog`.
603
604
  2. For multi-session static mounts, remove `manager`.
604
605
  3. Register separate plugin instances per static session surface.
605
606
  4. Add startup tests for both architecture modes.
@@ -618,20 +619,20 @@ await fastify.register(mcpGraphql, {
618
619
 
619
620
  </details>
620
621
 
621
- <a id="error-126799"></a>
622
- ### `session is required when manager is provided (used for catalog bootstrap).`
622
+ <a id="error-aae9b3"></a>
623
+ ### `session or catalog is required when manager is provided (used for catalog bootstrap).`
623
624
 
624
625
  Thrown from: `validateRuntimeOptions` (via `@mcp-layer/gateway`)
625
626
 
626
- This happens when `manager` is configured without a bootstrap `session`.
627
+ This happens when `manager` is configured without a bootstrap `session` or `catalog`.
627
628
 
628
629
  Step-by-step resolution:
629
- 1. Always provide a bootstrap `session` with `manager`.
630
- 2. Ensure bootstrap session is connected before registration.
630
+ 1. Always provide a bootstrap `session` or `catalog` with `manager`.
631
+ 2. Ensure the bootstrap session is connected before registration, or ensure the bootstrap catalog matches the managed session surface.
631
632
  3. Keep bootstrap and managed sessions aligned in capability surface.
632
- 4. Add tests that fail fast without bootstrap session.
633
+ 4. Add tests that fail fast without bootstrap metadata.
633
634
 
634
- Canonical gateway reference: [`@mcp-layer/gateway` runtime errors](../gateway/README.md#error-c773d9).
635
+ Canonical gateway reference: [`@mcp-layer/gateway` runtime errors](../gateway/README.md#error-b010d3).
635
636
 
636
637
  <details>
637
638
  <summary>Fix Example: include bootstrap session in manager mode</summary>
@@ -645,6 +646,50 @@ await fastify.register(mcpGraphql, {
645
646
 
646
647
  </details>
647
648
 
649
+ <details>
650
+ <summary>Fix Example: include bootstrap catalog in manager mode</summary>
651
+
652
+ ```js
653
+ await fastify.register(mcpGraphql, {
654
+ catalog,
655
+ manager
656
+ });
657
+ ```
658
+
659
+ </details>
660
+
661
+ <a id="error-f184e1"></a>
662
+ ### `catalog must be an object.`
663
+
664
+ Thrown from: `validateRuntimeOptions` (via `@mcp-layer/gateway`)
665
+
666
+ This happens when `catalog` is passed as a primitive, array, or serialized payload instead of the composed catalog object the GraphQL plugin expects at bootstrap.
667
+
668
+ Step-by-step resolution:
669
+ 1. Pass the bootstrap catalog as a plain object.
670
+ 2. Do not pass stringified JSON or only the `items` array.
671
+ 3. Ensure the object shape matches the extracted/composed catalog surface.
672
+ 4. Add registration tests that reject malformed catalog bootstrap values.
673
+
674
+ Canonical gateway reference: [`@mcp-layer/gateway` runtime errors](../gateway/README.md#error-17712f).
675
+
676
+ <details>
677
+ <summary>Fix Example: provide bootstrap catalog as an object</summary>
678
+
679
+ ```js
680
+ await fastify.register(mcpGraphql, {
681
+ catalog: {
682
+ server: {
683
+ info: { name: 'example-server', version: '1.0.0' }
684
+ },
685
+ items: []
686
+ },
687
+ manager
688
+ });
689
+ ```
690
+
691
+ </details>
692
+
648
693
  <a id="error-66da32"></a>
649
694
  ### `session or manager option is required.`
650
695
 
@@ -654,7 +699,7 @@ This happens when plugin options omit both `session` and `manager`.
654
699
 
655
700
  Step-by-step resolution:
656
701
  1. Pass a connected `session` for static mode.
657
- 2. Or pass `manager` plus bootstrap `session` for dynamic mode.
702
+ 2. Or pass `manager` plus bootstrap `session` or `catalog` for dynamic mode.
658
703
  3. Assert required options before `register`.
659
704
  4. Add tests that validate registration failure on missing session source.
660
705
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-layer/graphql",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Fastify GraphQL plugin and schema builder for MCP catalogs with shared gateway runtime primitives.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,8 +18,10 @@
18
18
  "gateway"
19
19
  ],
20
20
  "main": "src/index.js",
21
+ "types": "./types/index.d.ts",
21
22
  "exports": {
22
23
  ".": {
24
+ "types": "./types/index.d.ts",
23
25
  "import": "./src/index.js",
24
26
  "default": "./src/index.js"
25
27
  },
@@ -27,6 +29,7 @@
27
29
  },
28
30
  "files": [
29
31
  "src",
32
+ "types",
30
33
  "LICENSE"
31
34
  ],
32
35
  "publishConfig": {
@@ -39,19 +42,20 @@
39
42
  "graphql-type-json": "^0.3.2",
40
43
  "mercurius": "^16.7.0",
41
44
  "uri-template": "^2.0.0",
42
- "@mcp-layer/error": "0.2.0",
43
- "@mcp-layer/gateway": "0.2.0"
45
+ "@mcp-layer/error": "0.2.1",
46
+ "@mcp-layer/gateway": "0.2.2"
44
47
  },
45
48
  "peerDependencies": {
46
49
  "fastify": "^5.0.0"
47
50
  },
48
51
  "devDependencies": {
49
52
  "fastify": "^5.7.4",
50
- "@mcp-layer/attach": "1.1.1",
51
- "@mcp-layer/manager": "0.2.0",
52
- "@mcp-layer/test-server": "1.0.1"
53
+ "@mcp-layer/attach": "1.1.2",
54
+ "@mcp-layer/manager": "0.2.1",
55
+ "@mcp-layer/test-server": "1.0.4"
53
56
  },
54
57
  "scripts": {
55
- "test": "node --test --experimental-test-coverage ./test/**/*.test.js"
58
+ "build:types": "tsc -p tsconfig.json",
59
+ "test": "node --test --experimental-test-coverage \"./test/**/*.test.js\""
56
60
  }
57
61
  }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Default configuration values for the GraphQL plugin.
3
+ * @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 } }}
4
+ */
5
+ export const DEFAULTS: {
6
+ prefix: string | undefined;
7
+ validation: {
8
+ trustSchemas: "auto" | true | false;
9
+ maxSchemaDepth: number;
10
+ maxSchemaSize: number;
11
+ maxPatternLength: number;
12
+ maxToolNameLength: number;
13
+ maxTemplateParamLength: number;
14
+ };
15
+ resilience: {
16
+ enabled: boolean;
17
+ timeout: number;
18
+ errorThresholdPercentage: number;
19
+ resetTimeout: number;
20
+ volumeThreshold: number;
21
+ };
22
+ telemetry: {
23
+ enabled: boolean;
24
+ serviceName: string;
25
+ metricPrefix: string;
26
+ api?: any;
27
+ };
28
+ errors: {
29
+ exposeDetails: boolean;
30
+ };
31
+ endpoint: string;
32
+ ide: {
33
+ enabled: boolean;
34
+ path: string;
35
+ };
36
+ operations: {
37
+ generated: boolean;
38
+ generic: boolean;
39
+ };
40
+ };
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Validate GraphQL adapter options.
3
+ * @param {Record<string, unknown>} opts - User options.
4
+ * @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 } }}
5
+ */
6
+ export function validateOptions(opts: Record<string, unknown>): {
7
+ session: unknown;
8
+ manager?: {
9
+ get: (request: import("fastify").FastifyRequest) => Promise<any>;
10
+ close?: () => Promise<void>;
11
+ };
12
+ prefix?: string | ((version: string, info: Record<string, unknown> | undefined, name: string) => string);
13
+ validation: {
14
+ trustSchemas: "auto" | true | false;
15
+ maxSchemaDepth: number;
16
+ maxSchemaSize: number;
17
+ maxPatternLength: number;
18
+ maxToolNameLength: number;
19
+ maxTemplateParamLength: number;
20
+ };
21
+ resilience: {
22
+ enabled: boolean;
23
+ timeout: number;
24
+ errorThresholdPercentage: number;
25
+ resetTimeout: number;
26
+ volumeThreshold: number;
27
+ };
28
+ telemetry: {
29
+ enabled: boolean;
30
+ serviceName: string;
31
+ metricPrefix: string;
32
+ api?: any;
33
+ };
34
+ errors: {
35
+ exposeDetails: boolean;
36
+ };
37
+ endpoint: string;
38
+ ide: {
39
+ enabled: boolean;
40
+ path: string;
41
+ };
42
+ operations: {
43
+ generated: boolean;
44
+ generic: boolean;
45
+ };
46
+ };
@@ -0,0 +1,3 @@
1
+ export { schema } from "./schema.js";
2
+ export { map } from "./mapping.js";
3
+ export { default, plugin } from "./plugin.js";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Build deterministic GraphQL mapping metadata from a catalog.
3
+ * @param {{ items?: Array<Record<string, unknown>> }} catalog - Extracted catalog.
4
+ * @param {Record<string, unknown>} [options] - Reserved for future mapping customization.
5
+ * @returns {ReturnType<typeof createMap>}
6
+ */
7
+ export function map(catalog: {
8
+ items?: Array<Record<string, unknown>>;
9
+ }, options?: Record<string, unknown>): ReturnType<typeof createMap>;
10
+ import { createMap } from '@mcp-layer/gateway';
@@ -0,0 +1,8 @@
1
+ export default plugin;
2
+ /**
3
+ * Fastify plugin that exposes MCP sessions as GraphQL endpoints.
4
+ * @param {import('fastify').FastifyInstance} fastify - Fastify instance.
5
+ * @param {Record<string, unknown>} opts - Plugin options.
6
+ * @returns {Promise<void>}
7
+ */
8
+ export function plugin(fastify: import("fastify").FastifyInstance, opts: Record<string, unknown>): Promise<void>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Build an executable GraphQL schema from an MCP catalog.
3
+ * @param {{ items?: Array<Record<string, unknown>> }} catalog - Extracted catalog.
4
+ * @param {{ operations?: { generated?: boolean, generic?: boolean } }} [options] - Build options.
5
+ * @returns {{ schema: import('graphql').GraphQLSchema, typeDefs: string, resolvers: Record<string, unknown>, mapping: ReturnType<typeof map> }}
6
+ */
7
+ export function schema(catalog?: {
8
+ items?: Array<Record<string, unknown>>;
9
+ }, options?: {
10
+ operations?: {
11
+ generated?: boolean;
12
+ generic?: boolean;
13
+ };
14
+ }): {
15
+ schema: import("graphql").GraphQLSchema;
16
+ typeDefs: string;
17
+ resolvers: Record<string, unknown>;
18
+ mapping: ReturnType<typeof map>;
19
+ };
20
+ import { map } from './mapping.js';