<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      簡單介紹

      在進入教程之前我們可以先對MCP進行一個大概的了解,MCP是什么?為什么要用MCP?MCP和Function Calling有什么區別?

      MCP是什么?

      Model Context Protocol (MCP) 是一個開放協議,它使 LLM 應用與外部數據源和工具之間的無縫集成成為可能。無論你是構建 AI 驅動的 IDE、改善 chat 交互,還是構建自定義的 AI 工作流,MCP 提供了一種標準化的方式,將 LLM 與它們所需的上下文連接起來。

      • MCP Hosts: 想要通過MCP訪問數據的程序,如Claude Desktop、ide或AI工具
      • MCP Clients: 與服務器保持1:1連接的協議客戶端
      • MCP Servers: 輕量級程序,每個程序都通過標準化的模型上下文協議公開特定的功能
      • Local Data Sources: MCP服務器可以安全訪問的計算機文件、數據庫和服務
      • Remote Services: MCP服務器可以連接的internet上可用的外部系統(例如通過api)

      為什么要用MCP?

      1. 擴展LLM的能力:讓模型能夠訪問最新數據、專有信息和本地資源
      2. 數據私密性和安全性:數據可以保留在本地或受控環境中,減少敏感信息共享的風險
      3. 工具集成:使LLM能夠調用和控制外部工具,擴展其功能范圍
      4. 減少幻覺:通過提供準確的上下文信息,降低模型生成虛假內容的可能性
      5. 標準化:為開發者提供一致的接口,簡化集成過程
      6. 可擴展性:支持從簡單用例到復雜企業級應用的多種場景
      7. 跨語言的能力:通過標準的MCP協議我們可以使用不同語言提供的MCPServer的能力

      MCP和Function Calling有什么區別?

      我聽過最多人問的就是MCP和Function Calling有什么區別?

      特性 MCP Function Calling
      基礎關系 基于Function Calling構建并擴展 作為MCP的基礎技術
      設計范圍 更廣泛的協議,處理上下文獲取和工具使用 主要聚焦于調用特定函數
      架構 客戶端-服務器架構,支持分布式系統 通常是API參數的直接定義和調用
      數據處理 可以處理大型數據集和復雜上下文 主要處理結構化的函數參數和返回值
      上下文管理 專門設計用于管理和提供上下文 上下文管理不是核心功能
      標準化程度 開放協議,旨在跨不同系統和模型標準化 實現方式因平臺而異,標準化程度較低
      應用場景 適用于需要復雜上下文和工具集成的場景 適用于調用預定義函數執行特定任務

      簡而言之,MCP(Model Context Protocol)是在Function Calling基礎上發展而來的更全面的協議,它不僅保留了Function Calling的核心功能,還擴展了上下文獲取和管理能力,為LLM提供更豐富、更標準化的環境交互能力。

      開始MCPClient基礎教程

      前提條件,您需要先將上一個教程的MCPServer跑起來一會才能進行當前步驟,因為MCPClient是需要MCPServer提供Tools,下面我默認您已經運行了MCPServer,

      然后可以訪問 https://account.coreshub.cn/signup?invite=ZmpMQlZxYVU= 獲取免費的DeepSeek-V3模型和白嫖GPU服務器,通過上面連接注冊以后訪問

      https://console.coreshub.cn/xb3/maas/global-keys/ 地址獲取到APIKey

      然后記住我們的APIKey,開始下面的旅途

      1. 創建屬于您的MCPClient程序

      創建一個McpClient的控制臺項目

      給項目添加依賴包

          <ItemGroup>
              <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.3" />
              <PackageReference Include="Microsoft.SemanticKernel" Version="1.44.0" />
              <PackageReference Include="ModelContextProtocol" Version="0.1.0-preview.4" />
          </ItemGroup>
      

      下面的教程我們將使用Microsoft.SemanticKernel開發,然后依賴ModelContextProtocol官方的包,然后我們需要用到Microsoft.Extensions.Hosting

      開始我們的代碼開發

      1. 擴展SemanticKernel的MCPClient

      由于SemnaticKernel默認是不能直接使用MCP的功能,那么我們需要先對它進行擴展

      創建幾個基礎類

      JsonSchema.cs

      
      /// <summary>
      /// Represents a JSON schema for a tool's input arguments.
      /// <see >See the schema for details</see>
      /// </summary>
      internal class JsonSchema
      {
          /// <summary>
          /// The type of the schema, should be "object".
          /// </summary>
          [JsonPropertyName("type")]
          public string Type { get; set; } = "object";
      
          /// <summary>
          /// Map of property names to property definitions.
          /// </summary>
          [JsonPropertyName("properties")]
          public Dictionary<string, JsonSchemaProperty>? Properties { get; set; }
      
          /// <summary>
          /// List of required property names.
          /// </summary>
          [JsonPropertyName("required")]
          public List<string>? Required { get; set; }
      }
      JsonSchemaProperty.cs
      /// <summary>
      /// Represents a property in a JSON schema.
      /// <see >See the schema for details</see>
      /// </summary>
      internal class JsonSchemaProperty
      {
          /// <summary>
          /// The type of the property. Should be a JSON Schema type and is required.
          /// </summary>
          [JsonPropertyName("type")]
          public string Type { get; set; } = string.Empty;
      
          /// <summary>
          /// A human-readable description of the property.
          /// </summary>
          [JsonPropertyName("description")]
          public string? Description { get; set; } = string.Empty;
      }
      

      接下來創建MCP的擴展類,用于將MCPFunction進行轉換成SemanticKernel Function

      ModelContextProtocolExtensions.cs

      
      /// <summary>
      /// Extension methods for ModelContextProtocol
      /// </summary>
      internal static class ModelContextProtocolExtensions
      {
          /// <summary>
          /// Map the tools exposed on this <see cref="IMcpClient"/> to a collection of <see cref="KernelFunction"/> instances for use with the Semantic Kernel.
          /// <param name="mcpClient">The <see cref="IMcpClient"/>.</param>
          /// <param name="cancellationToken">The optional <see cref="CancellationToken"/>.</param>
          /// </summary>
          internal static async Task<IReadOnlyList<KernelFunction>> MapToFunctionsAsync(this IMcpClient mcpClient, CancellationToken cancellationToken = default)
          {
              var functions = new List<KernelFunction>();
              foreach (var tool in await mcpClient.ListToolsAsync(cancellationToken).ConfigureAwait(false))
              {
                  functions.Add(tool.ToKernelFunction(mcpClient, cancellationToken));
              }
      
              return functions;
          }
      
          private static KernelFunction ToKernelFunction(this McpClientTool tool, IMcpClient mcpClient, CancellationToken cancellationToken)
          {
              async Task<string> InvokeToolAsync(Kernel kernel, KernelFunction function, KernelArguments arguments, CancellationToken ct)
              {
                  try
                  {
                      // Convert arguments to dictionary format expected by ModelContextProtocol
                      Dictionary<string, object?> mcpArguments = [];
                      foreach (var arg in arguments)
                      {
                          if (arg.Value is not null)
                          {
                              mcpArguments[arg.Key] = function.ToArgumentValue(arg.Key, arg.Value);
                          }
                      }
      
                      // Call the tool through ModelContextProtocol
                      var result = await mcpClient.CallToolAsync(
                          tool.Name,
                          mcpArguments.AsReadOnly(),
                          cancellationToken: ct
                      ).ConfigureAwait(false);
      
                      // Extract the text content from the result
                      return string.Join("\n", result.Content
                          .Where(c => c.Type == "text")
                          .Select(c => c.Text));
                  }
                  catch (Exception ex)
                  {
                      await Console.Error.WriteLineAsync($"Error invoking tool '{tool.Name}': {ex.Message}");
      
                      // Rethrowing to allow the kernel to handle the exception
                      throw;
                  }
              }
      
              return KernelFunctionFactory.CreateFromMethod(
                  method: InvokeToolAsync,
                  functionName: tool.Name,
                  description: tool.Description,
                  parameters: tool.ToParameters(),
                  returnParameter: ToReturnParameter()
              );
          }
      
          private static object ToArgumentValue(this KernelFunction function, string name, object value)
          {
              var parameterType = function.Metadata.Parameters.FirstOrDefault(p => p.Name == name)?.ParameterType;
      
              if (parameterType == null)
              {
                  return value;
              }
      
              if (Nullable.GetUnderlyingType(parameterType) == typeof(int))
              {
                  return Convert.ToInt32(value);
              }
      
              if (Nullable.GetUnderlyingType(parameterType) == typeof(double))
              {
                  return Convert.ToDouble(value);
              }
      
              if (Nullable.GetUnderlyingType(parameterType) == typeof(bool))
              {
                  return Convert.ToBoolean(value);
              }
      
              if (parameterType == typeof(List<string>))
              {
                  return (value as IEnumerable<object>)?.ToList() ?? value;
              }
      
              if (parameterType == typeof(Dictionary<string, object>))
              {
                  return (value as Dictionary<string, object>)?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value) ?? value;
              }
      
              return value;
          }
      
          private static List<KernelParameterMetadata>? ToParameters(this McpClientTool tool)
          {
              var inputSchema = JsonSerializer.Deserialize<JsonSchema>(tool.JsonSchema.GetRawText());
              var properties = inputSchema?.Properties;
              if (properties == null)
              {
                  return null;
              }
      
              HashSet<string> requiredProperties = [.. inputSchema!.Required ?? []];
              return properties.Select(kvp =>
                  new KernelParameterMetadata(kvp.Key)
                  {
                      Description = kvp.Value.Description,
                      ParameterType = ConvertParameterDataType(kvp.Value, requiredProperties.Contains(kvp.Key)),
                      IsRequired = requiredProperties.Contains(kvp.Key)
                  }).ToList();
          }
      
          private static KernelReturnParameterMetadata ToReturnParameter()
          {
              return new KernelReturnParameterMetadata
              {
                  ParameterType = typeof(string),
              };
          }
      
          private static Type ConvertParameterDataType(JsonSchemaProperty property, bool required)
          {
              var type = property.Type switch
              {
                  "string" => typeof(string),
                  "integer" => typeof(int),
                  "number" => typeof(double),
                  "boolean" => typeof(bool),
                  "array" => typeof(List<string>),
                  "object" => typeof(Dictionary<string, object>),
                  _ => typeof(object)
              };
      
              return !required && type.IsValueType ? typeof(Nullable<>).MakeGenericType(type) : type;
          }
      }
      

      然后創建SemanticKernel的擴展,對SKFunction進行擴展

      KernelExtensions.cs

      
      /// <summary>
      /// Extension methods for KernelPlugin
      /// </summary>
      public static class KernelExtensions
      {
          private static readonly ConcurrentDictionary<string, IKernelBuilderPlugins> SseMap = new();
      
          /// <summary>
          /// Creates a Model Content Protocol plugin from an SSE server that contains the specified MCP functions and adds it into the plugin collection.
          /// </summary>
          /// <param name="endpoint"></param>
          /// <param name="serverName"></param>
          /// <param name="cancellationToken">The optional <see cref="CancellationToken"/>.</param>
          /// <param name="plugins"></param>
          /// <returns>A <see cref="KernelPlugin"/> containing the functions.</returns>
          public static async Task<IKernelBuilderPlugins> AddMcpFunctionsFromSseServerAsync(this IKernelBuilderPlugins plugins,
              string endpoint, string serverName, CancellationToken cancellationToken = default)
          {
              var key = ToSafePluginName(serverName);
      
              if (SseMap.TryGetValue(key, out var sseKernelPlugin))
              {
                  return sseKernelPlugin;
              }
      
              var mcpClient = await GetClientAsync(serverName, endpoint, null, null, cancellationToken).ConfigureAwait(false);
              var functions = await mcpClient.MapToFunctionsAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
      
              cancellationToken.Register(() => mcpClient.DisposeAsync().ConfigureAwait(false).GetAwaiter().GetResult());
      
              sseKernelPlugin = plugins.AddFromFunctions(key, functions);
              return SseMap[key] = sseKernelPlugin;
          }
      
          private static async Task<IMcpClient> GetClientAsync(string serverName, string? endpoint,
              Dictionary<string, string>? transportOptions, ILoggerFactory? loggerFactory,
              CancellationToken cancellationToken)
          {
              var transportType = !string.IsNullOrEmpty(endpoint) ? TransportTypes.Sse : TransportTypes.StdIo;
      
              McpClientOptions options = new()
              {
                  ClientInfo = new()
                  {
                      Name = $"{serverName} {transportType}Client",
                      Version = "1.0.0"
                  }
              };
      
              var config = new McpServerConfig
              {
                  Id = serverName.ToLowerInvariant(),
                  Name = serverName,
                  Location = endpoint,
                  TransportType = transportType,
                  TransportOptions = transportOptions
              };
      
              return await McpClientFactory.CreateAsync(config, options,
                  loggerFactory: loggerFactory ?? NullLoggerFactory.Instance, cancellationToken: cancellationToken);
          }
      
          // A plugin name can contain only ASCII letters, digits, and underscores.
          private static string ToSafePluginName(string serverName)
          {
              return Regex.Replace(serverName, @"[^\w]", "_");
          }
      }
      
      1. 實現連接MCPServer的Tools

      現在我們就可以實現核心的代碼了,打開我們的Program.cs

      using McpClient;
      using Microsoft.SemanticKernel;
      using Microsoft.SemanticKernel.ChatCompletion;
      using Microsoft.SemanticKernel.Connectors.OpenAI;
      using ChatMessageContent = Microsoft.SemanticKernel.ChatMessageContent;
      
      #pragma warning disable SKEXP0010
      
      var builder = Host.CreateEmptyApplicationBuilder(settings: null);
      
      builder.Configuration
          .AddEnvironmentVariables()
          .AddUserSecrets<Program>();
      
      var kernelBuilder = builder.Services.AddKernel()
          .AddOpenAIChatCompletion("DeepSeek-V3", new Uri("https://openapi.coreshub.cn/v1"), "您使用的https://openapi.coreshub.cn/v1平臺的APIKey");
      
      await kernelBuilder.Plugins.AddMcpFunctionsFromSseServerAsync("http://您的MCPServerip:端口/sse", "token");
      
      Console.ForegroundColor = ConsoleColor.Green;
      Console.WriteLine("MCP Client Started!");
      Console.ResetColor();
      
      var app = builder.Build();
      
      var kernel = app.Services.GetService<Kernel>();
      var chatCompletion = app.Services.GetService<IChatCompletionService>();
      
      PromptForInput();
      while (Console.ReadLine() is string query && !"exit".Equals(query, StringComparison.OrdinalIgnoreCase))
      {
          if (string.IsNullOrWhiteSpace(query))
          {
              PromptForInput();
              continue;
          }
      
          var history = new ChatHistory
          {
              new ChatMessageContent(AuthorRole.System, "下面如果需要計算倆個數的和,請使用我提供的工具。"),
              new ChatMessageContent(AuthorRole.User, query)
          };
      
          await foreach (var message in chatCompletion?.GetStreamingChatMessageContentsAsync(history,
                             new OpenAIPromptExecutionSettings()
                             {
                                 ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
                             }, kernel))
          {
              Console.Write(message.Content);
          }
      
          Console.WriteLine();
      
          PromptForInput();
      }
      
      static void PromptForInput()
      {
          Console.WriteLine("Enter a command (or 'exit' to quit):");
          Console.ForegroundColor = ConsoleColor.Cyan;
          Console.Write("> ");
          Console.ResetColor();
      }
      

      然后開始啟動我們的MCPClient,在此之前需要先修改代碼中的參數改成自己的,然后先啟動MCPServer以后,在啟動我們的MCPClient

      執行以后提問1+1=?然后會得到一下的結果

      在執行之前我們可以先在MCPServer中的算法函數Debug,這樣就可以清晰的看到進入的流程了

      通過上面的案例,恭喜您您已經熟練的掌握了MCPServer+MCPClient+SemanticKernel的入門級教程

      posted on 2025-04-08 17:16  239573049  閱讀(981)  評論(0)    收藏  舉報



      主站蜘蛛池模板: 天堂va蜜桃一区二区三区| 思茅市| h无码精品3d动漫在线观看| 男女激情一区二区三区| 河间市| 日本国产精品第一页久久| 午夜大片免费男女爽爽影院| 少妇熟女视频一区二区三区| 亚洲成片在线看一区二区| 欧美野外伦姧在线观看| 777米奇色狠狠888俺也去乱| 变态另类视频一区二区三区| 中文字幕av国产精品| 在线精品视频一区二区三四| 在线中文字幕国产一区| 日日碰狠狠躁久久躁96avv| 国产精品久久久久AV福利动漫 | 亚洲精品欧美综合二区| 国产无套护士在线观看| 特级做a爰片毛片免费看无码| 亚洲码亚洲码天堂码三区| 国产精品成人午夜福利| 免费拍拍拍网站| 成人性生交片无码免费看| 亚洲av永久一区二区| 国产精品亚洲av三区色| 国产91丝袜在线播放动漫| 国产精品综合在线免费看| 国产成人精品无码专区| 久久精品青青大伊人av| 18禁无遮挡啪啪无码网站| 国产精品久久久久久无毒不卡| 伊人久久大香线蕉AV网禁呦| 粉嫩av一区二区三区蜜臀| 女人腿张开让男人桶爽| 性男女做视频观看网站| 蜜桃成熟色综合久久av| 亚洲一区二区三区四区| 在线看国产精品自拍内射| 亚洲高清av一区二区| 精品人妻伦一二三区久久aaa片|