-
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathServerCommands.cs
More file actions
190 lines (159 loc) · 7.34 KB
/
Copy pathServerCommands.cs
File metadata and controls
190 lines (159 loc) · 7.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
using System;
using System.ComponentModel.Design;
using System.Linq;
using System.Windows;
using CodingWithCalvin.MCPServer.Services;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Task = System.Threading.Tasks.Task;
namespace CodingWithCalvin.MCPServer.Commands;
internal sealed class ServerCommands
{
public static async Task InitializeAsync(AsyncPackage package)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
var commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService == null)
{
return;
}
// Start Server command
var startCommandId = new CommandID(VSCommandTableVsct.guidMCPServerPackageCmdSet.Guid, VSCommandTableVsct.guidMCPServerPackageCmdSet.cmdidStartServer);
var startCommand = new OleMenuCommand(OnStartServer, startCommandId);
startCommand.BeforeQueryStatus += OnBeforeQueryStatusStart;
commandService.AddCommand(startCommand);
// Stop Server command
var stopCommandId = new CommandID(VSCommandTableVsct.guidMCPServerPackageCmdSet.Guid, VSCommandTableVsct.guidMCPServerPackageCmdSet.cmdidStopServer);
var stopCommand = new OleMenuCommand(OnStopServer, stopCommandId);
stopCommand.BeforeQueryStatus += OnBeforeQueryStatusStop;
commandService.AddCommand(stopCommand);
// Restart Server command
var restartCommandId = new CommandID(VSCommandTableVsct.guidMCPServerPackageCmdSet.Guid, VSCommandTableVsct.guidMCPServerPackageCmdSet.cmdidRestartServer);
var restartCommand = new OleMenuCommand(OnRestartServer, restartCommandId);
restartCommand.BeforeQueryStatus += OnBeforeQueryStatusStop;
commandService.AddCommand(restartCommand);
// Copy Server URL command
var copyUrlCommandId = new CommandID(VSCommandTableVsct.guidMCPServerPackageCmdSet.Guid, VSCommandTableVsct.guidMCPServerPackageCmdSet.cmdidCopyServerUrl);
var copyUrlCommand = new OleMenuCommand(OnCopyServerUrl, copyUrlCommandId);
commandService.AddCommand(copyUrlCommand);
// Show Available Tools command
var showToolsCommandId = new CommandID(VSCommandTableVsct.guidMCPServerPackageCmdSet.Guid, VSCommandTableVsct.guidMCPServerPackageCmdSet.cmdidShowTools);
var showToolsCommand = new OleMenuCommand(OnShowTools, showToolsCommandId);
showToolsCommand.BeforeQueryStatus += OnBeforeQueryStatusStop;
commandService.AddCommand(showToolsCommand);
}
private static void EnsureServicesInitialized()
{
MCPServerPackage.Instance?.InitializeServices();
}
private static void OnBeforeQueryStatusStart(object sender, EventArgs e)
{
if (sender is OleMenuCommand command)
{
command.Enabled = MCPServerPackage.ServerManager == null || !MCPServerPackage.ServerManager.IsRunning;
}
}
private static void OnBeforeQueryStatusStop(object sender, EventArgs e)
{
if (sender is OleMenuCommand command)
{
command.Enabled = MCPServerPackage.ServerManager != null && MCPServerPackage.ServerManager.IsRunning;
}
}
private static ServerStartSettings CaptureSettings()
{
ThreadHelper.ThrowIfNotOnUIThread();
var settings = MCPServerPackage.Settings;
return new ServerStartSettings
{
BindingAddress = settings?.BindingAddress ?? "localhost",
Port = settings?.Port ?? 5050,
ServerName = settings?.ServerName ?? "Visual Studio MCP",
LogLevel = settings?.LogLevel.ToString() ?? "Information",
LogRetentionDays = settings?.LogRetentionDays ?? 7,
OutputPane = MCPServerPackage.OutputPaneService?.GetPane()
};
}
private static void OnStartServer(object sender, EventArgs e)
{
// Capture everything we need on UI thread before going to background
EnsureServicesInitialized();
var serverManager = MCPServerPackage.ServerManager;
if (serverManager == null) return;
var startSettings = CaptureSettings();
_ = Task.Run(async () =>
{
await serverManager.StartAsync(startSettings);
// Refresh command states on UI thread after server starts
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
System.Windows.Input.CommandManager.InvalidateRequerySuggested();
});
}
private static void OnStopServer(object sender, EventArgs e)
{
var serverManager = MCPServerPackage.ServerManager;
if (serverManager == null) return;
_ = Task.Run(async () =>
{
await serverManager.StopAsync();
// Refresh command states on UI thread after server stops
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
System.Windows.Input.CommandManager.InvalidateRequerySuggested();
});
}
private static void OnRestartServer(object sender, EventArgs e)
{
var serverManager = MCPServerPackage.ServerManager;
if (serverManager == null) return;
var startSettings = CaptureSettings();
_ = Task.Run(async () =>
{
await serverManager.StopAsync();
await serverManager.StartAsync(startSettings);
// Refresh command states on UI thread after server restarts
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
System.Windows.Input.CommandManager.InvalidateRequerySuggested();
});
}
private static void OnCopyServerUrl(object sender, EventArgs e)
{
var port = MCPServerPackage.Settings?.Port ?? 5050;
var url = $"http://localhost:{port}/sse";
Clipboard.SetText(url);
}
private static void OnShowTools(object sender, EventArgs e)
{
ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
if (MCPServerPackage.Instance == null)
{
return;
}
if (MCPServerPackage.RpcServer == null || !MCPServerPackage.RpcServer.IsConnected)
{
VsShellUtilities.ShowMessageBox(
MCPServerPackage.Instance,
"Server is not connected. Start the server first.",
"VS MCP Server",
OLEMSGICON.OLEMSGICON_INFO,
OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
return;
}
var tools = await MCPServerPackage.RpcServer.GetAvailableToolsAsync();
var message = tools.Count == 0
? "No tools available."
: string.Join("\n", tools.GroupBy(t => t.Category).OrderBy(g => g.Key)
.SelectMany(g => new[] { $"\n{g.Key.ToUpperInvariant()} TOOLS:" }
.Concat(g.OrderBy(t => t.Name).Select(t => $" {t.Name}"))));
VsShellUtilities.ShowMessageBox(
MCPServerPackage.Instance,
message,
"VS MCP Server - Available Tools",
OLEMSGICON.OLEMSGICON_INFO,
OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
});
}
}