@arabold/docs-mcp-server 1.31.1 → 1.32.0

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/dist/index.js CHANGED
@@ -10056,6 +10056,8 @@ async function registerMcpService(server, docService, pipeline, readOnly = false
10056
10056
  const mcpServer = createMcpServerInstance(mcpTools, readOnly);
10057
10057
  const authMiddleware = authManager ? createAuthMiddleware(authManager) : null;
10058
10058
  const sseTransports = {};
10059
+ const heartbeatIntervals = {};
10060
+ const HEARTBEAT_INTERVAL_MS = 3e4;
10059
10061
  server.route({
10060
10062
  method: "GET",
10061
10063
  url: "/sse",
@@ -10067,12 +10069,31 @@ async function registerMcpService(server, docService, pipeline, readOnly = false
10067
10069
  if (telemetry.isEnabled()) {
10068
10070
  logger.info(`🔗 MCP client connected: ${transport.sessionId}`);
10069
10071
  }
10070
- reply.raw.on("close", () => {
10072
+ const heartbeatInterval = setInterval(() => {
10073
+ try {
10074
+ reply.raw.write(": heartbeat\n\n");
10075
+ } catch {
10076
+ clearInterval(heartbeatInterval);
10077
+ delete heartbeatIntervals[transport.sessionId];
10078
+ }
10079
+ }, HEARTBEAT_INTERVAL_MS);
10080
+ heartbeatIntervals[transport.sessionId] = heartbeatInterval;
10081
+ const cleanupConnection = () => {
10082
+ const interval = heartbeatIntervals[transport.sessionId];
10083
+ if (interval) {
10084
+ clearInterval(interval);
10085
+ delete heartbeatIntervals[transport.sessionId];
10086
+ }
10071
10087
  delete sseTransports[transport.sessionId];
10072
10088
  transport.close();
10073
10089
  if (telemetry.isEnabled()) {
10074
10090
  logger.info(`🔗 MCP client disconnected: ${transport.sessionId}`);
10075
10091
  }
10092
+ };
10093
+ reply.raw.on("close", cleanupConnection);
10094
+ reply.raw.on("error", (error) => {
10095
+ logger.debug(`SSE connection error: ${error}`);
10096
+ cleanupConnection();
10076
10097
  });
10077
10098
  await mcpServer.connect(transport);
10078
10099
  } catch (error) {
@@ -10114,10 +10135,15 @@ async function registerMcpService(server, docService, pipeline, readOnly = false
10114
10135
  const requestTransport = new StreamableHTTPServerTransport({
10115
10136
  sessionIdGenerator: void 0
10116
10137
  });
10117
- reply.raw.on("close", () => {
10138
+ const cleanupRequest = () => {
10118
10139
  logger.debug("Streamable HTTP request closed");
10119
10140
  requestTransport.close();
10120
10141
  requestServer.close();
10142
+ };
10143
+ reply.raw.on("close", cleanupRequest);
10144
+ reply.raw.on("error", (error) => {
10145
+ logger.debug(`Streamable HTTP connection error: ${error}`);
10146
+ cleanupRequest();
10121
10147
  });
10122
10148
  await requestServer.connect(requestTransport);
10123
10149
  await requestTransport.handleRequest(request.raw, reply.raw, request.body);
@@ -10130,10 +10156,17 @@ async function registerMcpService(server, docService, pipeline, readOnly = false
10130
10156
  }
10131
10157
  });
10132
10158
  mcpServer._sseTransports = sseTransports;
10159
+ mcpServer._heartbeatIntervals = heartbeatIntervals;
10133
10160
  return mcpServer;
10134
10161
  }
10135
10162
  async function cleanupMcpService(mcpServer) {
10136
10163
  try {
10164
+ const heartbeatIntervals = mcpServer._heartbeatIntervals;
10165
+ if (heartbeatIntervals) {
10166
+ for (const interval of Object.values(heartbeatIntervals)) {
10167
+ clearInterval(interval);
10168
+ }
10169
+ }
10137
10170
  const sseTransports = mcpServer._sseTransports;
10138
10171
  if (sseTransports) {
10139
10172
  for (const transport of Object.values(sseTransports)) {
@@ -10737,7 +10770,7 @@ const Layout = ({
10737
10770
  children,
10738
10771
  eventClientConfig
10739
10772
  }) => {
10740
- const versionString = version || "1.31.1";
10773
+ const versionString = version || "1.32.0";
10741
10774
  const versionInitializer = `versionUpdate({ currentVersion: ${`'${versionString}'`} })`;
10742
10775
  return /* @__PURE__ */ jsxs("html", { lang: "en", children: [
10743
10776
  /* @__PURE__ */ jsxs("head", { children: [
@@ -13049,7 +13082,7 @@ class AppServer {
13049
13082
  try {
13050
13083
  if (telemetry.isEnabled()) {
13051
13084
  telemetry.setGlobalContext({
13052
- appVersion: "1.31.1",
13085
+ appVersion: "1.32.0",
13053
13086
  appPlatform: process.platform,
13054
13087
  appNodeVersion: process.version,
13055
13088
  appServicesEnabled: this.getActiveServicesList(),
@@ -16536,7 +16569,7 @@ function createCliProgram() {
16536
16569
  const commandStartTimes = /* @__PURE__ */ new Map();
16537
16570
  let globalEventBus = null;
16538
16571
  let globalTelemetryService = null;
16539
- program.name("docs-mcp-server").description("Unified CLI, MCP Server, and Web Interface for Docs MCP Server.").version("1.31.1").addOption(
16572
+ program.name("docs-mcp-server").description("Unified CLI, MCP Server, and Web Interface for Docs MCP Server.").version("1.32.0").addOption(
16540
16573
  new Option("--verbose", "Enable verbose (debug) logging").conflicts("silent")
16541
16574
  ).addOption(new Option("--silent", "Disable all logging except errors")).addOption(
16542
16575
  new Option("--telemetry", "Enable telemetry collection").env("DOCS_MCP_TELEMETRY").argParser((value) => {
@@ -16570,7 +16603,7 @@ function createCliProgram() {
16570
16603
  if (shouldEnableTelemetry()) {
16571
16604
  if (telemetry.isEnabled()) {
16572
16605
  telemetry.setGlobalContext({
16573
- appVersion: "1.31.1",
16606
+ appVersion: "1.32.0",
16574
16607
  appPlatform: process.platform,
16575
16608
  appNodeVersion: process.version,
16576
16609
  appInterface: "cli",