Bitzsoft.Integrations.McpServer 1.0.0-alpha.10

This is a prerelease version of Bitzsoft.Integrations.McpServer.
dotnet add package Bitzsoft.Integrations.McpServer --version 1.0.0-alpha.10
                    
NuGet\Install-Package Bitzsoft.Integrations.McpServer -Version 1.0.0-alpha.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bitzsoft.Integrations.McpServer" Version="1.0.0-alpha.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bitzsoft.Integrations.McpServer" Version="1.0.0-alpha.10" />
                    
Directory.Packages.props
<PackageReference Include="Bitzsoft.Integrations.McpServer" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bitzsoft.Integrations.McpServer --version 1.0.0-alpha.10
                    
#r "nuget: Bitzsoft.Integrations.McpServer, 1.0.0-alpha.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bitzsoft.Integrations.McpServer@1.0.0-alpha.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bitzsoft.Integrations.McpServer&version=1.0.0-alpha.10&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Bitzsoft.Integrations.McpServer&version=1.0.0-alpha.10&prerelease
                    
Install as a Cake Tool

Bitzsoft.Integrations.McpServer

基于官方 MCP C# SDK 的安全 Client/Server 集成。包名为兼容既有命名保留 McpServer,实际同时提供 Streamable HTTP、stdio 客户端以及 HTTP、stdio 服务端。

适用范围

  • 将受信 MCP 工具接入 Microsoft Agent Framework 或 Microsoft.Extensions.AI
  • 把现有 ASP.NET Core 业务能力显式发布为 MCP 工具;
  • 启动经过审批的本地 stdio MCP 服务;
  • 按租户、地域、环境和凭据名称解析 MCP 访问凭据。

目标框架为 net8.0;net10.0。MCP 官方 SDK 不支持 .NET 5,因此老系统应把 MCP/Agent 能力部署为独立 .NET 8/10 服务,再通过受控 HTTP 边界调用。

安装

dotnet add package Bitzsoft.Integrations.McpServer

安全默认值

本封装采用默认拒绝策略:

  • 客户端必须配置非空 AllowedTools,连接成功后只返回白名单工具;
  • HTTP 必须配置 AllowedHosts;远程地址必须使用 HTTPS;
  • URL 禁止携带用户名、密码、query 或 fragment;
  • 默认阻止远程地址解析到私网、链路本地、共享地址、文档/基准测试地址和特殊网段, 并固定首次校验得到的 IP,降低 SSRF 与 DNS 重绑定风险;
  • loopback 主机必须只解析到 loopback IP,避免被污染的主机解析把本地配置导向远端;
  • HTTP Bearer Token 通过 IIntegrationCredentialResolver 按当前 IntegrationContext 解析,不进入 Options、配置文件或日志;
  • stdio 命令必须是白名单中的绝对路径,不通过 shell 拼接参数;
  • stdio 子进程不继承完整父进程环境,只传官方安全基础环境和显式凭据字段;
  • 服务端不扫描程序集、不附带示例工具,只有显式调用 WithTools<T>() 的类型会被公开;
  • HTTP 服务端自动加入 MCP 授权过滤器,但宿主仍必须为 MapMcp() 端点配置认证授权。

AllowPrivateNetwork = true 只应对经过审批的企业内网 MCP 服务开启;它不会关闭 主机白名单、HTTPS、禁重定向或 DNS 固定。客户端当前提供 Bearer Token;OAuth 动态授权、mTLS 或企业代理由宿主使用官方 MCP SDK 定制传输。

HTTP 客户端

注册

using Bitzsoft.Integrations.McpServer;
using Bitzsoft.Integrations.McpServer.Models;

// 命名客户端配置只保存非敏感连接策略。
services.AddBitzMcpHttpClient("knowledge", options =>
{
    options.Endpoint = new Uri("https://mcp.example.com/mcp");
    options.ProviderId = "knowledge";
    options.CredentialName = "production";
    options.AllowedHosts.Add("mcp.example.com");
    options.AllowedTools.Add("search_knowledge");
    options.AllowedTools.Add("read_document");
    options.RequireAuthentication = true;
});

生产宿主应实现 IIntegrationCredentialResolver 并连接 Vault、KMS 或云密钥服务。 开发测试可以显式使用进程内 Store:

// 仅开发/测试:生产环境替换为 Vault、KMS 或云密钥服务。
services.AddInMemoryIntegrationCredentials();

// 凭据键必须与实际调用时的 IntegrationContext 完全匹配。
var context = new IntegrationContext(
    tenantId: "tenant-a",
    region: "cn-east",
    environment: "production");
var key = IntegrationCredentialKey.FromContext(
    context,
    "MCP:knowledge",
    "production");
using var credential = new IntegrationCredential(
    new Dictionary<string, string>
    {
        [McpCredentialFieldNames.BearerToken] = developmentToken
    });
credentialStore.Set(key, credential);

不要把真实 Token 放入 appsettings.json、环境映射 Options 或日志。进程内 Store 不是 生产密钥服务。

连接并交给 Agent

每次操作必须先设置租户上下文。McpClientConnection 持有底层会话,工具仍依赖该会话, 因此必须在 Agent 完成调用后再释放连接。

// 当前租户上下文是凭据解析的强制输入。
using var contextScope = contextAccessor.Push(
    new IntegrationContext("tenant-a", correlationId: traceId));
await using var connection = await mcpClientFactory.ConnectHttpAsync(
    "knowledge",
    cancellationToken);

// AgentTools 已转换为 Agent 构造函数需要的 IList<AITool>。
IList<AITool> tools = connection.AgentTools;

推荐按请求或一次 Agent Run 创建连接,不要跨租户缓存连接或工具。白名单中有工具未被 远端公开时连接会失败,避免服务端能力漂移被静默忽略。

完整 HTTP Client + Agent 示例

以下示例使用开发 Token,并确保 MCP 连接覆盖整个 Agent Run:

using Bitzsoft.Integrations.AI;
using Bitzsoft.Integrations.Core;
using Bitzsoft.Integrations.McpServer;
using Bitzsoft.Integrations.McpServer.Models;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

// 仅开发/测试;生产环境注册安全凭据解析器。
services.AddInMemoryIntegrationCredentials();

// 注册租户感知模型;模型密钥同样不进入 Options。
services.AddBitzChatClient(options =>
{
    options.ProviderId = "deepseek-dev";
    options.ProfileId = "deepseek";
    options.ModelId = "deepseek-chat";
});

services.AddBitzMcpHttpClient("knowledge", options =>
{
    options.Endpoint = new Uri("https://mcp.example.com/mcp");
    options.ProviderId = "knowledge";
    options.CredentialName = "development";
    options.AllowedHosts.Add("mcp.example.com");
    options.AllowedTools.Add("search_knowledge");
    options.RequireAuthentication = true;
});

await using var provider = services.BuildServiceProvider(
    new ServiceProviderOptions { ValidateScopes = true });

// 为 tenant-a 写入 MCP:knowledge 的开发 Bearer Token。
var credentialStore = provider.GetRequiredService<
    InMemoryIntegrationCredentialStore>();

// 写入模型凭据 AI:deepseek-dev。
using (var credential = new IntegrationCredential(
[
    new(AICredentialFieldNames.ApiKey, "<开发环境模型 API Key>")
]))
{
    credentialStore.Set(
        new IntegrationCredentialKey(
            tenantId: "tenant-a",
            providerKey: "AI:deepseek-dev",
            environment: IntegrationEnvironments.Development),
        credential);
}

// 写入 MCP 凭据 MCP:knowledge。
using (var credential = new IntegrationCredential(
[
    new(McpCredentialFieldNames.BearerToken, "<开发环境 Bearer Token>")
]))
{
    credentialStore.Set(
        new IntegrationCredentialKey(
            tenantId: "tenant-a",
            providerKey: "MCP:knowledge",
            environment: IntegrationEnvironments.Development,
            credentialName: "development"),
        credential);
}

using var scope = provider.CreateScope();
var contextAccessor = scope.ServiceProvider.GetRequiredService<
    IIntegrationContextAccessor>();
using (contextAccessor.Push(new IntegrationContext(
    tenantId: "tenant-a",
    environment: IntegrationEnvironments.Development)))
{
    var factory = scope.ServiceProvider.GetRequiredService<
        IMcpClientFactory>();

    // connection 必须比 Agent 和它持有的 MCP tools 活得更久。
    await using var connection = await factory.ConnectHttpAsync("knowledge");
    var chatClient = scope.ServiceProvider.GetRequiredService<IChatClient>();
    var innerAgent = new ChatClientAgent(
        chatClient,
        instructions: "只能使用已批准的只读知识工具。",
        name: "knowledge-agent",
        description: "查询租户知识库",
        tools: connection.AgentTools);

    // 即使当前白名单只有只读工具,也保留官方审批中间件。
    AIAgent agent = new ToolApprovalAgent(innerAgent);
    var response = await agent.RunAsync("查询差旅报销标准。");
    Console.WriteLine(response.Text);
}

stdio 客户端

stdio 适合本机受控工具。不要允许用户输入决定 Command 或拼接 Arguments

// Command 和白名单都必须是管理员部署的绝对路径。
services.AddBitzMcpStdioClient("local-files", options =>
{
    options.Command = "/opt/company/mcp/files-server";
    options.AllowedExecutablePaths.Add("/opt/company/mcp/files-server");
    options.Arguments.Add("--read-only");
    // 工作目录必须是部署时已存在的绝对路径。
    options.WorkingDirectory = "/srv/approved-documents";
    options.AllowedTools.Add("read_approved_file");

    options.ProviderId = "local-files";
    options.RequireCredential = true;
    // 这里只保存“环境变量名 -> 凭据字段名”,不保存 Token 值。
    options.CredentialEnvironmentVariables["FILES_ACCESS_TOKEN"] =
        "AccessToken";
});

CredentialEnvironmentVariables 的 key 是子进程环境变量名,value 是凭据 Store 中的 字段名,字典本身不保存凭据值。若服务不需要凭据,保持 RequireCredential = false 并让映射为空。

// stdio 进程也按当前租户解析凭据;不要跨请求缓存 connection。
using var contextScope = contextAccessor.Push(
    new IntegrationContext("tenant-a"));
await using var connection = await mcpClientFactory.ConnectStdioAsync(
    "local-files",
    cancellationToken);

Streamable HTTP 服务端

工具必须显式注册。工具方法应再次执行租户、资源和业务权限检查,不能把“模型决定调用” 视为授权。

using System.ComponentModel;
using Microsoft.AspNetCore.Authorization;
using ModelContextProtocol.Server;

[McpServerToolType]
public sealed class KnowledgeTools(IKnowledgeService knowledge)
{
    [McpServerTool(Name = "search_knowledge")]
    [Description("Search approved tenant knowledge.")]
    [Authorize(Policy = "McpKnowledgeRead")]
    public Task<SearchResult> SearchAsync(
        string query,
        CancellationToken cancellationToken)
        // 业务服务内部仍需校验当前租户、用户和资源权限。
        => knowledge.SearchAsync(query, cancellationToken);
}

// 只显式公开 KnowledgeTools,不扫描程序集。
builder.Services
    .AddBitzMcpHttpServer(options =>
    {
        options.ServerName = "company-knowledge";
        options.ServerVersion = "1.0.0";
        options.Instructions = "Read-only access to approved knowledge.";
    })
    .WithTools<KnowledgeTools>();

var app = builder.Build();

// MCP 端点必须同时配置认证和授权策略。
app.MapMcp("/mcp").RequireAuthorization("McpClient");

生产端点还应配置 TLS、受众和 issuer 校验、速率限制、审计、超时、请求体限制以及网关 级防护。对有副作用的工具采用细粒度授权、幂等键和人工审批,不要只依赖自然语言指令。

stdio 服务端

// stdio 服务端只公开显式工具,标准输出保留给 MCP 协议。
services
    .AddBitzMcpStdioServer(options =>
    {
        options.ServerName = "company-local-tools";
        options.ServerVersion = "1.0.0";
    })
    .WithTools<ApprovedLocalTools>();

stdio 服务端是父进程控制的单会话服务。标准输出只能写 MCP 协议消息,应用日志应写入 标准错误或其他 Sink。

配置参考

McpHttpClientOptions

属性 默认值 说明
Endpoint https://localhost/mcp MCP 绝对地址
ProviderId default 凭据 Provider 标识,最终键为 MCP:{ProviderId}
CredentialName default 凭据名称
RequireAuthentication true 是否解析 Bearer Token
AllowedHosts 允许的 DNS 主机精确白名单
AllowPrivateNetwork false 是否允许非回环私网
AllowedTools 可交给模型使用的工具精确白名单
TransportMode AutoDetect Streamable HTTP/SSE 协商方式
ConnectionTimeout 30 秒 初始连接超时
ClientName / ClientVersion Bitzsoft / 1.0.0 MCP 握手客户端身份

McpStdioClientOptions

属性 默认值 说明
Command 可执行文件绝对路径
AllowedExecutablePaths 可执行文件绝对路径白名单
Arguments 独立进程参数
WorkingDirectory 可选绝对工作目录
AllowedTools 工具精确白名单
CredentialEnvironmentVariables 环境变量名到凭据字段名映射
RequireCredential false 是否要求凭据快照
ShutdownTimeout 5 秒 子进程退出等待时间

与 Agent Framework 的边界

本包负责 MCP 传输、凭据、端点和工具最小权限;Bitzsoft.Integrations.AgentFramework 负责 Agent 组装与会话。工具调用审批、业务授权、幂等和审计属于宿主业务边界。MCP 连接不能比其所属 AgentSession 更早释放。

常见错误

  • 把远端返回的全部工具直接交给模型;
  • 在配置文件中保存 Authorization 或 API Key;
  • 对 HTTP 服务调用 WithToolsFromAssembly()
  • 允许任意 nodenpxbash 或用户输入作为 stdio 命令;
  • stdio 子进程继承父进程全部环境变量;
  • 跨租户复用 McpClientConnection
  • 仅靠 Agent Instructions 限制删除、付款、发信等副作用。
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Bitzsoft.Integrations.McpServer:

Package Downloads
Bitzsoft.Integrations.All

Bitzsoft 第三方集成聚合包 — 包含全部 Integration 模块

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-alpha.10 0 7/26/2026
1.0.0-alpha.9 56 7/12/2026
1.0.0-alpha.8 62 7/1/2026
1.0.0-alpha.7 81 6/16/2026
1.0.0-alpha.6 71 6/16/2026
1.0.0-alpha.5 69 6/14/2026
1.0.0-alpha.3 66 6/7/2026
1.0.0-alpha.2 69 5/29/2026
1.0.0-alpha.1 64 5/28/2026