Skip to content

Commit 23b3ef4

Browse files
committed
HttpClientTransportOAuthTokenHelper to extract and inject the OAuth token, until we get the TokenCache (modelcontextprotocol/csharp-sdk#834).
1 parent 8f82730 commit 23b3ef4

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using ModelContextProtocol.Client;
2+
using System.Reflection;
3+
using System.Text.Json;
4+
5+
/// <summary>
6+
/// Extract and inject the OAuth token, until we get the TokenCache (https://github.com/modelcontextprotocol/csharp-sdk/pull/834).
7+
/// </summary>
8+
public static class HttpClientTransportOAuthTokenHelper
9+
{
10+
public static string? ExtractOAuthToken(this HttpClientTransport httpTransport)
11+
{
12+
var mcpHttpClientField = httpTransport.GetType().GetField("_mcpHttpClient", BindingFlags.NonPublic | BindingFlags.Instance);
13+
var mcpHttpClient = mcpHttpClientField?.GetValue(httpTransport);
14+
var clientOAuthProviderField = (mcpHttpClient?.GetType() as TypeInfo)?.DeclaredFields.FirstOrDefault(df => df.FieldType.FullName == "ModelContextProtocol.Authentication.ClientOAuthProvider");
15+
var clientOAuthProvider = clientOAuthProviderField?.GetValue(mcpHttpClient);
16+
var tokenField = clientOAuthProvider?.GetType().GetField("_token", BindingFlags.NonPublic | BindingFlags.Instance);
17+
var token = tokenField?.GetValue(clientOAuthProvider);
18+
var obtainedAtProperty = token?.GetType().GetProperty("ObtainedAt");
19+
var obtainedAt = obtainedAtProperty?.GetValue(token);
20+
if (token == null || obtainedAt == null) return null;
21+
var tokenJson = JsonSerializer.Serialize(token, token!.GetType());
22+
return JsonSerializer.Serialize(new { tokenJson, obtainedAt });
23+
}
24+
25+
public static void InjectOAuthToken(this HttpClientTransport httpTransport, string? token)
26+
{
27+
if (string.IsNullOrEmpty(token)) return;
28+
var tokenObj = JsonSerializer.Deserialize<JsonElement>(token);
29+
var tokenJson = tokenObj.GetProperty("tokenJson").GetString();
30+
var obtainedAt = tokenObj.GetProperty("obtainedAt").GetDateTimeOffset();
31+
var mcpHttpClientField = httpTransport.GetType().GetField("_mcpHttpClient", BindingFlags.NonPublic | BindingFlags.Instance);
32+
var mcpHttpClient = mcpHttpClientField?.GetValue(httpTransport);
33+
var clientOAuthProviderField = (mcpHttpClient?.GetType() as TypeInfo)?.DeclaredFields.FirstOrDefault(df => df.FieldType.FullName == "ModelContextProtocol.Authentication.ClientOAuthProvider");
34+
var clientOAuthProvider = clientOAuthProviderField?.GetValue(mcpHttpClient);
35+
var tokenField = clientOAuthProvider?.GetType().GetField("_token", BindingFlags.NonPublic | BindingFlags.Instance);
36+
var tokenType = tokenField?.FieldType;
37+
var deserializedToken = JsonSerializer.Deserialize(tokenJson!, tokenType!);
38+
if (deserializedToken != null)
39+
{
40+
var obtainedAtProperty = tokenType!.GetProperty("ObtainedAt");
41+
obtainedAtProperty?.SetValue(deserializedToken, obtainedAt);
42+
tokenField?.SetValue(clientOAuthProvider, deserializedToken);
43+
}
44+
}
45+
}

MyMCPClient.Console/Program.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
using Microsoft.Extensions.AI;
2-
using Microsoft.Extensions.Logging;
32
using ModelContextProtocol.Client;
4-
using System.ClientModel;
53
using System.Diagnostics;
64
using System.Net;
75
using System.Text;
8-
using System.Web;
9-
using System.Linq;
106
using System.Text.Json;
7+
using System.Web;
118

129

1310
// Local tool
@@ -23,7 +20,7 @@
2320
//var tokenResponse = await http.GetAsync($"https://localhost:7296/debug_token?userId={Guid.NewGuid()}&userName={"bob"}");
2421
//var debugtoken = await tokenResponse.Content.ReadFromJsonAsync<string>();
2522
//http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", debugtoken);
26-
await using var mcpClient2 = await McpClient.CreateAsync(new HttpClientTransport(new()
23+
var httpClientTransport = new HttpClientTransport(new()
2724
{
2825
Name = "Vibe MCP Server",
2926
Endpoint = new Uri("http://localhost:5253/bot"),
@@ -37,7 +34,12 @@
3734
Scopes = ["openid", "profile", "verification", "notes", "admin", "offline_access"],//the client we registered supports refresh tokens
3835
TokenCache = new TokenCacheFile("token_cache.json"),
3936
},
40-
}, http));
37+
}, http);
38+
39+
//var token = File.Exists("token.json") ? File.ReadAllText("token.json") : null;
40+
//httpClientTransport.InjectOAuthToken(token);
41+
await using var mcpClient2 = await McpClient.CreateAsync(httpClientTransport);
42+
//File.WriteAllText("token.json", httpClientTransport.ExtractOAuthToken());
4143

4244
/// Taken from https://github.com/modelcontextprotocol/csharp-sdk/blob/c0440760ac363d817cbdca87e1ab7eff7e74a025/samples/ProtectedMCPClient/Program.cs#L72
4345
static async Task<string?> HandleAuthorizationUrlAsync(Uri authorizationUrl, Uri redirectUri, CancellationToken cancellationToken)

0 commit comments

Comments
 (0)