[DEV] Tool _webmcp_server-info: estado del servidor MCP

Muestra version, commit git, host, puerto, canales activos,
clientes conectados, registry (tools/prompts/resources),
uptime y requests pendientes. Solo modo dev.
This commit is contained in:
2026-02-13 01:19:18 -06:00
parent 6f3479b3b5
commit 35e5605b31
4 changed files with 182 additions and 5 deletions

View File

@@ -10784,7 +10784,7 @@ var wrapper_default = import_websocket.default;
// src/websocket-server.js
import { createServer } from "http";
import { parse as parse3 } from "url";
import { fork } from "child_process";
import { fork, execSync as execSync2 } from "child_process";
// node_modules/zod/v3/helpers/util.js
var util;
@@ -25197,6 +25197,31 @@ ${token}`
return { content: [{ type: "text", text: `Error: ${e.message}` }], isError: true };
}
}
if (request.params.name === "_webmcp_server-info") {
if (!CONFIG.dev) {
return { content: [{ type: "text", text: "server-info solo esta disponible en modo desarrollo (--dev)" }], isError: true };
}
if (!wsClient || wsClient.readyState !== wrapper_default.OPEN) {
return { content: [{ type: "text", text: "No hay conexion al servidor WebSocket" }], isError: true };
}
const requestId2 = (requestIdCounter++).toString();
const responsePromise2 = new Promise((resolve, reject) => {
pendingRequests.set(requestId2, { resolve, reject });
setTimeout(() => {
if (pendingRequests.has(requestId2)) {
pendingRequests.delete(requestId2);
reject(new Error("Timeout obteniendo info del servidor"));
}
}, 1e4);
});
try {
await sendMessage({ id: requestId2, type: "getServerInfo" });
const result = await responsePromise2;
return result;
} catch (e) {
return { content: [{ type: "text", text: `Error: ${e.message}` }], isError: true };
}
}
if (!wsClient || wsClient.readyState !== wrapper_default.OPEN) {
return {
content: [{
@@ -25288,6 +25313,14 @@ mcpServer.setRequestHandler(ListToolsRequestSchema, async () => {
todas: { type: "boolean", description: "Si es true, quita todas las herramientas" }
}
}
},
{
name: "_webmcp_server-info",
description: "[DEV] Muestra estado del servidor @nucleoriofrio/webmcp: version, commit, host, puerto, canales activos, clientes, registry de tools/prompts/resources, uptime y requests pendientes.",
inputSchema: {
type: "object",
properties: {}
}
}
);
}
@@ -25548,6 +25581,12 @@ function sendNotification(clientWs, channelPath, notificationType, data, mcpOnly
var toolsRegistry = {};
var promptsRegistry = {};
var resourcesRegistry = {};
var serverStartTime = Date.now();
var gitCommit = "unknown";
try {
gitCommit = execSync2("git rev-parse --short HEAD", { stdio: ["pipe", "pipe", "ignore"] }).toString().trim();
} catch (e) {
}
var requestIdCounter2 = 1;
var pendingRequests2 = {};
async function verifyClientToken(info, callback) {
@@ -25738,6 +25777,9 @@ wss.on("connection", (ws, req) => {
case "getClientInfo":
handleGetClientInfo(ws, clientChannel, data);
break;
case "getServerInfo":
handleGetServerInfo(ws, data);
break;
case "clearRegistry":
handleClearRegistry(ws, data);
break;
@@ -26123,6 +26165,45 @@ function handleGetClientInfo(ws, callerChannel, data) {
result: { content: [{ type: "text", text }] }
}));
}
function handleGetServerInfo(ws, data) {
const { id } = data;
const uptimeMs = Date.now() - serverStartTime;
const uptimeSec = Math.floor(uptimeMs / 1e3);
const hours = Math.floor(uptimeSec / 3600);
const minutes = Math.floor(uptimeSec % 3600 / 60);
const seconds = uptimeSec % 60;
const channelsList = {};
for (const [channelPath, channelClients] of Object.entries(channels)) {
channelsList[channelPath] = channelClients.size;
}
const info = {
server: `@nucleoriofrio/webmcp v0.2.0`,
commit: gitCommit,
host: HOST,
port: CONFIG.port,
dev: !!CONFIG.dev,
uptime: `${hours}h ${minutes}m ${seconds}s`,
uptimeMs,
channels: channelsList,
totalClients: Object.values(channels).reduce((sum, ch) => sum + ch.size, 0),
registry: {
tools: Object.keys(toolsRegistry).length,
prompts: Object.keys(promptsRegistry).length,
resources: Object.keys(resourcesRegistry).length
},
toolsList: Object.entries(toolsRegistry).map(([id2, info2]) => ({
id: id2,
name: info2.originalName,
channel: info2.channel
})),
pendingRequests: Object.keys(pendingRequests2).length
};
ws.send(JSON.stringify({
id,
type: "toolResponse",
result: { content: [{ type: "text", text: JSON.stringify(info, null, 2) }] }
}));
}
function handleClearRegistry(ws, data) {
const { id } = data;
let toolCount = Object.keys(toolsRegistry).length;

File diff suppressed because one or more lines are too long