jaegis-npm-mcp-server
Version:
NPM Package Management MCP Server for JAEGIS-web-os project with 8 specialized tools
613 lines (604 loc) ⢠25 kB
JavaScript
#!/usr/bin/env node
"use strict";
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 });
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const dotenv = __importStar(require("dotenv"));
// Using built-in fetch (Node.js 18+) for better compatibility
// Load environment variables
dotenv.config();
// Command line argument parsing
const args = process.argv.slice(2);
const hasListTools = args.includes('--list-tools');
const hasToolsJson = args.includes('--tools-json');
const hasHelp = args.includes('--help') || args.includes('-h');
const formatTable = args.includes('--format=table');
// Security: Credential sanitization
function sanitizeCredential(value) {
if (!value || value.length < 8)
return '****';
return `${value.substring(0, 4)}****...****${value.substring(value.length - 4)}`;
}
function sanitizeEnvVars(env) {
const sensitiveKeys = ['TOKEN', 'KEY', 'SECRET', 'PASSWORD', 'API_'];
const sanitized = { ...env };
Object.keys(sanitized).forEach(key => {
if (sensitiveKeys.some(sensitive => key.toUpperCase().includes(sensitive))) {
sanitized[key] = sanitizeCredential(sanitized[key]);
}
});
return sanitized;
}
function showHelp() {
console.log(`
NPM JAEGIS MCP Server v1.0.0 - NPM package management with 8 specialized tools
USAGE:
npm-mcp-server [OPTIONS]
OPTIONS:
--list-tools List all available tools with descriptions
--tools-json Output complete MCP tools schema as JSON
--format=table Use table format for tool listings (default: JSON)
--help, -h Show this help message
ENVIRONMENT VARIABLES:
NPM_TOKEN NPM access token (required)
Format: npm_*
Generate at: https://www.npmjs.com/settings/tokens
NPM_USERNAME NPM username (required)
NPM_EMAIL NPM email (required)
NPM_REGISTRY NPM registry URL (optional, default: https://registry.npmjs.org/)
DEFAULT_PACKAGE Default package name (optional, default: JAEGIS-web-os)
EXAMPLES:
# List all tools in table format
npm-mcp-server --list-tools --format=table
# Get tools schema for MCP client integration
npm-mcp-server --tools-json
# Start the MCP server (default)
npm-mcp-server
QUICK SETUP:
1. Generate NPM token: https://www.npmjs.com/settings/tokens
2. Set environment variables:
export NPM_TOKEN=npm_your_token_here
export NPM_USERNAME=your_username
export NPM_EMAIL=your_email@example.com
3. Run: npm-mcp-server
For detailed documentation, see: README.md
`);
}
function getToolsInfo() {
return [
{
name: 'npm_package_info',
category: 'Package Information',
description: 'Get detailed information about an NPM package including metadata and dependencies',
requiredParams: ['package_name'],
optionalParams: ['version'],
inputSchema: { type: 'object', properties: { package_name: { type: 'string' } } }
},
{
name: 'npm_search_packages',
category: 'Package Discovery',
description: 'Search for NPM packages using keywords and filters',
requiredParams: ['query'],
optionalParams: ['limit'],
inputSchema: { type: 'object', properties: { query: { type: 'string' } } }
},
{
name: 'npm_publish_package',
category: 'Package Publishing',
description: 'Publish a package to NPM registry with specified configuration',
requiredParams: ['package_path'],
optionalParams: ['tag', 'access'],
inputSchema: { type: 'object', properties: { package_path: { type: 'string' } } }
},
{
name: 'npm_unpublish_package',
category: 'Package Management',
description: 'Unpublish a package version from NPM registry (irreversible)',
requiredParams: ['package_name'],
optionalParams: ['version'],
inputSchema: { type: 'object', properties: { package_name: { type: 'string' } } }
},
{
name: 'npm_deprecate_package',
category: 'Package Management',
description: 'Deprecate a package version with a custom message',
requiredParams: ['package_name', 'version', 'message'],
optionalParams: [],
inputSchema: { type: 'object', properties: { package_name: { type: 'string' }, version: { type: 'string' }, message: { type: 'string' } } }
},
{
name: 'npm_list_versions',
category: 'Package Information',
description: 'List all available versions of a package with release information',
requiredParams: ['package_name'],
optionalParams: [],
inputSchema: { type: 'object', properties: { package_name: { type: 'string' } } }
},
{
name: 'npm_download_stats',
category: 'Package Analytics',
description: 'Get download statistics and analytics for a package',
requiredParams: ['package_name'],
optionalParams: ['period'],
inputSchema: { type: 'object', properties: { package_name: { type: 'string' } } }
},
{
name: 'npm_validate_package',
category: 'Package Validation',
description: 'Validate package.json and check for publishing readiness',
requiredParams: ['package_path'],
optionalParams: [],
inputSchema: { type: 'object', properties: { package_path: { type: 'string' } } }
}
];
}
function displayToolsTable(tools) {
console.log('\nš¦ NPM JAEGIS MCP Server - Tool Inventory\n');
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāā¬āāāāāāāāāāā');
console.log('ā Tool Name ā Category ā Required ā Optional ā');
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāā¼āāāāāāāāāāā¤');
tools.forEach(tool => {
const name = tool.name.padEnd(35);
const category = tool.category.padEnd(32);
const required = tool.requiredParams.length.toString().padEnd(8);
const optional = tool.optionalParams.length.toString().padEnd(8);
console.log(`ā ${name} ā ${category} ā ${required} ā ${optional} ā`);
});
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāā“āāāāāāāāāāā');
// Summary by category
const categories = tools.reduce((acc, tool) => {
acc[tool.category] = (acc[tool.category] || 0) + 1;
return acc;
}, {});
console.log('\nš Tool Summary by Category:');
Object.entries(categories).forEach(([category, count]) => {
console.log(` ⢠${category}: ${count} tools`);
});
console.log(`\nšÆ Total: ${tools.length} tools available\n`);
}
function displayToolsJson(tools, includeSchema = false) {
const output = {
server: 'npm-jaegis-mcp-server',
version: '1.0.0',
totalTools: tools.length,
categories: tools.reduce((acc, tool) => {
acc[tool.category] = (acc[tool.category] || 0) + 1;
return acc;
}, {}),
tools: tools.map(tool => ({
name: tool.name,
category: tool.category,
description: tool.description,
parameters: {
required: tool.requiredParams,
optional: tool.optionalParams,
total: tool.requiredParams.length + tool.optionalParams.length
},
...(includeSchema && { inputSchema: tool.inputSchema })
}))
};
console.log(JSON.stringify(output, null, 2));
}
// Handle command line arguments before server initialization
if (hasHelp) {
showHelp();
process.exit(0);
}
if (hasListTools || hasToolsJson) {
const tools = getToolsInfo();
if (hasToolsJson) {
displayToolsJson(tools, true);
}
else if (formatTable) {
displayToolsTable(tools);
}
else {
displayToolsJson(tools, false);
}
process.exit(0);
}
class NPMJAEGISMCPServer {
server;
config;
constructor() {
this.config = this.loadConfig();
this.validateConfiguration();
this.server = new index_js_1.Server({
name: 'npm-jaegis-mcp-server',
version: '1.0.0',
}, {
capabilities: {
tools: {},
},
});
this.setupToolHandlers();
this.setupErrorHandling();
}
loadConfig() {
const token = process.env.NPM_TOKEN;
const username = process.env.NPM_USERNAME;
const email = process.env.NPM_EMAIL;
if (!token) {
throw new Error(`NPM token is required. Please set NPM_TOKEN environment variable.
Generate a token at: https://www.npmjs.com/settings/tokens`);
}
if (!username) {
throw new Error('NPM username is required. Please set NPM_USERNAME environment variable.');
}
if (!email) {
throw new Error('NPM email is required. Please set NPM_EMAIL environment variable.');
}
return {
token,
username,
email,
registry: process.env.NPM_REGISTRY || 'https://registry.npmjs.org/',
scope: process.env.NPM_SCOPE,
defaultPackage: process.env.DEFAULT_PACKAGE || 'JAEGIS-web-os'
};
}
validateConfiguration() {
if (!this.config.token.startsWith('npm_')) {
console.warn('Warning: NPM token format may be invalid. Expected format: npm_*');
}
console.log(`NPM MCP Server configured for user: ${this.config.username}`);
console.log(`Registry: ${this.config.registry}`);
console.log(`Default package: ${this.config.defaultPackage}`);
}
setupToolHandlers() {
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'npm_package_info',
description: 'Get detailed information about an NPM package',
inputSchema: {
type: 'object',
properties: {
package_name: {
type: 'string',
description: 'Name of the NPM package'
},
version: {
type: 'string',
description: 'Specific version (optional, defaults to latest)'
}
},
required: ['package_name']
}
},
{
name: 'npm_search_packages',
description: 'Search for NPM packages',
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Search query'
},
limit: {
type: 'number',
description: 'Maximum number of results (default: 20)'
}
},
required: ['query']
}
},
{
name: 'npm_publish_package',
description: 'Publish a package to NPM registry',
inputSchema: {
type: 'object',
properties: {
package_path: {
type: 'string',
description: 'Path to package directory containing package.json'
},
tag: {
type: 'string',
description: 'Distribution tag (default: latest)'
},
access: {
type: 'string',
enum: ['public', 'restricted'],
description: 'Package access level (default: public)'
}
},
required: ['package_path']
}
},
{
name: 'npm_unpublish_package',
description: 'Unpublish a package version from NPM',
inputSchema: {
type: 'object',
properties: {
package_name: {
type: 'string',
description: 'Name of the package to unpublish'
},
version: {
type: 'string',
description: 'Specific version to unpublish (optional, unpublishes entire package if not specified)'
}
},
required: ['package_name']
}
},
{
name: 'npm_deprecate_package',
description: 'Deprecate a package version',
inputSchema: {
type: 'object',
properties: {
package_name: {
type: 'string',
description: 'Name of the package'
},
version: {
type: 'string',
description: 'Version range to deprecate'
},
message: {
type: 'string',
description: 'Deprecation message'
}
},
required: ['package_name', 'version', 'message']
}
},
{
name: 'npm_list_versions',
description: 'List all versions of a package',
inputSchema: {
type: 'object',
properties: {
package_name: {
type: 'string',
description: 'Name of the package'
}
},
required: ['package_name']
}
},
{
name: 'npm_download_stats',
description: 'Get download statistics for a package',
inputSchema: {
type: 'object',
properties: {
package_name: {
type: 'string',
description: 'Name of the package'
},
period: {
type: 'string',
enum: ['last-day', 'last-week', 'last-month', 'last-year'],
description: 'Time period for stats (default: last-month)'
}
},
required: ['package_name']
}
},
{
name: 'npm_validate_package',
description: 'Validate package.json and check for publishing readiness',
inputSchema: {
type: 'object',
properties: {
package_path: {
type: 'string',
description: 'Path to package directory'
}
},
required: ['package_path']
}
}
]
};
});
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'npm_package_info':
return await this.getPackageInfo(args);
case 'npm_search_packages':
return await this.searchPackages(args);
case 'npm_publish_package':
return await this.publishPackage(args);
case 'npm_unpublish_package':
return await this.unpublishPackage(args);
case 'npm_deprecate_package':
return await this.deprecatePackage(args);
case 'npm_list_versions':
return await this.listVersions(args);
case 'npm_download_stats':
return await this.getDownloadStats(args);
case 'npm_validate_package':
return await this.validatePackage(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
}
catch (error) {
return {
content: [
{
type: 'text',
text: JSON.stringify({
error: error instanceof Error ? error.message : String(error),
success: false
}, null, 2)
}
]
};
}
});
}
setupErrorHandling() {
this.server.onerror = (error) => {
console.error('[NPM MCP Server Error]', error);
};
process.on('SIGINT', async () => {
await this.server.close();
process.exit(0);
});
}
// Tool implementations will be added in the next part
async getPackageInfo(args) {
// Implementation placeholder
return {
content: [
{
type: 'text',
text: 'Package info functionality will be implemented'
}
]
};
}
async searchPackages(args) {
// Implementation placeholder
return {
content: [
{
type: 'text',
text: 'Search packages functionality will be implemented'
}
]
};
}
async publishPackage(args) {
// Implementation placeholder
return {
content: [
{
type: 'text',
text: 'Publish package functionality will be implemented'
}
]
};
}
async unpublishPackage(args) {
// Implementation placeholder
return {
content: [
{
type: 'text',
text: 'Unpublish package functionality will be implemented'
}
]
};
}
async deprecatePackage(args) {
// Implementation placeholder
return {
content: [
{
type: 'text',
text: 'Deprecate package functionality will be implemented'
}
]
};
}
async listVersions(args) {
// Implementation placeholder
return {
content: [
{
type: 'text',
text: 'List versions functionality will be implemented'
}
]
};
}
async getDownloadStats(args) {
// Implementation placeholder
return {
content: [
{
type: 'text',
text: 'Download stats functionality will be implemented'
}
]
};
}
async validatePackage(args) {
// Implementation placeholder
return {
content: [
{
type: 'text',
text: 'Validate package functionality will be implemented'
}
]
};
}
async run() {
const transport = new stdio_js_1.StdioServerTransport();
await this.server.connect(transport);
// Display startup summary
const tools = getToolsInfo();
const categories = tools.reduce((acc, tool) => {
acc[tool.category] = (acc[tool.category] || 0) + 1;
return acc;
}, {});
console.error('š¦ NPM JAEGIS MCP Server (v1.0.0) running on stdio');
console.error(`š Total Tools: ${tools.length} | Categories: ${Object.keys(categories).length}`);
console.error(`š§ Configured for user: ${sanitizeCredential(this.config.username)}`);
console.error(`š Registry: ${this.config.registry}`);
console.error('ā
Server ready with NPM package management tools');
console.error('š” Use --list-tools to see all available tools');
}
}
// Run the server
if (require.main === module) {
try {
const server = new NPMJAEGISMCPServer();
server.run().catch((error) => {
console.error('Failed to start NPM JAEGIS MCP Server:', error.message);
process.exit(1);
});
}
catch (error) {
console.error('Failed to initialize NPM JAEGIS MCP Server:');
console.error(error instanceof Error ? error.message : String(error));
process.exit(1);
}
}
//# sourceMappingURL=index.js.map