Skip to content

Commit 12c9b94

Browse files
committed
Refactoring
1 parent 70d9bb9 commit 12c9b94

File tree

4 files changed

+225
-155
lines changed

4 files changed

+225
-155
lines changed

src/WinGetMCPServer/Program.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
using Microsoft.Extensions.DependencyInjection;
2-
using Microsoft.Extensions.Hosting;
3-
using Microsoft.Extensions.Logging;
4-
using ModelContextProtocol.Protocol;
5-
using ModelContextProtocol.Server;
1+
// -----------------------------------------------------------------------------
2+
// <copyright file="Program.cs" company="Microsoft Corporation">
3+
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
4+
// </copyright>
5+
// -----------------------------------------------------------------------------
66

77
namespace WinGetMCPServer
88
{
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.Hosting;
11+
using Microsoft.Extensions.Logging;
12+
using ModelContextProtocol.Protocol;
13+
914
internal class Program
1015
{
1116
private const string ServerName = "winget-mcp";
@@ -24,7 +29,7 @@ static void Main(string[] args)
2429
configureOptions.ServerInfo = new Implementation() { Name = ServerName, Version = ServerVersion };
2530
})
2631
.WithStdioServerTransport()
27-
.WithTools<WingetPackage_Reflection>();
32+
.WithTools<WingetPackageTools>();
2833

2934
builder.Build().Run();
3035
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// -----------------------------------------------------------------------------
2+
// <copyright file="PackageResponse.cs" company="Microsoft Corporation">
3+
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
4+
// </copyright>
5+
// -----------------------------------------------------------------------------
6+
7+
namespace WinGetMCPServer.Response
8+
{
9+
using Microsoft.Management.Deployment;
10+
using ModelContextProtocol.Protocol;
11+
using System.Text.Json;
12+
13+
/// <summary>
14+
/// Contains reusable responses for package tools.
15+
/// </summary>
16+
internal static class PackageResponse
17+
{
18+
public static CallToolResponse ResponseForConnectError(ConnectResult connectResult)
19+
{
20+
return new CallToolResponse()
21+
{
22+
IsError = true,
23+
Content = [new Content() { Text = $"Failed when connecting to the WinGet package catalog with error: {connectResult.ExtendedErrorCode.Message} [0x{connectResult.ExtendedErrorCode.HResult:X8}]" }],
24+
};
25+
}
26+
27+
public static CallToolResponse ResponseForFindError(FindPackagesResult findResult)
28+
{
29+
return new CallToolResponse()
30+
{
31+
IsError = true,
32+
Content = [new Content() { Text = $"Failed when finding packages with reason {findResult.Status} and error: {findResult.ExtendedErrorCode.Message} [0x{findResult.ExtendedErrorCode.HResult:X8}]" }],
33+
};
34+
}
35+
36+
public static CallToolResponse ResponseForCancelBeforeSystemChange()
37+
{
38+
return new CallToolResponse()
39+
{
40+
IsError = true,
41+
Content = [new Content() { Text = $"The operation was cancelled before any system change was started" }],
42+
};
43+
}
44+
45+
public static CallToolResponse ResponseForEmptyFind(string identifer, string? catalog)
46+
{
47+
PackageIdentityErrorResult result = new()
48+
{
49+
Message = "Did not find a package with the requested identifier",
50+
Identifier = identifer,
51+
Catalog = catalog,
52+
};
53+
54+
return ResponseFromObject(result);
55+
}
56+
57+
public static CallToolResponse ResponseForMultiFind(string identifer, string? catalog, FindPackagesResult findResult)
58+
{
59+
PackageIdentityErrorResult result = new()
60+
{
61+
Message = "Found multiple packages matching the requested identifier; provide a more specific identifier and/or catalog",
62+
Identifier = identifer,
63+
Catalog = catalog,
64+
};
65+
66+
AddFoundPackagesToList(result.Packages, findResult);
67+
68+
return ResponseFromObject(result);
69+
}
70+
71+
public static CallToolResponse ResponseForInstallOperation(InstallResult installResult, FindPackagesResult? findResult)
72+
{
73+
InstallOperationResult result = new InstallOperationResult();
74+
75+
switch (installResult.Status)
76+
{
77+
case InstallResultStatus.Ok:
78+
result.Message = "Install completed successfully";
79+
break;
80+
case InstallResultStatus.BlockedByPolicy:
81+
result.Message = "Installation was blocked by policy";
82+
break;
83+
case InstallResultStatus.CatalogError:
84+
result.Message = "An error occurred with the catalog";
85+
break;
86+
case InstallResultStatus.InternalError:
87+
result.Message = "An internal WinGet error occurred";
88+
break;
89+
case InstallResultStatus.InvalidOptions:
90+
result.Message = "The install options were invalid";
91+
break;
92+
case InstallResultStatus.DownloadError:
93+
result.Message = "An error occurred while downloading the package installer";
94+
break;
95+
case InstallResultStatus.InstallError:
96+
result.Message = "The package installer failed during installation";
97+
break;
98+
case InstallResultStatus.ManifestError:
99+
result.Message = "The package manifest was invalid";
100+
break;
101+
case InstallResultStatus.NoApplicableInstallers:
102+
result.Message = "No applicable package installers were available for this system";
103+
break;
104+
case InstallResultStatus.NoApplicableUpgrade:
105+
result.Message = "No applicable upgrade was available for this system";
106+
break;
107+
case InstallResultStatus.PackageAgreementsNotAccepted:
108+
result.Message = "The package requires accepting agreements; please install manually";
109+
break;
110+
default:
111+
result.Message = "Unknown install status";
112+
break;
113+
}
114+
115+
if (installResult.RebootRequired)
116+
{
117+
result.RebootRequired = true;
118+
}
119+
120+
result.ErrorCode = installResult.ExtendedErrorCode?.HResult;
121+
122+
if (installResult.Status == InstallResultStatus.InstallError)
123+
{
124+
result.InstallerErrorCode = installResult.InstallerErrorCode;
125+
}
126+
127+
if (findResult != null && findResult.Status == FindPackagesResultStatus.Ok && findResult.Matches?.Count == 1)
128+
{
129+
result.InstalledPackageInformation = FindPackageResultFromCatalogPackage(findResult.Matches[0].CatalogPackage);
130+
}
131+
132+
return ResponseFromObject(result, installResult.Status != InstallResultStatus.Ok);
133+
}
134+
}
135+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// -----------------------------------------------------------------------------
2+
// <copyright file="ToolResponse.cs" company="Microsoft Corporation">
3+
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
4+
// </copyright>
5+
// -----------------------------------------------------------------------------
6+
7+
namespace WinGetMCPServer.Response
8+
{
9+
using ModelContextProtocol.Protocol;
10+
using System.Text.Json;
11+
using System.Text.Json.Serialization;
12+
13+
/// <summary>
14+
/// Contains reusable responses for tools.
15+
/// </summary>
16+
internal static class ToolResponse
17+
{
18+
/// <summary>
19+
/// Constructs a response from an object.
20+
/// </summary>
21+
/// <param name="value">The object to return in the response.</param>
22+
/// <param name="isError">Whether or not the response is an error.</param>
23+
/// <returns>The response.</returns>
24+
public static CallToolResponse FromObject(object value, bool isError = false)
25+
{
26+
return FromObject(value, isError, GetDefaultJsonOptions());
27+
}
28+
29+
/// <summary>
30+
/// Constructs a response from an object.
31+
/// </summary>
32+
/// <param name="value">The object to return in the response.</param>
33+
/// <param name="isError">Whether or not the response is an error.</param>
34+
/// <param name="jsonSerializerOptions">The JSON serializer options for serializing the object.</param>
35+
/// <returns>The response.</returns>
36+
public static CallToolResponse FromObject(object value, bool isError = false, JsonSerializerOptions jsonSerializerOptions)
37+
{
38+
return new CallToolResponse()
39+
{
40+
IsError = isError,
41+
Content = [new Content() { Text = JsonSerializer.Serialize(value, GetDefaultJsonOptions()) }]
42+
};
43+
}
44+
45+
/// <summary>
46+
/// Gets the default serialization options.
47+
/// </summary>
48+
/// <returns>The default serialization options.</returns>
49+
public static JsonSerializerOptions GetDefaultJsonOptions()
50+
{
51+
return new JsonSerializerOptions()
52+
{
53+
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
54+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
55+
Converters =
56+
{
57+
new JsonStringEnumConverter(),
58+
},
59+
};
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)