mcp-ai-agent-guidelines
Version:
A comprehensive Model Context Protocol server providing advanced tools, resources, and prompts for implementing AI agent best practices
153 lines • 7.2 kB
JavaScript
/**
* .NET/NuGet Parser (csproj)
*/
import { BaseParser } from "./base.js";
export class DotNetCsprojParser extends BaseParser {
static deprecatedPackages = {
"Microsoft.AspNet.WebApi": {
reason: "Legacy ASP.NET Web API, replaced by ASP.NET Core",
alternative: "Use Microsoft.AspNetCore.* packages",
},
"Microsoft.AspNet.Mvc": {
reason: "Legacy ASP.NET MVC, replaced by ASP.NET Core MVC",
alternative: "Use Microsoft.AspNetCore.Mvc",
},
"Newtonsoft.Json": {
reason: "Consider using System.Text.Json for new projects",
alternative: "System.Text.Json is built-in since .NET Core 3.0",
},
EntityFramework: {
reason: "Legacy Entity Framework 6.x",
alternative: "Use Microsoft.EntityFrameworkCore for new projects",
},
"Microsoft.Owin": {
reason: "OWIN/Katana is legacy middleware",
alternative: "Use ASP.NET Core middleware",
},
RestSharp: {
reason: "Consider using HttpClient for new projects",
alternative: "Use System.Net.Http.HttpClient with IHttpClientFactory",
},
log4net: {
reason: "Consider more modern logging frameworks",
alternative: "Use Microsoft.Extensions.Logging or Serilog",
},
};
/**
* Escape special regex characters in a string to prevent ReDoS attacks
*/
escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
parse(content) {
const packages = [];
const errors = [];
let projectName;
let projectVersion;
try {
const assemblyMatch = content.match(/<AssemblyName>([^<]+)<\/AssemblyName>/);
const rootNsMatch = content.match(/<RootNamespace>([^<]+)<\/RootNamespace>/);
projectName = assemblyMatch?.[1] || rootNsMatch?.[1];
const versionMatch = content.match(/<Version>([^<]+)<\/Version>/);
projectVersion = versionMatch?.[1];
const packageRefs = content.matchAll(/<PackageReference\s+Include=["']([^"']+)["']\s*(?:Version=["']([^"']+)["'])?[^>]*\/?>/gi);
for (const match of packageRefs) {
const name = match[1];
const escapedName = this.escapeRegex(name);
let version = match[2] || "*";
if (!match[2]) {
const versionElementMatch = content.match(new RegExp(`<PackageReference\\s+Include=["']${escapedName}["'][^>]*>[\\s\\S]*?<Version>([^<]+)<\\/Version>`, "i"));
if (versionElementMatch)
version = versionElementMatch[1];
}
const privateAssetsMatch = content.match(new RegExp(`<PackageReference\\s+Include=["']${escapedName}["'][^>]*PrivateAssets=["']All["']`, "i"));
packages.push({
name,
version,
type: privateAssetsMatch ? "devDependencies" : "dependencies",
ecosystem: "dotnet",
});
}
const projectRefs = content.matchAll(/<ProjectReference\s+Include=["']([^"']+)["']/gi);
for (const match of projectRefs) {
const projectPath = match[1];
const projectFileName = projectPath.split(/[/\\]/).pop() || projectPath;
packages.push({
name: projectFileName.replace(".csproj", ""),
version: "local",
type: "dependencies",
ecosystem: "dotnet",
});
}
}
catch (error) {
errors.push(`Error parsing csproj: ${error instanceof Error ? error.message : "Unknown error"}`);
}
return {
packages,
projectName,
projectVersion,
ecosystem: "dotnet",
fileType: "csproj",
errors: errors.length > 0 ? errors : undefined,
};
}
canParse(content) {
return (content.includes("<Project") &&
(content.includes("<PackageReference") ||
content.includes("<ItemGroup") ||
content.includes("Sdk=")));
}
getEcosystem() {
return "dotnet";
}
getFileTypes() {
return ["csproj"];
}
analyzePackage(pkg, options, issues) {
if (pkg.version === "local")
return;
if (options.checkDeprecated) {
const deprecated = DotNetCsprojParser.deprecatedPackages[pkg.name];
if (deprecated) {
this.addIssue(issues, pkg, "Deprecated Package", "moderate", deprecated.reason, deprecated.alternative);
}
}
if (options.checkOutdated) {
if (pkg.version === "*" || pkg.version.includes("*")) {
this.addIssue(issues, pkg, "Unpinned Version", "moderate", "Floating version can lead to unexpected updates", "Pin to a specific version for reproducible builds");
}
if (pkg.version.includes("-alpha") ||
pkg.version.includes("-beta") ||
pkg.version.includes("-preview") ||
pkg.version.includes("-rc")) {
this.addIssue(issues, pkg, "Pre-release Version", "info", "Using pre-release version which may be unstable", "Consider using stable release for production");
}
if (pkg.name.startsWith("Microsoft.") && pkg.version.match(/^[1-3]\./)) {
this.addIssue(issues, pkg, "Potentially Outdated", "info", "Package may be from an older .NET version", "Check if a newer version is available");
}
}
if (options.checkVulnerabilities)
this.checkKnownVulnerabilities(pkg, issues);
}
checkKnownVulnerabilities(pkg, issues) {
if (pkg.name === "System.Text.Json" && pkg.version.match(/^[1-5]\./)) {
this.addIssue(issues, pkg, "Known Vulnerabilities", "high", "Older System.Text.Json versions have known vulnerabilities", "Update to System.Text.Json >= 6.0.0");
}
if (pkg.name === "Newtonsoft.Json" &&
pkg.version.match(/^([1-9]|1[0-2])\./)) {
this.addIssue(issues, pkg, "Known Vulnerabilities", "moderate", "Older Newtonsoft.Json versions may have security issues", "Update to Newtonsoft.Json >= 13.0.1");
}
if (pkg.name.startsWith("Microsoft.AspNetCore.") &&
pkg.version.match(/^[1-5]\./)) {
this.addIssue(issues, pkg, "End of Support", "high", "This ASP.NET Core version is out of support", "Update to .NET 6+ (LTS) or .NET 8+ (current LTS)");
}
}
addEcosystemRecommendations(recommendations) {
recommendations.push("Run 'dotnet list package --outdated' to check for updates");
recommendations.push("Run 'dotnet list package --vulnerable' for security scanning");
recommendations.push("Use Directory.Packages.props for centralized versioning");
recommendations.push("Consider using dependabot for automated NuGet updates");
}
}
//# sourceMappingURL=dotnet.js.map