Skip to content

Commit 0bd80e6

Browse files
committed
Experimental changes in a different direction
1 parent bac97ef commit 0bd80e6

19 files changed

+1777
-1
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,7 @@ docs/api
8080

8181
# Rider
8282
.idea/
83-
.idea_modules/
83+
.idea_modules/
84+
85+
# Misc project metadata
86+
.specs/
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// filepath: c:\Users\ddelimarsky\source\csharp-sdk-anm\samples\SecureWeatherClient\Program.cs
2+
using System.Net.Http;
3+
using System.Threading.Tasks;
4+
using ModelContextProtocol.Auth;
5+
using ModelContextProtocol.Client;
6+
using ModelContextProtocol.Protocol.Transport;
7+
8+
namespace SecureWeatherClient;
9+
10+
class Program
11+
{
12+
// The URI for our OAuth redirect - in a real app, this would be a registered URI or a local server
13+
private static readonly Uri RedirectUri = new("http://localhost:8888/oauth-callback");
14+
15+
static async Task Main(string[] args)
16+
{
17+
Console.WriteLine("MCP Secure Weather Client with OAuth Authentication");
18+
Console.WriteLine("==================================================");
19+
Console.WriteLine();
20+
21+
// Create an HTTP client with OAuth handling
22+
var oauthHandler = new OAuthDelegatingHandler(
23+
redirectUri: RedirectUri,
24+
clientName: "SecureWeatherClient",
25+
scopes: new[] { "weather.read" },
26+
authorizationHandler: HandleAuthorizationRequestAsync);
27+
28+
var httpClient = new HttpClient(oauthHandler);
29+
var serverUrl = "http://localhost:5000"; // Default server URL
30+
31+
// Allow the user to specify a different server URL
32+
Console.WriteLine($"Server URL (press Enter for default: {serverUrl}):");
33+
var userInput = Console.ReadLine();
34+
if (!string.IsNullOrWhiteSpace(userInput))
35+
{
36+
serverUrl = userInput;
37+
}
38+
39+
Console.WriteLine();
40+
Console.WriteLine($"Connecting to weather server at {serverUrl}...");
41+
42+
// Create an MCP client with the server URL
43+
var client = new McpClient(new Uri(serverUrl), httpClient);
44+
45+
try
46+
{
47+
// Get the list of available tools
48+
var tools = await client.GetToolsAsync();
49+
if (tools.Count == 0)
50+
{
51+
Console.WriteLine("No tools available on the server.");
52+
return;
53+
}
54+
55+
Console.WriteLine($"Found {tools.Count} tools on the server.");
56+
Console.WriteLine();
57+
58+
// Find the weather tool
59+
var weatherTool = tools.FirstOrDefault(t => t.Name == "get_weather");
60+
if (weatherTool == null)
61+
{
62+
Console.WriteLine("The server does not provide a weather tool.");
63+
return;
64+
}
65+
66+
// Get the weather for different locations
67+
string[] locations = { "New York", "London", "Tokyo", "Sydney", "Moscow" };
68+
69+
foreach (var location in locations)
70+
{
71+
try
72+
{
73+
Console.WriteLine($"Getting weather for {location}...");
74+
var result = await client.InvokeToolAsync(weatherTool.Name, new Dictionary<string, object>
75+
{
76+
["location"] = location
77+
});
78+
79+
if (result.TryGetValue("temperature", out var temperature) &&
80+
result.TryGetValue("conditions", out var conditions) &&
81+
result.TryGetValue("humidity", out var humidity) &&
82+
result.TryGetValue("windSpeed", out var windSpeed))
83+
{
84+
Console.WriteLine($"Weather in {location}:");
85+
Console.WriteLine($" Temperature: {temperature}°C");
86+
Console.WriteLine($" Conditions: {conditions}");
87+
Console.WriteLine($" Humidity: {humidity}%");
88+
Console.WriteLine($" Wind speed: {windSpeed} km/h");
89+
}
90+
else
91+
{
92+
Console.WriteLine($"Invalid response format for {location}");
93+
}
94+
}
95+
catch (Exception ex)
96+
{
97+
Console.WriteLine($"Error getting weather for {location}: {ex.Message}");
98+
}
99+
100+
Console.WriteLine();
101+
}
102+
}
103+
catch (Exception ex)
104+
{
105+
Console.WriteLine($"Error: {ex.Message}");
106+
}
107+
108+
Console.WriteLine("Press any key to exit...");
109+
Console.ReadKey();
110+
}
111+
112+
/// <summary>
113+
/// Handles the OAuth authorization request by showing the URL to the user and getting the authorization code.
114+
/// In a real application, this would launch a browser and listen for the callback.
115+
/// </summary>
116+
private static Task<string> HandleAuthorizationRequestAsync(Uri authorizationUri)
117+
{
118+
Console.WriteLine();
119+
Console.WriteLine("Authentication Required");
120+
Console.WriteLine("======================");
121+
Console.WriteLine();
122+
Console.WriteLine("Please open the following URL in your browser to authenticate:");
123+
Console.WriteLine(authorizationUri);
124+
Console.WriteLine();
125+
Console.WriteLine("After authentication, you will be redirected to a page with a code.");
126+
Console.WriteLine("Please enter the code parameter from the URL:");
127+
128+
var authorizationCode = Console.ReadLine();
129+
if (string.IsNullOrWhiteSpace(authorizationCode))
130+
{
131+
throw new InvalidOperationException("Authorization code is required.");
132+
}
133+
134+
return Task.FromResult(authorizationCode);
135+
}
136+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!-- filepath: c:\Users\ddelimarsky\source\csharp-sdk-anm\samples\SecureWeatherClient\SecureWeatherClient.csproj -->
2+
<Project Sdk="Microsoft.NET.Sdk">
3+
4+
<PropertyGroup>
5+
<OutputType>Exe</OutputType>
6+
<TargetFramework>net8.0</TargetFramework>
7+
<Nullable>enable</Nullable>
8+
<ImplicitUsings>enable</ImplicitUsings>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<ProjectReference Include="..\..\src\ModelContextProtocol\ModelContextProtocol.csproj" />
13+
</ItemGroup>
14+
15+
</Project>

0 commit comments

Comments
 (0)