Skip to content

Commit 2c852f0

Browse files
authored
Update README to work with latest code (#70)
1 parent 9e92bc9 commit 2c852f0

File tree

1 file changed

+67
-72
lines changed

1 file changed

+67
-72
lines changed

README.MD

Lines changed: 67 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -54,44 +54,41 @@ dotnet add package mcpdotnet
5454

5555
Then create a client and start using tools, or other capabilities, from the servers you configure:
5656
```csharp
57-
var options = new McpClientOptions()
58-
{ ClientInfo = new() { Name = "TestClient", Version = "1.0.0" } };
57+
McpClientOptions options = new()
58+
{
59+
ClientInfo = new() { Name = "TestClient", Version = "1.0.0" }
60+
};
5961

60-
var config = new McpServerConfig
61-
{
62-
Id = "everything",
63-
Name = "Everything",
64-
TransportType = TransportTypes.StdIo,
65-
TransportOptions = new Dictionary<string, string>
66-
{
67-
["command"] = "npx",
68-
["arguments"] = "-y @modelcontextprotocol/server-everything",
69-
}
70-
};
62+
McpServerConfig config = new()
63+
{
64+
Id = "everything",
65+
Name = "Everything",
66+
TransportType = TransportTypes.StdIo,
67+
TransportOptions = new()
68+
{
69+
["command"] = "npx",
70+
["arguments"] = "-y @modelcontextprotocol/server-everything",
71+
}
72+
};
7173

72-
var factory = new McpClientFactory(
73-
[config],
74-
options,
75-
NullLoggerFactory.Instance
76-
);
74+
var factory = new McpClientFactory([config], options, NullLoggerFactory.Instance);
7775

7876
var client = await factory.GetClientAsync("everything");
7977

80-
// Get the list of tools, for passing to an LLM
81-
var tools = await client.ListToolsAsync();
78+
// Print the list of tools available from the server.
79+
await foreach (var tool in client.ListToolsAsync())
80+
{
81+
Console.WriteLine($"{tool.Name} ({tool.Description})");
82+
}
8283

83-
// Execute a tool, in practice this would normally be driven by LLM tool invocations
84+
// Execute a tool (this would normally be driven by LLM tool invocations).
8485
var result = await client.CallToolAsync(
85-
"echo",
86-
new Dictionary<string, object>
87-
{
88-
["message"] = "Hello MCP!"
89-
},
90-
CancellationToken.None
91-
);
86+
"echo",
87+
new() { ["message"] = "Hello MCP!" },
88+
CancellationToken.None);
9289

9390
// echo always returns one and only one text content object
94-
Console.WriteLine(result.Content.FirstOrDefault(c => c.Type == "text").Text);
91+
Console.WriteLine(result.Content.First(c => c.Type == "text").Text);
9592
```
9693

9794
Note that you should pass CancellationToken objects suitable for your use case, to enable proper error handling, timeouts, etc. This example also does not paginate the tools list, which may be necessary for large tool sets. See the IntegrationTests project for an example of pagination, as well as examples of how to handle Prompts and Resources.
@@ -107,52 +104,54 @@ Remember you can connect to any MCP server, not just ones created using mcpdotne
107104
## Getting Started (Server)
108105

109106
Here is an example of how to create an MCP server and register all tools from the current application.
107+
It includes a simple echo tool as an example (this is included in the same file here for easy of copy and paste, but it needn't be in the same file...
108+
the employed overload of `WithTools` examines the current assembly for classes with the `McpToolType` attribute, and registers all methods with the
109+
`McpTool` attribute as tools.)
110110

111111
```csharp
112-
var builder = Host.CreateApplicationBuilder(args);
113-
builder.Services.AddMcpServer()
112+
using McpDotNet;
113+
using McpDotNet.Server;
114+
using Microsoft.Extensions.Hosting;
115+
using System.ComponentModel;
116+
117+
var builder = Host.CreateEmptyApplicationBuilder(settings: null);
118+
builder.Services
119+
.AddMcpServer()
114120
.WithStdioServerTransport()
115-
.WithTools()
116-
117-
var app = builder.Build();
118-
119-
await app.RunAsync();
120-
```
121+
.WithTools();
122+
await builder.Build().RunAsync();
121123

122-
The `EchoTool` class is a simple example of a tool implementation:
123-
```csharp
124124
[McpToolType]
125125
public static class EchoTool
126126
{
127-
[McpTool(Description = "Echoes the input back to the client.")]
128-
public static string Echo([McpParameter(true)] string message)
129-
{
130-
return "hello " + message;
131-
}
127+
[McpTool, Description("Echoes the message back to the client.")]
128+
public static string Echo(string message) => $"hello {message}";
132129
}
133130
```
134131

135-
Here is an example of how to create an MCP server manually with a single tool. You can also refer to the TestServer in the tests folder, which implements a wider range of capabilities.
136-
132+
More control is also available, with fine-grained control over configuring the server and how it should handle client requests. For example:
137133
```csharp
138-
McpServerOptions options = new McpServerOptions()
134+
using McpDotNet.Protocol.Transport;
135+
using McpDotNet.Protocol.Types;
136+
using McpDotNet.Server;
137+
using Microsoft.Extensions.Logging.Abstractions;
138+
139+
var loggerFactory = NullLoggerFactory.Instance;
140+
McpServerOptions options = new()
139141
{
140-
ServerInfo = new Implementation() { Name = "MyServer", Version = "1.0.0" },
141-
Capabilities = new ServerCapabilities()
142-
{
143-
Tools = new()
144-
}
142+
ServerInfo = new() { Name = "MyServer", Version = "1.0.0" },
143+
Capabilities = new() { Tools = new() },
145144
};
146-
McpServerFactory factory = new McpServerFactory(new StdioServerTransport("MyServer", loggerFactory), options, loggerFactory);
145+
McpServerFactory factory = new(new StdioServerTransport("MyServer", loggerFactory), options, loggerFactory);
147146
IMcpServer server = factory.CreateServer();
148147

149-
server.ListToolsHandler = (request, cancellationToken) =>
148+
server.SetListToolsHandler(async (request, cancellationToken) =>
150149
{
151-
return Task.FromResult(new ListToolsResult()
150+
return new ListToolsResult()
152151
{
153-
Tools =
152+
Tools =
154153
[
155-
new Tool()
154+
new Tool()
156155
{
157156
Name = "echo",
158157
Description = "Echoes the input back to the client.",
@@ -166,35 +165,31 @@ server.ListToolsHandler = (request, cancellationToken) =>
166165
},
167166
}
168167
]
169-
});
170-
};
168+
};
169+
});
171170

172-
server.CallToolHandler = async (request, cancellationToken) =>
171+
server.SetCallToolHandler(async (request, cancellationToken) =>
173172
{
174-
if (request.Name == "echo")
173+
if (request.Params?.Name == "echo")
175174
{
176-
if (request.Arguments is null || !request.Arguments.TryGetValue("message", out var message))
175+
if (request.Params.Arguments?.TryGetValue("message", out var message) is not true)
177176
{
178177
throw new McpServerException("Missing required argument 'message'");
179178
}
179+
180180
return new CallToolResponse()
181181
{
182-
Content = [new Content() { Text = "Echo: " + message.ToString(), Type = "text" }]
182+
Content = [new Content() { Text = $"Echo: {message}", Type = "text" }]
183183
};
184184
}
185-
else
186-
{
187-
throw new McpServerException($"Unknown tool: {request.Name}");
188-
}
189-
};
185+
186+
throw new McpServerException($"Unknown tool: '{request.Params?.Name}'");
187+
});
190188

191189
await server.StartAsync();
192190

193191
// Run until process is stopped by the client (parent process)
194-
while (true)
195-
{
196-
await Task.Delay(1000);
197-
}
192+
await Task.Delay(Timeout.Infinite);
198193
```
199194

200195

0 commit comments

Comments
 (0)