@@ -54,44 +54,41 @@ dotnet add package mcpdotnet
54
54
55
55
Then create a client and start using tools, or other capabilities, from the servers you configure:
56
56
``` 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
+ };
59
61
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
+ };
71
73
72
- var factory = new McpClientFactory (
73
- [config ],
74
- options ,
75
- NullLoggerFactory .Instance
76
- );
74
+ var factory = new McpClientFactory ([config ], options , NullLoggerFactory .Instance );
77
75
78
76
var client = await factory .GetClientAsync (" everything" );
79
77
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
+ }
82
83
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).
84
85
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 );
92
89
93
90
// 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 );
95
92
```
96
93
97
94
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
107
104
## Getting Started (Server)
108
105
109
106
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.)
110
110
111
111
``` 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 ()
114
120
.WithStdioServerTransport ()
115
- .WithTools ()
116
-
117
- var app = builder .Build ();
118
-
119
- await app .RunAsync ();
120
- ```
121
+ .WithTools ();
122
+ await builder .Build ().RunAsync ();
121
123
122
- The ` EchoTool ` class is a simple example of a tool implementation:
123
- ``` csharp
124
124
[McpToolType ]
125
125
public static class EchoTool
126
126
{
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 }" ;
132
129
}
133
130
```
134
131
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:
137
133
``` 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 ()
139
141
{
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 () },
145
144
};
146
- McpServerFactory factory = new McpServerFactory (new StdioServerTransport (" MyServer" , loggerFactory ), options , loggerFactory );
145
+ McpServerFactory factory = new (new StdioServerTransport (" MyServer" , loggerFactory ), options , loggerFactory );
147
146
IMcpServer server = factory .CreateServer ();
148
147
149
- server .ListToolsHandler = (request , cancellationToken ) =>
148
+ server .SetListToolsHandler ( async (request , cancellationToken ) =>
150
149
{
151
- return Task . FromResult ( new ListToolsResult ()
150
+ return new ListToolsResult ()
152
151
{
153
- Tools =
152
+ Tools =
154
153
[
155
- new Tool ()
154
+ new Tool ()
156
155
{
157
156
Name = " echo" ,
158
157
Description = " Echoes the input back to the client." ,
@@ -166,35 +165,31 @@ server.ListToolsHandler = (request, cancellationToken) =>
166
165
},
167
166
}
168
167
]
169
- }) ;
170
- };
168
+ };
169
+ }) ;
171
170
172
- server .CallToolHandler = async (request , cancellationToken ) =>
171
+ server .SetCallToolHandler ( async (request , cancellationToken ) =>
173
172
{
174
- if (request .Name == " echo" )
173
+ if (request .Params ? . Name == " echo" )
175
174
{
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 )
177
176
{
178
177
throw new McpServerException (" Missing required argument 'message'" );
179
178
}
179
+
180
180
return new CallToolResponse ()
181
181
{
182
- Content = [new Content () { Text = " Echo: " + message . ToString () , Type = " text" }]
182
+ Content = [new Content () { Text = $ " Echo: { message } " , Type = " text" }]
183
183
};
184
184
}
185
- else
186
- {
187
- throw new McpServerException ($" Unknown tool: {request .Name }" );
188
- }
189
- };
185
+
186
+ throw new McpServerException ($" Unknown tool: '{request .Params ? .Name }'" );
187
+ });
190
188
191
189
await server .StartAsync ();
192
190
193
191
// 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 );
198
193
```
199
194
200
195
0 commit comments