Forge
csharpb1bb0b24
1using System.Collections.Frozen;
2using System.Text.Json;
3using ModelContextProtocol.Protocol;
4using ModelContextProtocol.Server;
5using OpenAgentRegistry.Mcp;
6
7const string DefaultBaseUrl = "http://127.0.0.1:8765";
8
9var baseUrl = Environment.GetEnvironmentVariable("OAR_BASE_URL")?.Trim();
10if (string.IsNullOrWhiteSpace(baseUrl))
11 baseUrl = DefaultBaseUrl;
12
13if (!Uri.TryCreate(baseUrl, UriKind.Absolute, out var baseUri))
14{
15 Console.Error.WriteLine("OAR_BASE_URL must be an absolute URL.");
16 return 1;
17}
18
19using var http = new HttpClient { BaseAddress = baseUri };
20http.DefaultRequestHeaders.Accept.ParseAdd("application/json");
21
22var client = new RegistryApiClient(http);
23var toolsList = ToolCatalog.Build();
24
25var options = new McpServerOptions
26{
27 ServerInfo = new Implementation { Name = "OpenAgentRegistryMcp", Version = "0.1.0" },
28 ServerInstructions = ServerInstructions.Text,
29 ProtocolVersion = "2024-11-05",
30 Capabilities = new ServerCapabilities { Tools = new ToolsCapability { ListChanged = false } },
31 Handlers = new McpServerHandlers
32 {
33 ListToolsHandler = (_, _) => ValueTask.FromResult(new ListToolsResult { Tools = toolsList }),
34 CallToolHandler = async (request, cancellationToken) =>
35 {
36 var name = request.Params?.Name ?? "";
37 var args = request.Params?.Arguments is IReadOnlyDictionary<string, JsonElement> dictionary
38 ? dictionary
39 : FrozenDictionary<string, JsonElement>.Empty;
40
41 try
42 {
43 var result = await ToolHandlers.HandleAsync(name, client, args, cancellationToken).ConfigureAwait(false);
44 return new CallToolResult
45 {
46 Content = [new TextContentBlock { Text = result.Body }],
47 IsError = !result.IsSuccess,
48 };
49 }
50 catch (ArgumentException ex)
51 {
52 return Error(ex.Message);
53 }
54 catch (HttpRequestException ex)
55 {
56 return Error($"Registry unreachable at {baseUri}: {ex.Message}");
57 }
58 catch (Exception ex)
59 {
60 return Error(ex.Message);
61 }
62 },
63 },
64};
65
66static CallToolResult Error(string message) =>
67 new()
68 {
69 Content = [new TextContentBlock { Text = $"Error: {message}" }],
70 IsError = true,
71 };
72
73var transport = new StdioServerTransport("OpenAgentRegistryMcp");
74await using var server = McpServer.Create(transport, options);
75await server.RunAsync();
76return 0;
77
View only · write via MCP/CIDE