{"id":60153,"date":"2026-05-21T10:05:00","date_gmt":"2026-05-21T17:05:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=60153"},"modified":"2026-05-21T10:05:00","modified_gmt":"2026-05-21T17:05:00","slug":"announcing-agent-governance-toolkit-mcp-extensions-for-dotnet","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-agent-governance-toolkit-mcp-extensions-for-dotnet\/","title":{"rendered":"Announcing Agent Governance Toolkit MCP Extensions for .NET"},"content":{"rendered":"<p>The <a href=\"https:\/\/modelcontextprotocol.io\/\">Model Context Protocol (MCP)<\/a> has made\nit much easier to connect tools and resources to AI applications. But once\nthose tools are exposed to agents, you also need a reliable way to govern what\ngets registered, what gets executed, and what comes back from tool calls.<\/p>\n<p>For a detailed look at the governance patterns and controls behind this\npackage, see <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/governing-mcp-tool-calls-in-dotnet-with-the-agent-governance-toolkit\/\">Governing MCP tool calls in .NET with the Agent Governance\nToolkit<\/a>. This post\nannounces <strong><code>Microsoft.AgentGovernance.Extensions.ModelContextProtocol<\/code><\/strong>, a\nPublic Preview companion package for the official <a href=\"https:\/\/modelcontextprotocol.github.io\/csharp-sdk\/api\/ModelContextProtocol.html\">MCP C# SDK<\/a> that makes it\nsimple to apply those controls.<\/p>\n<p>It adds one-call governance to <code>IMcpServerBuilder<\/code> so you can apply policy\nenforcement, startup scanning, runtime tool-call governance, and response\nsanitization to your MCP server without building that plumbing yourself.<\/p>\n<p>If you&#8217;re already building MCP servers with .NET, this package is designed to\nfit directly into the builder pipeline you already use.<\/p>\n<h2>Why MCP servers need governance<\/h2>\n<p>MCP makes tool integration straightforward, but the same flexibility creates a\nnew set of security and reliability questions:<\/p>\n<ul>\n<li>Should every registered tool be callable by every agent?<\/li>\n<li>What happens if a tool description includes prompt-injection-style\ninstructions?<\/li>\n<li>How do you fail closed when a tool definition changes in a risky way?<\/li>\n<li>How do you keep unsafe tool output from flowing straight back into the model?<\/li>\n<\/ul>\n<p>Those concerns usually show up as a mix of custom filters, ad hoc validation,\nand application-specific guardrails.\n<code>Microsoft.AgentGovernance.Extensions.ModelContextProtocol<\/code> packages those\nconcerns into a single extension method so the secure path is also the simple\npath.<\/p>\n<h2>Getting started<\/h2>\n<p>Here&#8217;s how to add it to your MCP server. Start by installing the package:<\/p>\n<pre><code class=\"language-bash\">dotnet add package Microsoft.AgentGovernance.Extensions.ModelContextProtocol<\/code><\/pre>\n<p>Then add governance when configuring your MCP server:<\/p>\n<pre><code class=\"language-csharp\">using AgentGovernance.Extensions.ModelContextProtocol;\n\nbuilder.Services\n    .AddMcpServer()\n    .WithGovernance(options =&gt;\n    {\n        options.PolicyPaths.Add(\"policies\/mcp.yaml\");\n        options.DefaultAgentId = \"did:mcp:server\";\n        options.ServerName = \"contoso-support\";\n    });<\/code><\/pre>\n<p>That single call registers startup and runtime governance controls in one\nplace: tool-definition scanning before exposure, identity-aware policy\nenforcement on each call, response sanitization before model return, and audit plus metrics instrumentation.<\/p>\n<h2>What <code>WithGovernance(...)<\/code> adds<\/h2>\n<p>The package is intentionally small on surface area and opinionated in behavior.<\/p>\n<h2>How the governed flow works<\/h2>\n<p>The flow has two phases: startup gating and runtime tool-call governance.\nStartup scanning happens before tools are exposed, while runtime checks apply on each tool call.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2026\/05\/governance-flow.webp\" alt=\"Diagram of governed MCP flow showing startup scanning, runtime policy checks, and response sanitization\" \/><\/p>\n<h3>Startup scanning for unsafe tool definitions<\/h3>\n<p>When MCP server options are materialized, the package scans registered tools\nbefore they are exposed. By default, unsafe tools fail startup.<\/p>\n<p>This is a startup gate, not a per-call runtime step, so unsafe tool metadata\ncan fail closed before any tool is exposed to clients.<\/p>\n<p>The built-in scanner detects threat categories including:<\/p>\n<ul>\n<li>tool poisoning<\/li>\n<li>typosquatting<\/li>\n<li>hidden instructions<\/li>\n<li>rug pulls<\/li>\n<li>schema abuse<\/li>\n<li>cross-server attacks<\/li>\n<li>description injection<\/li>\n<\/ul>\n<p>This helps detect problems such as prompt-like control text in descriptions,\nsuspiciously similar tool names, hidden Unicode characters, or schema fields\nthat request sensitive values like <code>token<\/code>, <code>password<\/code>, or <code>system_prompt<\/code>.\nDetection effectiveness depends on your threshold tuning and threat model\u2014tune\nthe risk score threshold in your own environment based on your acceptable\nfalse-positive rate.<\/p>\n<h3>Policy enforcement on tool execution<\/h3>\n<p>Governance decisions are applied when tools are invoked, using the same Agent\nGovernance policy model as the base .NET package.<\/p>\n<p>That means you can use YAML-backed policies to decide which tools are allowed,\ndenied, or rate-limited, and you can keep those rules outside of application\ncode.<\/p>\n<p>For example:<\/p>\n<pre><code class=\"language-yaml\">apiVersion: governance.toolkit\/v1\nversion: \"1.0\"\nname: mcp-governance-policy\ndefault_action: deny\nrules:\n  - name: allow-echo\n    condition: \"tool_name == 'echo'\"\n    action: allow\n    priority: 10<\/code><\/pre>\n<p>If a tool call is denied, the package returns a governed error result instead\nof letting execution continue.<\/p>\n<h3>Authenticated identity support<\/h3>\n<p>When an authenticated identity is present, governance uses that agent identity\nin evaluation. If one is not available, the package falls back to a\nconfigurable default DID such as <code>did:mcp:anonymous<\/code>.<\/p>\n<p>This makes it easier to write policies that distinguish between trusted callers\nand anonymous or low-trust execution contexts.<\/p>\n<h3>Response sanitization before content reaches the model<\/h3>\n<p>Tool output is another place where attacks can hide. By default, the package\nsanitizes text responses before they are returned to the client.<\/p>\n<p>The sanitizer scans for:<\/p>\n<ul>\n<li>prompt-injection tags like <code>&lt;system&gt;...&lt;\/system&gt;<\/code><\/li>\n<li>imperative override phrasing like &#8220;ignore previous instructions&#8221;<\/li>\n<li>credential leakage patterns<\/li>\n<li>exfiltration-oriented URLs<\/li>\n<\/ul>\n<p>When it finds patterns matching these categories, it redacts the dangerous\nfragments while preserving as much useful result content as possible. Sanitizer\neffectiveness depends on pattern tuning and your environment&#8217;s threat baseline.<\/p>\n<h2>Designed to fail closed by default<\/h2>\n<p>One of the goals of this package is to make safe defaults the default defaults.<\/p>\n<p><code>McpGovernanceOptions<\/code> enables several protections out of the box:<\/p>\n<ul>\n<li><code>ScanToolsOnStartup = true<\/code><\/li>\n<li><code>FailOnUnsafeTools = true<\/code><\/li>\n<li><code>SanitizeResponses = true<\/code><\/li>\n<li><code>GovernFallbackHandlers = true<\/code><\/li>\n<li><code>EnableAudit = true<\/code><\/li>\n<li><code>EnableMetrics = true<\/code><\/li>\n<\/ul>\n<p>That combination gives you a strong baseline without requiring a long checklist\nbefore your first deployment.<\/p>\n<h2>Works with the MCP builder model you already use<\/h2>\n<p>This package doesn&#8217;t require a forked SDK, a separate proxy process, or a\ncustom server abstraction. It extends the official C# SDK builder and wraps the\nfinal <code>ToolCollection<\/code>, so governance applies to tools registered before or\nafter the extension is added.<\/p>\n<p>That detail matters for real applications, because MCP server setup often grows\nacross feature modules and DI registrations over time.<\/p>\n<h2>A practical fit for production MCP servers<\/h2>\n<p><code>Microsoft.AgentGovernance.Extensions.ModelContextProtocol<\/code> is a good fit when\nyou want to:<\/p>\n<ul>\n<li>add policy control to an existing MCP server<\/li>\n<li>block unsafe tool definitions before startup completes<\/li>\n<li>enforce identity-aware tool execution<\/li>\n<li>sanitize tool output before it is fed back into agent workflows<\/li>\n<li>standardize governance across multiple MCP servers in the same organization<\/li>\n<\/ul>\n<p>Because the package builds on the broader <code>Microsoft.AgentGovernance<\/code> stack, it\nalso lines up with features like auditability, metrics, execution rings,\nprompt-injection detection, and circuit-breaker support already available in\nthe .NET package.<\/p>\n<h2>Try it today<\/h2>\n<p><code>Microsoft.AgentGovernance.Extensions.ModelContextProtocol<\/code> is available now as\na <strong>Public Preview<\/strong> package for .NET 8+ applications using the official MCP C#\n<a href=\"https:\/\/modelcontextprotocol.github.io\/csharp-sdk\/api\/ModelContextProtocol.html\">SDK<\/a>.<\/p>\n<p>To get started:<\/p>\n<ol>\n<li>Install <code>Microsoft.AgentGovernance.Extensions.ModelContextProtocol<\/code>.<\/li>\n<li>Add <code>WithGovernance(...)<\/code> to your <code>IMcpServerBuilder<\/code> pipeline.<\/li>\n<li>Point the package at your governance policy files.<\/li>\n<li>Run your server with startup scanning and response sanitization enabled.<\/li>\n<\/ol>\n<p>If you&#8217;re building MCP servers for internal copilots, enterprise tools, or\nagent platforms, this gives you a straightforward way to add governance support\nto your MCP servers without re-implementing the same controls in every service.<\/p>\n<p><div class=\"alert alert-info\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Compliance note<\/strong><\/p>\nAgent Governance Toolkit provides technical controls that can help support\nsecurity and privacy programs. It does not, by itself, guarantee legal or\nregulatory compliance. You are responsible for validating your end-to-end\nimplementation, data handling, and operational controls against applicable\nrequirements (for example, GDPR, SOC 2, or your internal policies).\n<\/div><\/p>\n<h2>Resources<\/h2>\n<ul>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-governance-toolkit\">Agent Governance Toolkit repository<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-governance-toolkit\/tree\/main\/agent-governance-dotnet\"><code>Microsoft.AgentGovernance<\/code> for .NET<\/a><\/li>\n<li><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.AgentGovernance.Extensions.ModelContextProtocol\"><code>Microsoft.AgentGovernance.Extensions.ModelContextProtocol<\/code> on NuGet<\/a><\/li>\n<li><a href=\"https:\/\/modelcontextprotocol.io\/\">Model Context Protocol<\/a><\/li>\n<li><a href=\"https:\/\/modelcontextprotocol.github.io\/csharp-sdk\/api\/ModelContextProtocol.html\">MCP C# SDK<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/modelcontextprotocol\/csharp-sdk\">MCP C# SDK repository<\/a><\/li>\n<li><a href=\"https:\/\/www.nuget.org\/packages\/ModelContextProtocol\">ModelContextProtocol (MCP C# SDK) on NuGet<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/build-a-model-context-protocol-mcp-server-in-csharp\/\">Build a Model Context Protocol (MCP) server in C#<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Announcing a Public Preview .NET package that adds policy enforcement, startup tool scanning, fallback governance, and response sanitization to MCP servers with a single builder extension.<\/p>\n","protected":false},"author":212218,"featured_media":60154,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,7781,326],"tags":[8168,8166,8167,8032,8053],"class_list":["post-60153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-ai","category-security","tag-net-8","tag-agent-governance-toolkit","tag-ai-security","tag-mcp","tag-model-context-protocol"],"acf":[],"blog_post_summary":"<p>Announcing a Public Preview .NET package that adds policy enforcement, startup tool scanning, fallback governance, and response sanitization to MCP servers with a single builder extension.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/212218"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=60153"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60153\/revisions"}],"predecessor-version":[{"id":60162,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60153\/revisions\/60162"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/60154"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=60153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=60153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=60153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}