npmplus-mcp-server
Version:
Production-ready MCP server for intelligent JavaScript package management. Works with Claude, Windsurf, Cursor, VS Code, and any MCP-compatible AI editor.
165 lines • 7.99 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.createServer = createServer;
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const analytics_js_1 = require("./analytics.js");
const constants_js_1 = require("./constants.js");
const schema_converter_js_1 = require("./utils/schema-converter.js");
// Import tool modules that export their tool definitions and handlers
const searchTools = __importStar(require("./tools/search-tools.js"));
const installTools = __importStar(require("./tools/install-tools.js"));
const securityTools = __importStar(require("./tools/security-tools.js"));
const analysisTools = __importStar(require("./tools/analysis-tools.js"));
const managementTools = __importStar(require("./tools/management-tools.js"));
async function createServer() {
// Debug logging to stderr instead of stdout
console.error(`[npmplus-mcp] Server starting with version ${constants_js_1.VERSION} at ${new Date().toISOString()}`);
console.error(`[npmplus-mcp] Current working directory: ${process.cwd()}`);
console.error(`[npmplus-mcp] Node version: ${process.version}`);
console.error(`[npmplus-mcp] Platform: ${process.platform}`);
const server = new index_js_1.Server({
name: constants_js_1.SERVER_NAME,
version: constants_js_1.VERSION
}, {
capabilities: {
tools: {}
}
});
// Aggregate all tools
const allTools = [
...searchTools.tools,
...installTools.tools,
...securityTools.tools,
...analysisTools.tools,
...managementTools.tools
];
// Create a map of tool handlers
const toolHandlers = new Map([
...searchTools.handlers,
...installTools.handlers,
...securityTools.handlers,
...analysisTools.handlers,
...managementTools.handlers
]);
// Register unified tools/list handler
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async (request) => {
const parsed = types_js_1.ListToolsRequestSchema.safeParse(request);
if (!parsed.success) {
throw new Error(`Invalid request: ${parsed.error}`);
}
// Debug logging to stderr
console.error(`[npmplus-mcp] ListToolsRequest received at ${new Date().toISOString()}`);
console.error(`[npmplus-mcp] Returning ${allTools.length} tools`);
return {
tools: allTools.map(tool => (0, schema_converter_js_1.convertToolSchema)(tool))
};
});
// Register unified tools/call handler
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
const parsed = types_js_1.CallToolRequestSchema.safeParse(request);
if (!parsed.success) {
throw new Error(`Invalid request: ${parsed.error}`);
}
const { name, arguments: args } = parsed.data.params;
// Debug logging to stderr
console.error(`\n[npmplus-mcp v${constants_js_1.VERSION}] ========== Tool Call ==========`);
console.error(`[npmplus-mcp] Tool: ${name}`);
console.error(`[npmplus-mcp] Time: ${new Date().toISOString()}`);
console.error(`[npmplus-mcp] Raw args:`, JSON.stringify(args, null, 2));
const handler = toolHandlers.get(name);
if (!handler) {
console.error(`[npmplus-mcp] ERROR: Unknown tool: ${name}`);
throw new Error(`Unknown tool: ${name}`);
}
const startTime = Date.now();
try {
// MCP Workaround: Fix cwd parameter that gets transformed from "." to "/"
let fixedArgs = args;
if (args && typeof args === 'object' && 'cwd' in args) {
// Debug logging to stderr
console.error(`[npmplus-mcp] CWD Detection:`);
console.error(`[npmplus-mcp] - Found cwd parameter: "${args.cwd}"`);
console.error(`[npmplus-mcp] - Current process.cwd(): "${process.cwd()}"`);
console.error(`[npmplus-mcp] - Type of cwd: ${typeof args.cwd}`);
// UPDATED FIX: Always convert '/' to '.' since users never mean root
if (args.cwd === '/') {
console.error(`[npmplus-mcp] ✅ APPLYING FIX: Converting "/" to "."`);
fixedArgs = { ...args, cwd: '.' };
console.error(`[npmplus-mcp] Fixed args:`, JSON.stringify(fixedArgs, null, 2));
}
else if (args.cwd === '') {
// Empty string should also be treated as current directory
console.error(`[npmplus-mcp] ✅ APPLYING FIX: Converting empty string to "."`);
fixedArgs = { ...args, cwd: '.' };
console.error(`[npmplus-mcp] Fixed args:`, JSON.stringify(fixedArgs, null, 2));
}
else {
console.error(`[npmplus-mcp] ℹ️ No fix needed for cwd: "${args.cwd}"`);
}
}
else {
console.error(`[npmplus-mcp] ℹ️ No cwd parameter found in args`);
}
console.error(`[npmplus-mcp] Calling handler for ${name}...`);
const result = await handler(fixedArgs);
const responseTime = Date.now() - startTime;
// Log successful completion to stderr
console.error(`[npmplus-mcp] ✅ Tool ${name} completed successfully in ${responseTime}ms`);
console.error(`[npmplus-mcp] ==============================\n`);
// Track successful tool usage
analytics_js_1.analytics.trackToolUsage(name, true, responseTime);
return result;
}
catch (error) {
const responseTime = Date.now() - startTime;
// Log error details to stderr
console.error(`[npmplus-mcp] ❌ Tool ${name} failed after ${responseTime}ms`);
console.error(`[npmplus-mcp] Error:`, error.message);
console.error(`[npmplus-mcp] Stack:`, error.stack);
console.error(`[npmplus-mcp] ==============================\n`);
// Track failed tool usage
analytics_js_1.analytics.trackToolUsage(name, false, responseTime, undefined, undefined, error);
if (error.name === "ZodError") {
throw new Error(`Invalid arguments: ${error.message}`);
}
throw error;
}
});
console.error(`[npmplus-mcp] Server initialization complete`);
return server;
}
//# sourceMappingURL=server.js.map