Skip to content

feat(mcp): support custom JSON-RPC methods and capabilities - #2420

Open
zensucht wants to merge 6 commits into
graphql-hive:mainfrom
zensucht:feat/mcp-graphql-jsonrpc
Open

feat(mcp): support custom JSON-RPC methods and capabilities#2420
zensucht wants to merge 6 commits into
graphql-hive:mainfrom
zensucht:feat/mcp-graphql-jsonrpc

Conversation

@zensucht

Copy link
Copy Markdown

Description

@graphql-hive/plugin-mcp dispatches a fixed set of MCP methods. This PR makes that dispatch extensible: integrators can serve additional JSON-RPC methods from the MCP endpoint via customMethods and advertise matching entries in the initialize response via customCapabilities.

import { MCPMethodError, useMCP } from '@graphql-hive/plugin-mcp';

useMCP(ctx, {
  name: 'my-api',
  customCapabilities: { graphql: {} },
  customMethods: {
    'graphql/run': async (params, context) => {
      const { query } = params as { query?: string };
      if (typeof query !== 'string') {
        throw new MCPMethodError(-32602, 'Invalid params: "query" must be a string');
      }
      return context.executeGraphQL({ query });
    },
  },
});

Handlers receive a context with executeGraphQL (runs the operation through the full server pipeline — every configured plugin sees it, original request headers forwarded), getSchema(), and transport (the incoming request and its headers). The return value becomes the JSON-RPC result; throwing MCPMethodError produces an error response with a specific code.

This keeps the plugin's built-in surface untouched while letting gateway operators expose purpose-built methods (for example, direct GraphQL execution for agent clients) without forking the plugin.

Commits

  1. refactor(mcp): extract built-in method dispatch into a registry — behavior-preserving restructure of handleMCPRequest: the six built-in method cases move from a switch into named handler functions dispatched via a map. No public API change; the existing test suite passes unchanged. This is the bulk of the diff by line count.
  2. fix(mcp): suppress responses for unknown notification methods — spec-correctness fix found while restructuring the dispatcher: unknown notifications/* methods previously received a -32601 error response, but per JSON-RPC 2.0 §4.1 notifications never receive a response. They are now dropped with a debug log. This is the PR's only behavior change to an existing path; it is called out in the changeset.
  3. feat(mcp): support custom JSON-RPC methods and capabilities — the feature: public types (MCPMethodHandler, MCPMethodContext, MCPMethodTransport, MCPGraphQLOperation), the MCPMethodError class, config fields, dispatch, capability merge, and docs.

Design notes

  • executeGraphQL runs the full pipeline. Internal execution goes through yoga.handle() — the same entry the server adapter wraps — with the incoming request's server context and forwarded headers. Header-driven plugins (auth, tracing) treat the operation like any HTTP request; the operation shares the surrounding MCP request's server context, which is documented on the context type.
  • Header forwarding matches tools/call fidelity. tools/call already executes GraphQL with the original request's headers; custom methods behave identically. Policy (header filtering, rate limits) remains where it already lives — the gateway's plugin chain, which runs on the internal request too.
  • Collisions fail at startup. customMethods names that shadow built-ins (initialize, tools/list, tools/call, resources/list, resources/templates/list, resources/read, notifications/initialized) throw with a message listing the conflicts. Non-function values also throw.
  • Notification semantics by name and by id. Methods under notifications/ never produce a response, even if a client mistakenly sends an id — matching the built-in notifications/initialized behavior. Handler errors on notifications are logged and swallowed.
  • Guarded internal responses. If a plugin short-circuits internal execution with a non-JSON response, the handler surfaces a clear error naming the HTTP status instead of a JSON parse failure. A startup guard also rejects configuring the MCP path to collide with the GraphQL endpoint.

Testing

28 new tests (351 total in the plugin):

  • Dispatch unit tests: result wrapping, context contents, MCPMethodError conversion (with and without data), error bubbling, notification semantics (no-id, with-id, thrown errors), built-in-first ordering, unknown-method fallthrough.
  • Startup validation: collision throws (including the tools/call reservation), non-function rejection.
  • E2E through createGatewayRuntime with a proxied upstream: full round trip over HTTP, capability advertisement, pipeline execution verified by an onExecute hook firing and the upstream resolver being reached, header forwarding into internal execution, HTTP 204 for notifications, and a second gateway whose /graphql returns 401 HTML to pin the non-JSON error path.

Changeset

Minor bump for @graphql-hive/plugin-mcp. The notification behavior change is documented there.

zensucht added 3 commits June 10, 2026 20:08
Per JSON-RPC 2.0, notifications never receive a response. Unknown
notifications/* methods previously got a -32601 error response; they
are now dropped with a debug log.
Adds customMethods and customCapabilities to the MCP plugin config.
Custom methods are dispatched on the MCP endpoint after the built-ins
and receive a context with executeGraphQL (full server pipeline,
request headers and server context forwarded), getSchema, and
transport details. MCPMethodError produces JSON-RPC error responses
with specific codes. Name collisions with built-in methods fail at
startup.
@qodo-code-review

qodo-code-review Bot commented Jun 11, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0)

Grey Divider


Action required

1. Prototype method dispatch ✓ Resolved 🐞 Bug ≡ Correctness
Description
handleMCPRequest looks up customMethods via options.customMethods?.[method], so requests like
method="constructor"/"toString" can resolve to inherited Object prototype properties and be
(mis)dispatched or throw internal errors instead of returning -32601. This makes unknown-method
handling incorrect whenever customMethods is configured and the client picks a prototype-key
method name.
Code

packages/plugins/mcp/src/protocol.ts[R872-883]

+  const handler = defaultMethods.get(method);
+  if (!handler) {
+    const customHandler = options.customMethods?.[method];
+    if (customHandler) {
+      return dispatchCustomMethod(
+        ctx,
+        body,
+        options,
+        customHandler,
+        dispatchContext,
+      );
+    }
Evidence
The dispatcher uses direct bracket access on a plain object for client-controlled method names,
which includes prototype chain properties; useMCP only validates values and collisions but does
not prevent prototype inheritance from affecting runtime lookups.

packages/plugins/mcp/src/protocol.ts[872-883]
packages/plugins/mcp/src/plugin.ts[918-932]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`handleMCPRequest` reads `options.customMethods?.[method]` directly. Because `customMethods` is a plain object, attacker-controlled `method` strings can resolve to inherited properties (e.g. `constructor`, `toString`, `hasOwnProperty`), causing unintended dispatch or unexpected internal errors instead of a clean `-32601` "Method not found" response.
## Issue Context
Startup validation in `useMCP` verifies that configured entries are functions and don’t collide with built-ins, but it does not prevent inherited prototype properties from being visible at runtime.
## Fix Focus Areas
- packages/plugins/mcp/src/protocol.ts[872-883]
- packages/plugins/mcp/src/plugin.ts[918-932]
### Recommended fix
Guard dispatch with an own-property check:
- Prefer `Object.hasOwn(options.customMethods, method)` (or `Object.prototype.hasOwnProperty.call(...)`) before reading/dispatching.
Optionally, normalize `customMethods` once at startup:
- In `useMCP`, copy `config.customMethods` into an `Object.create(null)` object (or a `Map`) and pass that safe container down as `options.customMethods`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. tools/call null id allowed 🐞 Bug ≡ Correctness
Description
The HTTP-layer tools/call path accepts id: null and proceeds to produce a response with `id:
null, even though the shared JSON-RPC validation rejects id == null for non-notifications/*`
methods. This creates inconsistent request-id semantics across MCP methods and can emit responses
that the rest of the implementation treats as invalid requests.
Code

packages/plugins/mcp/src/plugin.ts[1]

    const providerContext: DescriptionProviderContext | undefined =
Evidence
tools/call validation explicitly allows null ids and stores jsonrpcId as possibly null;
meanwhile, the protocol-layer validator rejects id == null for non-notification methods,
establishing the plugin’s intended rule and showing the inconsistency.

packages/plugins/mcp/src/plugin.ts[1495-1514]
packages/plugins/mcp/src/plugin.ts[1677-1685]
packages/plugins/mcp/src/protocol.ts[864-870]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`tools/call` is validated and dispatched in `plugin.ts` (before `handleMCPRequest`). The current validation permits `id: null`, which allows a `tools/call` request to proceed and later return a JSON-RPC response with a null id.
This contradicts the shared JSON-RPC validator in `handleMCPRequest`, which treats `id == null` as a missing id for all non-notification methods.
## Issue Context
- `handleMCPRequest` rejects `id == null` unless the method name starts with `notifications/`.
- `tools/call` bypasses that validator and therefore needs to enforce the same policy itself (or explicitly treat `id: null` as a notification and suppress responses).
## Fix Focus Areas
- packages/plugins/mcp/src/plugin.ts[1495-1514]
- packages/plugins/mcp/src/plugin.ts[1677-1685]
- packages/plugins/mcp/src/protocol.ts[864-870]
### Recommended fix
Make `tools/call` require a non-null id:
- Change validation to reject when `body.id == null` or type is not string/number.
- Update error message accordingly.
- If null-id notifications for `tools/call` are desired, implement explicit notification semantics (do not store the call / do not set a result processor / return 204), and document it consistently.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unknown notifications still respond ✓ Resolved 🐞 Bug ≡ Correctness
Description
handleMCPRequest only drops unknown notification methods when id == null, so an unknown
notifications/* call that includes an id returns a -32601 response. This contradicts the
documented behavior that notifications/* methods never produce a response (even if an id is sent)
and is inconsistent with the custom-method notification handling which checks the method prefix.
Code

packages/plugins/mcp/src/protocol.ts[R884-896]

+    // Per JSON-RPC 2.0 §4.1, notifications never receive a response.
+    // The validation step above already established that a null id
+    // implies a `notifications/` method, so checking id alone here
+    // is sufficient.
+    if (id == null) {
+      ctx.log.debug(`Ignoring unknown notification method: ${method}`);
+      return null;
+    }
+    return {
+      jsonrpc: '2.0',
+      id,
+      error: { code: -32601, message: `Method not found: ${method}` },
+    };
Evidence
The protocol dispatcher explicitly suppresses unknown notification responses only when id == null,
so notifications/* with an id falls through to the -32601 error response. The README states
that methods under notifications/ never produce a response, implying the suppression should be
based on the method prefix, not only on the absence of an id.

packages/plugins/mcp/src/protocol.ts[833-896]
packages/plugins/mcp/README.md[394-431]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Unknown JSON-RPC methods under `notifications/` are only ignored when the request `id` is null/absent. If a client mistakenly includes an `id` for an unknown `notifications/*` method, the server currently replies with `-32601`, despite the documented contract that `notifications/*` never receive a response.
### Issue Context
- Built-in `notifications/initialized` correctly returns `null` (no response) even if an `id` is provided.
- Custom method dispatch treats `method.startsWith('notifications/')` as a notification regardless of id.
- The unknown-method fallback currently checks only `id == null`.
### Fix Focus Areas
- packages/plugins/mcp/src/protocol.ts[884-896]
Suggested change:
- In the unknown-method branch, change the suppression condition from `if (id == null)` to `if (method.startsWith('notifications/'))`.
- Keep the debug log, but ensure it logs and returns `null` for *any* unknown `notifications/*` method, even when an id is present.
- Add/adjust a unit test to cover `notifications/something-unknown` with an explicit `id` and assert no response.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Unknown notifications still respond ✓ Resolved 🐞 Bug ≡ Correctness
Description
handleMCPRequest only drops unknown notification methods when id == null, so an unknown
notifications/* call that includes an id returns a -32601 response. This contradicts the
documented behavior that notifications/* methods never produce a response (even if an id is sent)
and is inconsistent with the custom-method notification handling which checks the method prefix.
Code

packages/plugins/mcp/src/protocol.ts[R884-896]

+    // Per JSON-RPC 2.0 §4.1, notifications never receive a response.
+    // The validation step above already established that a null id
+    // implies a `notifications/` method, so checking id alone here
+    // is sufficient.
+    if (id == null) {
+      ctx.log.debug(`Ignoring unknown notification method: ${method}`);
+      return null;
+    }
+    return {
+      jsonrpc: '2.0',
+      id,
+      error: { code: -32601, message: `Method not found: ${method}` },
+    };
Evidence
The protocol dispatcher explicitly suppresses unknown notification responses only when id == null,
so notifications/* with an id falls through to the -32601 error response. The README states
that methods under notifications/ never produce a response, implying the suppression should be
based on the method prefix, not only on the absence of an id.

packages/plugins/mcp/src/protocol.ts[833-896]
packages/plugins/mcp/README.md[394-431]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Unknown JSON-RPC methods under `notifications/` are only ignored when the request `id` is null/absent. If a client mistakenly includes an `id` for an unknown `notifications/*` method, the server currently replies with `-32601`, despite the documented contract that `notifications/*` never receive a response.
### Issue Context
- Built-in `notifications/initialized` correctly returns `null` (no response) even if an `id` is provided.
- Custom method dispatch treats `method.startsWith('notifications/')` as a notification regardless of id.
- The unknown-method fallback currently checks only `id == null`.
### Fix Focus Areas
- packages/plugins/mcp/src/protocol.ts[884-896]
Suggested change:
- In the unknown-method branch, change the suppression condition from `if (id == null)` to `if (method.startsWith('notifications/'))`.
- Keep the debug log, but ensure it logs and returns `null` for *any* unknown `notifications/*` method, even when an id is present.
- Add/adjust a unit test to cover `notifications/something-unknown` with an explicit `id` and assert no response.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 11, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0)

Grey Divider


Remediation recommended

1. Unknown notifications still respond 🐞 Bug ≡ Correctness
Description
handleMCPRequest only drops unknown notification methods when id == null, so an unknown
notifications/* call that includes an id returns a -32601 response. This contradicts the
documented behavior that notifications/* methods never produce a response (even if an id is sent)
and is inconsistent with the custom-method notification handling which checks the method prefix.
Code

packages/plugins/mcp/src/protocol.ts[R884-896]

+    // Per JSON-RPC 2.0 §4.1, notifications never receive a response.
+    // The validation step above already established that a null id
+    // implies a `notifications/` method, so checking id alone here
+    // is sufficient.
+    if (id == null) {
+      ctx.log.debug(`Ignoring unknown notification method: ${method}`);
+      return null;
+    }
+    return {
+      jsonrpc: '2.0',
+      id,
+      error: { code: -32601, message: `Method not found: ${method}` },
+    };
Evidence
The protocol dispatcher explicitly suppresses unknown notification responses only when id == null,
so notifications/* with an id falls through to the -32601 error response. The README states
that methods under notifications/ never produce a response, implying the suppression should be
based on the method prefix, not only on the absence of an id.

packages/plugins/mcp/src/protocol.ts[833-896]
packages/plugins/mcp/README.md[394-431]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Unknown JSON-RPC methods under `notifications/` are only ignored when the request `id` is null/absent. If a client mistakenly includes an `id` for an unknown `notifications/*` method, the server currently replies with `-32601`, despite the documented contract that `notifications/*` never receive a response.

### Issue Context
- Built-in `notifications/initialized` correctly returns `null` (no response) even if an `id` is provided.
- Custom method dispatch treats `method.startsWith('notifications/')` as a notification regardless of id.
- The unknown-method fallback currently checks only `id == null`.

### Fix Focus Areas
- packages/plugins/mcp/src/protocol.ts[884-896]

Suggested change:
- In the unknown-method branch, change the suppression condition from `if (id == null)` to `if (method.startsWith('notifications/'))`.
- Keep the debug log, but ensure it logs and returns `null` for *any* unknown `notifications/*` method, even when an id is present.
- Add/adjust a unit test to cover `notifications/something-unknown` with an explicit `id` and assert no response.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 11, 2026

Copy link
Copy Markdown

PR Summary by Qodo

MCP: add custom JSON-RPC methods/capabilities with spec-correct notifications
✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

Walkthroughs

Description
• Add customMethods and customCapabilities to extend the MCP JSON-RPC surface.
• Dispatch built-ins via a registry and drop unknown notifications per JSON-RPC 2.0.
• Execute custom GraphQL operations through Yoga with forwarded headers and full pipeline.
Diagram
flowchart TD
  A["MCP client"] --> B["POST /mcp"] --> C["useMCP plugin"] --> D["JSON-RPC dispatch"]
  D --> E["Built-in methods"] --> H["Response / 204"]
  D --> F["Custom methods"] --> G["Yoga handle /graphql"] --> H
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use MCP tools (`tools/call`) instead of adding custom JSON-RPC methods
  • ➕ Avoids expanding the JSON-RPC method surface area
  • ➕ Reuses existing tool schemas/listing and execution formatting
  • ➖ Not all integrations map cleanly to tool semantics (especially non-tool capabilities/initialize advertising)
  • ➖ Harder to preserve native JSON-RPC error codes and notification behavior by method namespace
2. Adopt a generic JSON-RPC router/middleware library for dispatch
  • ➕ Less bespoke dispatch code; potentially more spec edge-cases covered out of the box
  • ➖ Adds a new dependency and integration surface
  • ➖ Still needs deep coupling for Yoga-backed execution and MCP-specific built-ins/notification rules
3. Expose an MCP dispatcher hook (middleware) instead of `customMethods` map
  • ➕ Allows cross-cutting behaviors (authz, metrics) around all MCP methods uniformly
  • ➖ More complex API design; harder to validate collisions and provide typed per-method context
  • ➖ Less discoverable configuration compared to explicit method registry

Recommendation: The PR’s approach (explicit customMethods + customCapabilities, with startup collision checks and a typed handler context) is the best fit: it keeps built-ins stable, makes extension intentional and auditable, and integrates safely with the gateway pipeline via Yoga.handle. The spec fix for unknown notifications and the added tests meaningfully reduce risk; alternatives either contort semantics (tools/call) or add dependency/API complexity without clear benefit.

Grey Divider

File Changes

Enhancement (4)
index.ts Export custom method handler types and MCPMethodError +7/-0

Export custom method handler types and MCPMethodError

• Re-exports 'MCPMethodError' plus the new public types ('MCPMethodHandler', 'MCPMethodContext', transport and operation types) from the package entrypoint.

packages/plugins/mcp/src/index.ts


method-handler.ts Introduce public custom method handler API types and MCPMethodError +67/-0

Introduce public custom method handler API types and MCPMethodError

• Defines the custom method handler interface, typed handler context (logger/method/id/schema access/transport), GraphQL operation input shape, and an 'MCPMethodError' used to emit JSON-RPC errors with specific codes and optional data.

packages/plugins/mcp/src/method-handler.ts


plugin.ts Wire custom method dispatch, Yoga-backed executeGraphQL, and startup validation +110/-2

Wire custom method dispatch, Yoga-backed executeGraphQL, and startup validation

• Adds 'customMethods'/'customCapabilities' to MCPConfig and passes them into handler options. Validates method collisions and handler types at startup, constructs a per-request dispatch context (transport + bound executor), and implements internal GraphQL execution via 'yoga.handle()' with forwarded headers and a guard against MCP path colliding with the GraphQL endpoint.

packages/plugins/mcp/src/plugin.ts


protocol.ts Refactor built-in method dispatch into registry and add custom dispatch path +580/-401

Refactor built-in method dispatch into registry and add custom dispatch path

• Replaces the built-in 'switch' with a map-based registry of handlers and exports 'builtInMethodNames' for collision checks. Adds custom method dispatch with typed context, 'MCPMethodError' conversion, capability merging into 'initialize', and spec-correct notification handling (drop unknown notifications with debug log; notification-named methods never respond even if an id is present).

packages/plugins/mcp/src/protocol.ts


Tests (2)
custom-methods.spec.ts Add unit + E2E coverage for custom methods, capabilities, and internal execution +613/-0

Add unit + E2E coverage for custom methods, capabilities, and internal execution

• Introduces comprehensive tests for custom dispatch behavior (result wrapping, context contents, error mapping, notification semantics, startup validation) and end-to-end gateway tests verifying full-pipeline GraphQL execution, header forwarding, capability advertisement, and clear errors for non-JSON internal responses.

packages/plugins/mcp/tests/custom-methods.spec.ts


protocol.spec.ts Add regression test for dropping unknown notification methods +16/-2

Add regression test for dropping unknown notification methods

• Extends protocol validation tests to assert unknown 'notifications/*' methods produce no wire response and emit a debug log, aligning behavior with JSON-RPC 2.0 notification rules.

packages/plugins/mcp/tests/protocol.spec.ts


Documentation (2)
mcp-custom-methods.md Add changeset for custom MCP methods/capabilities and notification fix +5/-0

Add changeset for custom MCP methods/capabilities and notification fix

• Introduces a minor changeset documenting 'customMethods', 'customCapabilities', 'MCPMethodError', and the spec-correct change to drop unknown notification methods.

.changeset/mcp-custom-methods.md


README.md Document customMethods/customCapabilities usage and handler semantics +38/-0

Document customMethods/customCapabilities usage and handler semantics

• Adds a new 'Custom methods' section with examples (including GraphQL execution) and clarifies result/error handling, header-forwarded pipeline execution, startup collision rules, and notification behavior.

packages/plugins/mcp/README.md


Grey Divider

Qodo Logo

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for customMethods and customCapabilities in the MCP plugin configuration, allowing users to register custom JSON-RPC methods and advertise them in the initialize response. Custom handlers receive a context that enables executing GraphQL operations through the full server pipeline with forwarded headers, accessing the schema, and retrieving transport details. Additionally, unknown notification methods are now silently ignored per the JSON-RPC 2.0 specification. The review feedback suggests improving robustness by stripping additional hop-by-hop headers (such as host and transfer-encoding) during internal GraphQL execution, and validating that customMethods and customCapabilities are plain objects at startup.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/plugins/mcp/src/plugin.ts
Comment thread packages/plugins/mcp/src/plugin.ts Outdated
Comment thread packages/plugins/mcp/src/protocol.ts
Review follow-ups:
- Guard custom method lookup with Object.hasOwn so prototype-chain
  names (constructor, toString) resolve to -32601 instead of being
  dispatched as handlers
- Drop unknown notifications/* methods even when an id is sent,
  matching the custom-method dispatch behavior
- Strip transport-mechanics headers (host, connection, keep-alive,
  transfer-encoding) from internal GraphQL execution requests
- Validate customMethods and customCapabilities are plain objects at
  startup, covering non-TypeScript config paths
@zensucht

Copy link
Copy Markdown
Author

Addressed the review findings in 3a14272:

  • Prototype method dispatch (Qodo): custom method lookup is now guarded with Object.hasOwn, so prototype-chain names like constructor or toString fall through to -32601 instead of resolving to inherited properties. Regression test covers constructor/toString/hasOwnProperty/__proto__.
  • Unknown notifications with an id (Qodo): the unknown-method fallthrough now suppresses by method-name prefix as well, consistent with the custom-method dispatch and the documented contract.
  • Hop-by-hop/host headers (Gemini): host, connection, keep-alive, and transfer-encoding are now stripped from internal execution requests alongside the existing content-length/accept-encoding — they describe the original request's transport, which is false for the synthetic internal request. Semantic headers (authorization, cookies) still flow, matching tools/call fidelity.
  • Config shape validation (Gemini): customMethods and customCapabilities are validated as plain objects at startup, covering YAML/JSON config paths that bypass TypeScript.

One finding not addressed here: the tools/call HTTP-layer path accepting id: null while the protocol layer rejects it is a real inconsistency, but it predates this PR (the validation allowing null is untouched by this change — the type widening just made it visible). Changing tools/call request-id semantics felt out of scope for an extensibility PR; happy to follow up separately if maintainers prefer it fixed here.

…rnal responses

- Strip the full RFC 7230 hop-by-hop set (proxy-authorization,
  proxy-authenticate, te, trailer, upgrade) from internal GraphQL
  execution requests
- Non-OK internal responses without GraphQL result shape (e.g. a
  401 JSON body from an auth plugin) now surface as errors instead
  of being returned as execution results; GraphQL-shaped error
  responses still pass through as data
@zensucht

Copy link
Copy Markdown
Author

Pushed 09ad6fa from a further hardening pass on this branch's internals:

  • Completed the RFC 7230 hop-by-hop header set stripped from internal GraphQL execution requests (proxy-authorization, proxy-authenticate, te, trailer, upgrade — joining the existing host/connection/keep-alive/transfer-encoding/content-length/accept-encoding). Semantic headers still pass through unchanged.
  • Non-OK internal responses without GraphQL result shape now surface as errors instead of being returned as execution results — e.g. an auth plugin short-circuiting with a 401 JSON body previously flowed back to the custom method as a pseudo-result with neither data nor errors. GraphQL-shaped error responses (errors present) still pass through as data per GraphQL-over-HTTP conventions. New e2e regression test covers the 401-JSON case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant