drupal-mcp-connector 2.4.0 → 2.4.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,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.4.1] - 2026-08-14
11
+
12
+ ### Fixed
13
+ - **One unresolvable site no longer kills tool discovery (#187).** 2.4.0's
14
+ discovery gate resolved every configured site eagerly, so a deliberately
15
+ credential-less site — the inert break-glass tier keeps its Keychain item
16
+ absent by design — threw `requireSecureAuth` during `tools/list` and took
17
+ the whole tool surface down. Discovery now skips sites whose resolution
18
+ throws; execution against such a site still surfaces its own descriptive
19
+ error at call time, exactly as in 2.3.0.
20
+
10
21
  ## [2.4.0] - 2026-08-14
11
22
 
12
23
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drupal-mcp-connector",
3
- "version": "2.4.0",
3
+ "version": "2.4.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
@@ -31,12 +31,12 @@ import { createMcpHandler } from "@modelcontextprotocol/server";
31
31
  import { serveStdio } from "@modelcontextprotocol/server/stdio";
32
32
  import { toNodeHandler } from "@modelcontextprotocol/node";
33
33
 
34
- import { getSiteConfig, listSiteNames, getTlsConfig, CLIENT_VERSION } from "./lib/config.js";
34
+ import { listSiteNames, getTlsConfig, CLIENT_VERSION } from "./lib/config.js";
35
35
  import { makeBearerCheck } from "./lib/http-auth.js";
36
36
  import { createLegacySessionHandler, createMcpRequestHandler } from "./lib/http-handler.js";
37
37
  import { createConnectorServerFactory } from "./lib/mcp-server.js";
38
38
  import { createRateLimiter } from "./lib/rate-limit.js";
39
- import { callTool } from "./lib/dispatch.js";
39
+ import { callTool, listResolvableSiteConfigs } from "./lib/dispatch.js";
40
40
  import { filterDiscoverableTools } from "./lib/governance.js";
41
41
 
42
42
  // Tools — aggregated (single source of truth, side-effect-free) and per-tool prompts
@@ -236,7 +236,7 @@ const buildConnectorServer = createConnectorServerFactory({
236
236
  serverInfo: { name: "drupal-mcp-connector", version: CLIENT_VERSION },
237
237
  tools: {
238
238
  definitions: allDefinitions,
239
- list: () => filterDiscoverableTools(allDefinitions, listSiteNames().map((n) => getSiteConfig(n))),
239
+ list: () => filterDiscoverableTools(allDefinitions, listResolvableSiteConfigs()),
240
240
  call: callTool,
241
241
  },
242
242
  resources: { definitions: RESOURCES, read: readResource },
@@ -8,7 +8,7 @@
8
8
  * this module is denial on every path, with no ungoverned fallback below it.
9
9
  */
10
10
 
11
- import { getSiteConfig } from "./config.js";
11
+ import { getSiteConfig, listSiteNames } from "./config.js";
12
12
  import { resolveSecurityConfig, assertNotReadOnly,
13
13
  assertDestructiveAllowed, assertGraphqlMutationAllowed,
14
14
  SecurityError } from "./security.js";
@@ -18,6 +18,26 @@ import { inferOperation } from "./operations.js";
18
18
  import { assertSourceGovernance, GovernanceError, GOVERNANCE_DIAGNOSTIC_TOOLS } from "./governance.js";
19
19
  import { allHandlers } from "../tools/index.js";
20
20
 
21
+ /**
22
+ * Resolve every configured site that CAN resolve, skipping the ones that
23
+ * throw. A site can legitimately be unresolvable on purpose — the break-glass
24
+ * tier keeps its credential absent to stay inert — and discovery must treat
25
+ * such a site as simply unable to serve tools, never let it kill tools/list
26
+ * for everyone (the 2.4.0 regression). Execution against an unresolvable
27
+ * site still surfaces its own descriptive error at call time.
28
+ *
29
+ * @returns {Array<object>} Resolved site configs.
30
+ */
31
+ export function listResolvableSiteConfigs() {
32
+ return listSiteNames().flatMap((name) => {
33
+ try {
34
+ return [getSiteConfig(name)];
35
+ } catch {
36
+ return [];
37
+ }
38
+ });
39
+ }
40
+
21
41
  /**
22
42
  * Derive the entity type a tool acts on, for destructive-allow assertions.
23
43
  *