drupal-mcp-connector 2.10.0 → 2.10.1

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/CHANGELOG.md CHANGED
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.10.1] - 2026-08-28
11
+
12
+ ### Fixed
13
+ - **Node reads include the numeric Drupal node ID (#237).** JSON:API-backed
14
+ `drupal_get_node` and `drupal_entity_get` results retain
15
+ `fields.drupal_internal__nid`, matching schema discovery while preserving
16
+ entity allowlists and configured field redaction. The canonical top-level
17
+ `id` remains the UUID.
18
+
19
+ ### Deprecated
20
+ - **Loopback `shared_bearer` inbound auth (#231).** Startup warns when
21
+ `resolveInboundAuthMode` is `shared_bearer`, naming removal in v3.0.0.
22
+ Resource-server mode is silent. `npm run verify` lists the residual.
23
+ This is the deprecation half only; removal waits for the next major.
24
+
10
25
  ## [2.10.0] - 2026-08-27
11
26
 
12
27
  ### Security
@@ -1314,6 +1329,7 @@ The connector is now **dual-protocol**: every tool runs against an abstract back
1314
1329
  - User tools gained explicit PII-access assertions.
1315
1330
  - Whole tree lint-clean (`npm run lint`) with object-injection sinks rewritten to safe lookups.
1316
1331
 
1332
+ [2.10.1]: https://github.com/Wilkes-Liberty/drupal-mcp-connector/releases/tag/v2.10.1
1317
1333
  [1.0.0]: https://github.com/Wilkes-Liberty/drupal-mcp-connector/releases/tag/v1.0.0
1318
1334
  [0.10.0]: https://github.com/Wilkes-Liberty/drupal-mcp-connector/releases/tag/v0.10.0
1319
1335
  [0.9.1]: https://github.com/Wilkes-Liberty/drupal-mcp-connector/releases/tag/v0.9.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drupal-mcp-connector",
3
- "version": "2.10.0",
3
+ "version": "2.10.1",
4
4
  "description": "A secure, multi-site Model Context Protocol (MCP) connector for Drupal — dual-protocol JSON:API and GraphQL.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -39,6 +39,7 @@ import {
39
39
  makeBearerCheck,
40
40
  resolveInboundAuthConfig,
41
41
  resolveInboundAuthMode,
42
+ inboundAuthDeprecationWarning,
42
43
  createInboundHttpsAuth,
43
44
  } from "./lib/http-auth.js";
44
45
  import { createLegacySessionHandler, createMcpRequestHandler } from "./lib/http-handler.js";
@@ -404,6 +405,8 @@ if (transport === "stdio") {
404
405
  console.error(`[drupal-mcp-connector] FATAL: ${inboundMode.reason}`);
405
406
  process.exit(1);
406
407
  }
408
+ const deprecation = inboundAuthDeprecationWarning(inboundMode.mode);
409
+ if (deprecation) console.error(deprecation);
407
410
 
408
411
  let checkAuth = makeBearerCheck(inboundMode.mode === "shared_bearer" ? authToken : "");
409
412
  let authenticate = null;
@@ -17,8 +17,9 @@ import {
17
17
  BASE_ATTRIBUTE_FIELDS,
18
18
  } from "../canonical.js";
19
19
 
20
- // Drupal exposes internal numeric ids under drupal_internal__* attributes;
21
- // these are dropped from canonical `fields` (the canonical id is the UUID).
20
+ // Drupal exposes internal identifiers under drupal_internal__* attributes.
21
+ // They are dropped from canonical `fields` except for the identifiers that
22
+ // governed read/write workflows explicitly need.
22
23
  const INTERNAL_ATTR_RE = /^drupal_internal__/;
23
24
 
24
25
  // countEntities() pagination. Drupal core JSON:API returns no total in `meta`,
@@ -194,8 +195,9 @@ export class JsonApiBackend extends Backend {
194
195
 
195
196
  /**
196
197
  * Convert a JSON:API resource object into a CanonicalEntity. Base attributes
197
- * (title/status/...) are promoted; drupal_internal__* and base fields are
198
- * stripped from `fields`; relationships are normalized to canonical refs.
198
+ * (title/status/...) are promoted; base fields and unneeded
199
+ * drupal_internal__* attributes are stripped from `fields`; relationships
200
+ * are normalized to canonical refs.
199
201
  * @param {object} resource A JSON:API resource object.
200
202
  * @returns {import("../canonical.js").CanonicalEntity}
201
203
  */
@@ -208,10 +210,13 @@ export class JsonApiBackend extends Backend {
208
210
  Object.entries(attrs).filter(([k]) => {
209
211
  if (BASE_ATTRIBUTE_FIELDS.includes(k)) return false;
210
212
  if (INTERNAL_ATTR_RE.test(k)) {
213
+ // Node reads expose the numeric nid advertised by schema discovery
214
+ // while the UUID remains the canonical top-level id (#237).
211
215
  // Paragraph ERR attach needs the current revision id (#192).
212
216
  // Node / revisionable writes need the working vs live vid (#166).
213
217
  // Other drupal_internal__* attributes stay stripped.
214
- return k === "drupal_internal__vid"
218
+ return (entityType === "node" && k === "drupal_internal__nid")
219
+ || k === "drupal_internal__vid"
215
220
  || (entityType === "paragraph" && k === "drupal_internal__revision_id");
216
221
  }
217
222
  return true;
@@ -479,6 +479,26 @@ export function resolveInboundAuthMode({
479
479
  };
480
480
  }
481
481
 
482
+ /**
483
+ * Startup deprecation warning for inbound auth mode `shared_bearer` (#231).
484
+ *
485
+ * Removal is the next major (v3.0.0). Resource-server and unauthenticated
486
+ * modes are silent. The warning names the issue and the removal version so
487
+ * a loopback install cannot miss the kill criterion.
488
+ *
489
+ * @param {string} mode
490
+ * @returns {?string} Warning text, or null when this mode is not deprecated.
491
+ */
492
+ export function inboundAuthDeprecationWarning(mode) {
493
+ if (mode !== "shared_bearer") return null;
494
+ return (
495
+ "[drupal-mcp-connector] WARNING: inbound auth mode shared_bearer is deprecated " +
496
+ "and will be removed in v3.0.0 (#231). Configure an OAuth resource server " +
497
+ "(auth.issuer + auth.audience) or run unauthenticated loopback. " +
498
+ "MCP_ALLOW_UNAUTHENTICATED remains the explicit trusted-proxy opt-in."
499
+ );
500
+ }
501
+
482
502
  /**
483
503
  * Merge config.auth with environment overrides.
484
504
  * @param {object} [cfg]
package/src/lib/verify.js CHANGED
@@ -75,6 +75,16 @@ export const RESIDUALS = [
75
75
  "responsibility; the connector reads secrets from the environment and never " +
76
76
  "stores them.",
77
77
  },
78
+ {
79
+ id: "loopback_shared_bearer",
80
+ status: "managed",
81
+ detail:
82
+ "Loopback MCP_AUTH_TOKEN (inbound mode shared_bearer) still ships. It is " +
83
+ "deprecated as of this release and will be removed in v3.0.0 (#231). " +
84
+ "Network-facing product paths already refuse it. MCP_ALLOW_UNAUTHENTICATED " +
85
+ "is a separate named residual: an explicit trusted-proxy opt-in, not a " +
86
+ "shared credential, and is not retired by #231.",
87
+ },
78
88
  ];
79
89
 
80
90
  /** Hostname suffixes reserved for documentation and testing (RFC 2606/6761). */