Forge
csharpdeeb25a2
1#nullable enable
2
3using System.Text.Json;
4
5namespace CascadeIDE.Services;
6
7/// <summary>
8/// Имена MCP-прокси (<c>ide_*</c>), которые один-в-один дублируются в MAF-агента как именованные <see cref="Microsoft.Extensions.AI.AIFunction"/>
9/// Параметры тех же типов что у MCP через JSON-объект (схему даёт MCP-каталог).
10/// </summary>
11internal static class CascadeIdeMafPromotedTools
12{
13 /// <summary>Точное совпадение с полем <see cref="IdeMcpToolCatalog.BuildTools"/>/<c>Name</c>.</summary>
14 internal static IEnumerable<string> GetPromotedMcpToolNames(bool includeDebugBuildOnlyExtras)
15 {
16 foreach (var n in NamesCore)
17 yield return n;
18
19 if (includeDebugBuildOnlyExtras)
20 {
21 foreach (var n in DebugOnlyExtras)
22 yield return n;
23 }
24 }
25
26 private static readonly string[] NamesCore =
27 [
28 "ide_get_ide_state",
29 "ide_get_editor_state",
30 "ide_get_editor_content_range",
31 "ide_get_solution_info",
32 "ide_get_solution_files",
33 "ide_get_build_output",
34 "ide_build",
35 "ide_run_tests",
36 "ide_run_affected_tests",
37 "ide_open_file",
38 "ide_load_solution",
39 "ide_go_to_position",
40 "ide_select",
41 "ide_apply_edit",
42 "ide_set_breakpoint",
43 "ide_remove_breakpoint",
44 "ide_get_current_file_diagnostics",
45 "ide_ping",
46 "ide_search_workspace_text",
47 "ide_search_web_public_query",
48 "ide_fetch_web_public_url",
49 "ide_read_agent_notes",
50 "ide_append_agent_notes",
51 "ide_search_agent_notes",
52 "ide_get_ui_layout",
53 "ide_route_context",
54 "ide_read_hot_context",
55 ];
56
57 private static readonly string[] DebugOnlyExtras =
58 [
59 "ide_get_debug_snapshot",
60 "ide_debug_launch",
61 "ide_debug_ping",
62 "ide_list_tools",
63 ];
64
65 internal static HashSet<string> BuildLookup(bool includeDebugBuildOnlyExtras) =>
66 new(GetPromotedMcpToolNames(includeDebugBuildOnlyExtras), StringComparer.Ordinal);
67
68 /// <summary>Маппинг как в <see cref="IdeMcpServer"/> (имя тула MCP → command_id).</summary>
69 internal static bool TryMcpProxyToolToCommandId(string mcpToolName, out string commandId)
70 {
71 commandId = "";
72 if (string.IsNullOrEmpty(mcpToolName))
73 return false;
74 if (!mcpToolName.StartsWith("ide_", StringComparison.Ordinal))
75 return false;
76
77 commandId = mcpToolName["ide_".Length..];
78 if (string.Equals(commandId, IdeCommands.Build, StringComparison.Ordinal))
79 commandId = IdeCommands.BuildStructured;
80 return true;
81 }
82
83 internal static IReadOnlyDictionary<string, JsonElement>? JsonArgsToDict(JsonElement arguments)
84 {
85 var kind = arguments.ValueKind;
86 if (kind is JsonValueKind.Undefined or JsonValueKind.Null)
87 return null;
88 if (kind != JsonValueKind.Object)
89 return null;
90 var dict = new Dictionary<string, JsonElement>(StringComparer.Ordinal);
91 foreach (var p in arguments.EnumerateObject())
92 dict[p.Name] = p.Value;
93 return dict;
94 }
95}
96
View only · write via MCP/CIDE