# NPM Sentinel MCP Server - Full Documentation ## Protocol Specification Version: 2025-05-11 Transport: stdio Features: resources, tools, error handling ## Architecture ```mermaid flowchart TD Client[MCP Client] <-->|MCP Protocol| Server[NPM Sentinel Server] Server -->|Fetch| NPM[NPM Registry] Server -->|Analysis| Security[Security DB] Server -->|Metrics| Stats[Download Stats] subgraph Resources NPM Security Stats end subgraph Tools Analysis[Package Analysis] TypeScript[TS Support] Performance[Performance] Trends[Trend Analysis] end ``` ## Resources ### npm://registry Content-Type: application/json Methods: GET, SUBSCRIBE Update Frequency: Real-time Rate Limits: Follows npm registry limits Description: Package metadata and version information interface ### npm://security Content-Type: application/json Methods: GET Update Frequency: Daily Severity Levels: Low, Medium, High, Critical Description: Vulnerability and security analysis interface ### npm://metrics Content-Type: application/json Methods: GET, SUBSCRIBE Update Frequency: Real-time Metrics Types: Downloads, Stars, Issues, Updates Description: Package analytics and statistics interface ## Tool Specifications // Note: For all tools below, the response payload, typically as described by its `XYZResponse` interface // (or a textual summary if the response is simpler), is JSON stringified and placed within the `text` field // of the standard MCP content object: {"type": "text", "text": "...", "isError": boolean}. #### npmVersions ```typescript interface NpmVersionsInput { packages: string[]; } interface VersionInfo { version: string; releaseDate: string; deprecated?: boolean; description?: string; } interface NpmVersionsResponse { [packageName: string]: VersionInfo[]; } ``` #### npmLatest ```typescript interface NpmLatestInput { packages: string[]; } interface LatestInfo { version: string; releaseDate: string; changelog?: string; } interface NpmLatestResponse { [packageName: string]: LatestInfo; } ``` #### npmDeps ```typescript interface NpmDepsInput { packages: string[]; } interface DependencyNode { name: string; version: string; dependencies?: { [dependencyName: string]: string }; } interface NpmDepsResponse { [packageName: string]: { dependencyTree?: DependencyNode; analysisSummary?: string; }; } ``` #### npmTypes ```typescript interface NpmTypesInput { packages: string[]; } interface TypeSupport { hasTypes: boolean; bundled: boolean; definitelyTyped: boolean; typeVersion?: string; } interface NpmTypesResponse { [packageName: string]: TypeSupport; } ``` #### npmSize ```typescript interface NpmSizeInput { packages: string[]; } interface SizeMetrics { size: number; gzip: number; dependenciesCount: number; treeshakeable?: boolean; assetSizes?: { assetName: string; size: number }[]; } interface NpmSizeResponse { [packageName: string]: SizeMetrics; } ``` #### npmVulnerabilities ```typescript interface NpmVulnerabilitiesInput { packages: string[]; } interface Vulnerability { severity: 'low' | 'medium' | 'high' | 'critical' | 'unknown'; title: string; description: string; affectedVersions: string; recommendation?: string; cvssScore?: number; url?: string; } interface NpmVulnerabilitiesResponse { [packageName: string]: Vulnerability[]; } ``` #### npmTrends ```typescript interface NpmTrendsInput { packages: string[]; period: 'last-day' | 'last-week' | 'last-month' | 'last-year'; } interface TrendDataPoint { date: string; downloads: number; } interface TrendMetrics { period: string; downloads: TrendDataPoint[]; growth?: number; popularityScore?: number; } interface NpmTrendsResponse { [packageName: string]: TrendMetrics; } ``` #### npmCompare ```typescript interface NpmCompareInput { packages: string[]; } interface ComparisonAspects { latestVersion?: string; size?: SizeMetrics; vulnerabilitiesCount?: number; averageDownloads?: number; qualityScore?: number; } interface NpmCompareResponse { [packageName: string]: ComparisonAspects; comparisonSummary?: string; } ``` #### npmMaintainers ```typescript interface NpmMaintainersInput { packages: string[]; } interface Maintainer { name: string; email?: string; githubUsername?: string; } interface NpmMaintainersResponse { [packageName: string]: Maintainer[]; } ``` #### npmScore ```typescript interface NpmScoreInput { packages: string[]; } interface ScoreDetails { quality: number; popularity: number; maintenance: number; overall: number; } interface NpmScoreResponse { [packageName: string]: ScoreDetails; } ``` #### npmPackageReadme ```typescript interface NpmPackageReadmeInput { packages: string[]; } interface NpmPackageReadmeResponse { [packageName: string]: { content: string; format: 'markdown' | 'text'; error?: string; }; } ``` #### npmSearch ```typescript interface NpmSearchInput { query: string; limit?: number; } interface SearchResultPackage { name: string; version: string; description?: string; keywords?: string[]; score?: ScoreDetails; } interface NpmSearchResponse { query: string; results: SearchResultPackage[]; totalResults?: number; } ``` #### npmLicenseCompatibility ```typescript interface NpmLicenseCompatibilityInput { packages: string[]; projectLicense?: string; } interface LicenseInfo { spdxId: string; name: string; isCompatible?: boolean; issues?: string[]; } interface NpmLicenseCompatibilityResponse { [packageName: string]: LicenseInfo; compatibilitySummary?: string; } ``` #### npmRepoStats ```typescript interface NpmRepoStatsInput { packages: string[]; } interface RepoStats { stars?: number; forks?: number; openIssues?: number; lastCommitDate?: string; contributorsCount?: number; repoUrl?: string; } interface NpmRepoStatsResponse { [packageName: string]: RepoStats; } ``` #### npmDeprecated ```typescript interface NpmDeprecatedInput { packages: string[]; } interface DeprecationInfo { isDeprecated: boolean; message?: string; alternative?: string; } interface NpmDeprecatedResponse { [packageName: string]: DeprecationInfo; } ``` #### npmChangelogAnalysis ```typescript interface NpmChangelogAnalysisInput { packages: string[]; targetVersion?: string; sinceVersion?: string; } interface ChangelogEntry { version: string; date?: string; summary?: string; changes?: { type: 'added' | 'fixed' | 'changed' | 'removed'; description: string }[]; } interface NpmChangelogAnalysisResponse { [packageName: string]: { changelogUrl?: string; entries?: ChangelogEntry[]; analysisSummary?: string; }; } ``` #### npmAlternatives ```typescript interface NpmAlternativesInput { packages: string[]; } interface AlternativePackageInfo { name: string; reason?: string; score?: ScoreDetails; } interface NpmAlternativesResponse { [packageName: string]: { alternatives: AlternativePackageInfo[]; }; } ``` #### npmQuality ```typescript interface NpmQualityInput { packages: string[]; } interface QualityMetrics { codeComplexity?: number; testCoverage?: number; documentationScore?: number; communityEngagement?: number; npmsQualityScore?: number; npmsPopularityScore?: number; npmsMaintenanceScore?: number; } interface NpmQualityResponse { [packageName: string]: QualityMetrics; } ``` #### npmMaintenance ```typescript interface NpmMaintenanceInput { packages: string[]; } interface MaintenanceMetrics { lastPublishDate?: string; commitFrequency?: string; openIssuesRatio?: number; timeSinceLastCommit?: string; npmsMaintenanceScore?: number; } interface NpmMaintenanceResponse { [packageName: string]: MaintenanceMetrics; } ``` ## Error Handling ### Standard Error Format // When an error occurs, the standard MCP response 'content' object will have 'isError: true'. // The 'text' field of that content object will contain a JSON stringified MCPError object, as defined below. ```typescript interface MCPError { error: { code: number; message: string; data?: { details: string; packageName?: string; context?: any; }; }; } ``` ### Error Codes 1000: Invalid package name (Rejected by security validation filter due to restricted characters or format) 1001: Package not found 1002: Version not found 1003: Rate limit exceeded 1004: Network error 1005: Analysis failed 2000: Internal server error ## Security Considerations ### Data Protection - All data is processed locally - No sensitive information is stored - Secure communication channels ### Input Validation - Strict Regex-based allowlist for package names - Prevents Path Traversal (`../`) - Prevents Command Injection (`&`, `;`, `|`) - Prevents SSRF attacks ### Rate Limiting - Implements fair usage policies - Respects NPM registry limits - Prevents abuse ### Authentication - Supports npm token authentication - Validates package access - Manages credentials securely ## Integration Guide ### Docker Configuration The server can be run in a Docker container with directory mounting to `/projects`. This allows for secure access to files while maintaining isolation. #### Build ```bash # Build the Docker image docker build -t nekzus/npm-sentinel-mcp . ``` #### Basic Usage ```json { "mcpServers": { "npm-sentinel-mcp": { "command": "docker", "args": [ "run", "-i", "--rm", "-w", "/projects", "--mount", "type=bind,src=${PWD},dst=/projects", "nekzus/npm-sentinel-mcp", "node", "dist/index.js" ] } } } ``` #### Multi-Directory Configuration ```json { "mcpServers": { "npm-sentinel-mcp": { "command": "docker", "args": [ "run", "-i", "--rm", "-w", "/projects", "--mount", "type=bind,src=/path/to/workspace,dst=/projects/workspace", "--mount", "type=bind,src=/path/to/other/dir,dst=/projects/other/dir,ro", "nekzus/npm-sentinel-mcp", "node", "dist/index.js" ] } } } ``` #### Mount Guidelines - Mount all directories under `/projects` - Use absolute paths for source directories - Add `,ro` flag for read-only access - Working directory is set to `/projects` - Container runs in interactive mode with auto-removal ### Standard Configuration ```json { "mcpServers": { "npm-sentinel-mcp": { "transport": "stdio", "command": "npx", "args": ["-y", "@nekzus/mcp-server"] } } } ``` ### Basic Usage ```typescript // Initialize client const client = await MCPClient.connect("npm-sentinel-mcp"); // Analyze package const result = await client.invoke("npmVersions", { packages: ["react"] }); // Subscribe to updates const unsubscribe = await client.subscribe("npm://registry", { package: "react", onUpdate: (data) => console.log(data) }); ``` ## Best Practices ### Resource Usage 1. Subscribe to resources for real-time updates 2. Implement caching for frequently accessed data 3. Use batch operations when possible 4. Handle rate limits gracefully ### Error Handling 1. Implement proper error recovery 2. Provide meaningful error messages 3. Log errors for debugging 4. Handle timeout scenarios ### Performance 1. Use connection pooling 2. Implement request queuing 3. Cache responses 4. Handle concurrent requests