fai-mcp-csharp-scaffold — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited fai-mcp-csharp-scaffold (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Build MCP servers in C# with typed tools, validation, and ASP.NET hosting.
dotnet new console -n MyMcpServer
cd MyMcpServer
dotnet add package ModelContextProtocol
dotnet add package Microsoft.Extensions.Hostingusing ModelContextProtocol;
using System.ComponentModel;
[McpTool("search_documents")]
[Description("Search knowledge base documents by query")]
public class SearchDocumentsTool
{
[McpParameter("query", Required = true)]
[Description("Search query text")]
public string Query { get; set; } = "";
[McpParameter("top_k")]
[Description("Number of results to return")]
public int TopK { get; set; } = 5;
public async Task<string> ExecuteAsync()
{
var results = await searchClient.SearchAsync(Query, TopK);
return JsonSerializer.Serialize(results);
}
}using ModelContextProtocol;
using Microsoft.Extensions.Hosting;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMcpServer(options =>
{
options.ServerName = "my-mcp-server";
options.ServerVersion = "1.0.0";
})
.AddTool<SearchDocumentsTool>()
.AddTool<CalculateCostTool>();
var host = builder.Build();
await host.RunAsync();public async Task<string> ExecuteAsync()
{
if (string.IsNullOrWhiteSpace(Query))
throw new ArgumentException("Query cannot be empty");
if (TopK < 1 || TopK > 50)
throw new ArgumentOutOfRangeException(nameof(TopK), "Must be 1-50");
var results = await searchClient.SearchAsync(Query, TopK);
return JsonSerializer.Serialize(results);
}FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:8.0-noble-chiseled
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyMcpServer.dll"]| Issue | Cause | Fix |
|---|---|---|
| Tool not discovered | Missing [McpTool] attribute | Add attribute + register with AddTool<T>() |
| Serialization error | Non-serializable return type | Return string or JsonSerializer.Serialize() |
| Timeout on long operations | No cancellation token | Add CancellationToken parameter |
| Auth not working | No credential setup | Use DefaultAzureCredential in DI |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.