Skip to content
This repository was archived by the owner on Mar 21, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 42 additions & 42 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,7 @@ McpServerConfig config = new()
}
};

var factory = new McpClientFactory([config], options, NullLoggerFactory.Instance);

var client = await factory.GetClientAsync("everything");
var client = await McpClientFactory.CreateAsync(config, options);

// Print the list of tools available from the server.
await foreach (var tool in client.ListToolsAsync())
Expand Down Expand Up @@ -136,63 +134,65 @@ using McpDotNet.Protocol.Types;
using McpDotNet.Server;
using Microsoft.Extensions.Logging.Abstractions;

var loggerFactory = NullLoggerFactory.Instance;
McpServerOptions options = new()
{
ServerInfo = new() { Name = "MyServer", Version = "1.0.0" },
Capabilities = new() { Tools = new() },
};
McpServerFactory factory = new(new StdioServerTransport("MyServer", loggerFactory), options, loggerFactory);
IMcpServer server = factory.CreateServer();

server.SetListToolsHandler(async (request, cancellationToken) =>
{
return new ListToolsResult()
Capabilities = new()
{
Tools =
[
new Tool()
Tools = new()
{
ListToolsHandler = async (request, cancellationToken) =>
{
Name = "echo",
Description = "Echoes the input back to the client.",
InputSchema = new JsonSchema()
return new ListToolsResult()
{
Type = "object",
Properties = new Dictionary<string, JsonSchemaProperty>()
Tools =
[
new Tool()
{
Name = "echo",
Description = "Echoes the input back to the client.",
InputSchema = new JsonSchema()
{
Type = "object",
Properties = new Dictionary<string, JsonSchemaProperty>()
{
["message"] = new JsonSchemaProperty() { Type = "string", Description = "The input to echo back." }
}
},
}
]
};
},

CallToolHandler = async (request, cancellationToken) =>
{
if (request.Params?.Name == "echo")
{
if (request.Params.Arguments?.TryGetValue("message", out var message) is not true)
{
["message"] = new JsonSchemaProperty() { Type = "string", Description = "The input to echo back." }
throw new McpServerException("Missing required argument 'message'");
}
},
}
]
};
});

server.SetCallToolHandler(async (request, cancellationToken) =>
{
if (request.Params?.Name == "echo")
{
if (request.Params.Arguments?.TryGetValue("message", out var message) is not true)
{
throw new McpServerException("Missing required argument 'message'");
}
return new CallToolResponse()
{
Content = [new Content() { Text = $"Echo: {message}", Type = "text" }]
};
}

return new CallToolResponse()
{
Content = [new Content() { Text = $"Echo: {message}", Type = "text" }]
};
}
throw new McpServerException($"Unknown tool: '{request.Params?.Name}'");
},
}
},
};

throw new McpServerException($"Unknown tool: '{request.Params?.Name}'");
});
await using IMcpServer server = McpServerFactory.Create(new StdioServerTransport("MyServer"), options);

await server.StartAsync();

// Run until process is stopped by the client (parent process)
await Task.Delay(Timeout.Infinite);
```


## Roadmap

- Expand documentation with detailed guides for:
Expand Down
23 changes: 7 additions & 16 deletions samples/anthropic/tools/ToolsConsole/Program.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
using Anthropic.SDK;
using Anthropic.SDK.Constants;
using Anthropic.SDK.Messaging;
using System.Linq;
using McpDotNet;
using McpDotNet.Client;
using McpDotNet.Configuration;
using McpDotNet.Protocol.Transport;
using Microsoft.Extensions.Logging.Abstractions;

internal class Program
{
private static async Task<IMcpClient> GetMcpClientAsync()
{

McpClientOptions options = new()
McpClientOptions clientOptions = new()
{
ClientInfo = new() { Name = "SimpleToolsConsole", Version = "1.0.0" }
};

var config = new McpServerConfig
McpServerConfig serverConfig = new()
{
Id = "everything",
Name = "Everything",
Expand All @@ -30,21 +27,15 @@ private static async Task<IMcpClient> GetMcpClientAsync()
}
};

var factory = new McpClientFactory(
[config],
options,
NullLoggerFactory.Instance
);

return await factory.GetClientAsync("everything");
return await McpClientFactory.CreateAsync(serverConfig, clientOptions);
}

private static async Task Main(string[] args)
{
try
{
Console.WriteLine("Initializing MCP 'everything' server");
var client = await GetMcpClientAsync();
await using var client = await GetMcpClientAsync();
Console.WriteLine("MCP 'everything' server initialized");
Console.WriteLine("Listing tools...");
var tools = await client.ListToolsAsync().ToListAsync();
Expand All @@ -60,10 +51,10 @@ private static async Task Main(string[] args)

Console.WriteLine("Asking Claude to call the Echo Tool...");

var messages = new List<Message>
{
List<Message> messages =
[
new Message(RoleType.User, "Please call the echo tool with the string 'Hello MCP!' and show me the echoed response.")
};
];

var parameters = new MessageParameters()
{
Expand Down
16 changes: 4 additions & 12 deletions samples/microsoft.extensions.ai/tools/ToolsConsole/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@
using McpDotNet.Extensions.AI;
using McpDotNet.Protocol.Transport;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging.Abstractions;
using OpenAI;

internal class Program
{
private static async Task<IMcpClient> GetMcpClientAsync()
{

McpClientOptions options = new()
McpClientOptions clientOptions = new()
{
ClientInfo = new() { Name = "SimpleToolsConsole", Version = "1.0.0" }
};

var config = new McpServerConfig
McpServerConfig serverConfig = new()
{
Id = "everything",
Name = "Everything",
Expand All @@ -28,21 +26,15 @@ private static async Task<IMcpClient> GetMcpClientAsync()
}
};

var factory = new McpClientFactory(
[config],
options,
NullLoggerFactory.Instance
);

return await factory.GetClientAsync("everything");
return await McpClientFactory.CreateAsync(serverConfig, clientOptions);
}

private static async Task Main(string[] args)
{
try
{
Console.WriteLine("Initializing MCP 'everything' server");
var client = await GetMcpClientAsync();
await using var client = await GetMcpClientAsync();
Console.WriteLine("MCP 'everything' server initialized");
Console.WriteLine("Listing tools...");
var mappedTools = await client.ListToolsAsync().Select(t => t.ToAITool(client)).ToListAsync();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Runtime.CompilerServices;

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
internal sealed class CallerArgumentExpressionAttribute : Attribute
{
public CallerArgumentExpressionAttribute(string parameterName)
{
ParameterName = parameterName;
}

public string ParameterName { get; }
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Text;

namespace System.Threading.Tasks;

internal static class CancellationTokenSourceExtensions
Expand Down
21 changes: 9 additions & 12 deletions src/McpDotNet.Extensions.AI/McpSessionScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using McpDotNet.Configuration;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace McpDotNet.Extensions.AI;

Expand Down Expand Up @@ -45,7 +44,7 @@ public static async Task<McpSessionScope> CreateAsync(McpServerConfig serverConf
}

var scope = new McpSessionScope();
var client = await scope.AddClientAsync(serverConfig, options, loggerFactory).ConfigureAwait(false);
var client = await AddClientAsync(serverConfig, options, loggerFactory).ConfigureAwait(false);

scope.Tools = [];
await foreach (var tool in client.ListToolsAsync().ConfigureAwait(false))
Expand Down Expand Up @@ -81,7 +80,7 @@ public static async Task<McpSessionScope> CreateAsync(IEnumerable<McpServerConfi

foreach (var config in serverConfigs)
{
var client = await scope.AddClientAsync(config, options, loggerFactory).ConfigureAwait(false);
var client = await AddClientAsync(config, options, loggerFactory).ConfigureAwait(false);

scope.Tools ??= [];
await foreach (var tool in client.ListToolsAsync().ConfigureAwait(false))
Expand All @@ -95,17 +94,15 @@ public static async Task<McpSessionScope> CreateAsync(IEnumerable<McpServerConfi
return scope;
}

private async Task<IMcpClient> AddClientAsync(McpServerConfig config,
McpClientOptions? options,
private static Task<IMcpClient> AddClientAsync(
McpServerConfig serverConfig,
McpClientOptions? clientOptions,
ILoggerFactory? loggerFactory = null)
{
using var factory = new McpClientFactory([config],
options ?? new() { ClientInfo = new() { Name = "AnonymousClient", Version = "1.0.0.0" } },
loggerFactory ?? NullLoggerFactory.Instance);
factory.DisposeClientsOnDispose = false;
var client = await factory.GetClientAsync(config.Id).ConfigureAwait(false);
_clients.Add(client);
return client;
return McpClientFactory.CreateAsync(
serverConfig,
clientOptions ?? new() { ClientInfo = new() { Name = "AnonymousClient", Version = "1.0.0.0" } },
loggerFactory: loggerFactory);
}

/// <inheritdoc/>
Expand Down
21 changes: 0 additions & 21 deletions src/mcpdotnet/Client/IMcpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,6 @@ public interface IMcpClient : IAsyncDisposable
/// </summary>
string? ServerInstructions { get; }

/// <summary>Sets a handler for the named operation.</summary>
/// <param name="operationName">The name of the operation.</param>
/// <param name="handler">The handler. Each operation requires a specific delegate signature.</param>
/// <remarks>
/// <para>
/// Each operation may have only a single handler. Setting a handler for an operation that already has one
/// will replace the existing handler.
/// </para>
/// <para>
/// <see cref="OperationNames"> provides constants for common operations.</see>
/// </para>
/// </remarks>
void SetOperationHandler(string operationName, Delegate handler);

/// <summary>
/// Adds a handler for server notifications of a specific method.
/// </summary>
Expand All @@ -60,13 +46,6 @@ public interface IMcpClient : IAsyncDisposable
/// </remarks>
void AddNotificationHandler(string method, Func<JsonRpcNotification, Task> handler);

/// <summary>
/// Establishes a connection to the server.
/// </summary>
/// <param name="cancellationToken">A token to cancel the operation.</param>
/// <returns>A task representing the asynchronous operation.</returns>
Task ConnectAsync(CancellationToken cancellationToken = default);

/// <summary>
/// Sends a generic JSON-RPC request to the server.
/// </summary>
Expand Down
Loading