Skip to content

normalizeHeaders references the bare global HeadersInit, breaking Node-only consumers with skipLibCheck: false #2568

Description

@mdi-odoo

Summary

shared/transport.d.ts references the bare global HeadersInit, which is a DOM lib type. Node-only consumers compiling with "skipLibCheck": false and no "DOM" in lib fail to build.

File/line: dist/esm/shared/transport.d.ts:7

export declare function normalizeHeaders(headers: HeadersInit | undefined): Record<string, string>;

Reproduction

@modelcontextprotocol/sdk@1.30.0 + @types/node@22.20.1, with "lib": ["ES2023"], "types": ["node"], "skipLibCheck": false:

node_modules/@modelcontextprotocol/sdk/dist/esm/shared/transport.d.ts(7,51):
  error TS2304: Cannot find name 'HeadersInit'.

Affects every published 1.x from 1.23.0-beta.0 through 1.30.0 (current latest).

Why @types/node cannot fix this

@types/node@22's fetch-globals shim (node_modules/@types/node/web-globals/fetch.d.ts) binds Headers, Request, RequestInit, Response and ResponseInit globally from undici-types — but deliberately not HeadersInit.

Per the review thread on DefinitelyTyped PR #74414 (@Renegade334): HeadersInit is a web-IDL typedef, which maps to a TypeScript type alias, and type aliases cannot be declaration-merged — unlike the dictionary/interface-shaped Headers/Request/RequestInit/Response, which can. So @types/node structurally cannot bind this global the way it binds the others.

That leaves the fix on the SDK side: don't reference the bare global.

Suggested fix

Change the signature to avoid the DOM-only global:

export declare function normalizeHeaders(headers: RequestInit['headers'] | undefined): Record<string, string>;

This is same-behaviour and depends only on a global @types/node does bind. It's also exactly what the v2 rewrite already does (#1279).

Blast radius is small: src/shared/transport.ts and its compiled output — 2 files.

Why a 1.x backport matters

The v2 rewrite already fixes this, but v2 is outside the peer range that @anthropic-ai/claude-agent-sdk pins (^1.29.0), so consumers coming through the Agent SDK can't upgrade to it today. Without a 1.x backport, the only options are a local ambient shim, adding "DOM" to lib (which drags every browser global into a Node service), or skipLibCheck: true (which stops type-checking all declaration files).

Happy to open a PR for the one-line change if that's useful.

Activity

  1. DiadkoShmek commented on Jul 31, 2026

    @DiadkoShmek

    Confirmed on current v1.x at 2d889f2 using a packed SDK artifact and a clean Node-only consumer (lib: ["ES2023"], types: ["node"], skipLibCheck: false).

    The baseline fails with the reported TS2304: Cannot find name 'HeadersInit'. Changing the source signature to RequestInit['headers'] | undefined makes the same packed-artifact consumer compile successfully.

    I also ran:

    • npm run build
    • npm run check
    • the full non-e2e suite: 1,639/1,639 tests passed

    The diff is one source line and does not change runtime behavior. I have the independently reviewed local commit ready and can open a focused PR against v1.x if maintainers want this backport.

  2. added
    bugSomething isn't working
    P2Moderate issues affecting some users, edge cases, potentially valuable feature
    ready for workEnough information for someone to start working on
    on Aug 17, 2026
  3. added
    v1Issues / PRs related to v1.x
    on Aug 18, 2026
  4. added a commit that references this issue on Sep 30, 2026
    88d7af0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Moderate issues affecting some users, edge cases, potentially valuable featurebugSomething isn't workingready for workEnough information for someone to start working onv1Issues / PRs related to v1.x

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions