3using System.Diagnostics.CodeAnalysis;
4using System.Reflection;
5using System.Threading.Tasks;
23 private const string McpToolResultTitle =
"Result";
24 private const string McpToolResultDescription =
"Result returned after executing the tool.";
26 private Icons? icons =
null;
53 params KeyValuePair<string, object>[]
MetaData)
66 Type ReturnType = this.Method.ReturnType;
80 this.HasStructuredReturnValue =
false;
83 else if (ReturnType.IsGenericType &&
84 ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
86 Type[] TypeArguments = ReturnType.GetGenericArguments();
87 if (TypeArguments.Length == 1)
88 ReturnType = TypeArguments[0];
150 public KeyValuePair<string, object>[]
MetaData {
get; }
166 Dictionary<string, object>
Annotations =
new Dictionary<string, object>()
168 {
"readOnlyHint", this.CanModifyEnvironment },
169 {
"destructiveHint", this.CanDestroyEnvironment },
170 {
"idempotentHint", this.Idempotent },
171 {
"openWorldHint", this.OpenWorldAccess }
173 Dictionary<string, object> Result =
new Dictionary<string, object>()
175 {
"name", this.Method.Name },
176 {
"execution",
new Dictionary<string,object>()
178 {
"taskSupport",
"optional" }
181 {
"inputSchema", GenerateSchema(this.
Method) },
182 {
"annotations", Annotations }
185 if (!
string.IsNullOrEmpty(this.
Title))
186 Result.Add(
"title", this.
Title);
191 if (!this.icons.
Empty)
192 Result.Add(
"icons", this.icons.
ToJson());
197 IEnumerable<McpEnumValueAttribute>? EnumValues = this.Method.ReturnType.IsEnum ?
200 Result.Add(
"outputSchema", GenerateOutputSchema(this.
Method.ReturnType,
201 ReturnInfo, EnumValues));
204 if ((this.
MetaData?.Length ?? 0) > 0)
206 Dictionary<string, object>
MetaData =
new Dictionary<string, object>();
208 foreach (KeyValuePair<string, object> P
in this.
MetaData!)
226 BindingFlags.Static | BindingFlags.Instance |
227 BindingFlags.Public | BindingFlags.NonPublic);
235 if (Obj is
Icons Typed)
237 else if (Obj is
Icon[] IconArray)
239 else if (Obj is
Icon SingleIcon)
241 else if (Obj is
null)
245 throw new ArgumentException(
"Method " +
IconsMethod +
246 "returned an invalid type: " + Obj.GetType().FullName,
263 internal static Dictionary<string, object> GenerateSchema(MethodInfo
Method)
265 ParameterInfo[] Parameters =
Method.GetParameters();
266 Dictionary<string, object> Result =
new Dictionary<string, object>()
271 if (Parameters.Length == 0)
272 Result[
"additionalProperties"] =
false;
275 Dictionary<string, object> Properties =
new Dictionary<string, object>();
278 foreach (ParameterInfo Parameter
in Parameters)
280 Type ParameterType = Parameter.ParameterType;
288 if (!Parameter.IsOptional && !Parameter.HasDefaultValue)
289 Required.
Add(Parameter.Name);
292 IEnumerable<McpEnumValueAttribute>? EnumValues = ParameterType.IsEnum ?
295 Properties[Parameter.Name] = GenerateSchema(ParameterType,
296 Parameter.HasDefaultValue, Parameter.DefaultValue, ParameterInfo,
300 Result[
"properties"] = Properties;
301 Result[
"required"] = Required.
ToArray();
307 internal static Dictionary<string, object> GenerateOutputSchema(Type ReturnType,
310 Dictionary<string, object> Result =
new Dictionary<string, object>()
312 {
"type",
"object" },
313 {
"result", GenerateSchema(ReturnType,
false,
null, ParameterInfo, EnumValues) },
314 {
"title", McpToolResultTitle },
315 {
"description", McpToolResultDescription },
319 Result[
"required"] = Array.Empty<
string>();
321 Result[
"required"] =
new string[] {
"result" };
335 internal static object GenerateSchema(Type T,
bool HasDefault,
object? Default,
338 Dictionary<string, object?> Result =
new Dictionary<string, object?>();
339 bool EmitDefault = HasDefault;
345 if (EnumValues is
null)
346 EnumValuesList =
null;
353 EnumValuesList.
Add(
new Dictionary<string, object>()
355 {
"const", EnumValue.
Value.ToString() },
356 {
"title", EnumValue.Title ?? EnumValue.
Value.ToString() }
361 if (Attribute.IsDefined(T, typeof(FlagsAttribute)))
363 Result[
"type"] =
"array";
365 if (EnumValuesList is
null)
367 Result[
"items"] =
new Dictionary<string, object>()
369 {
"type",
"string" },
370 {
"enum", Enum.GetNames(T) }
375 Result[
"items"] =
new Dictionary<string, object>()
377 {
"anyOf", EnumValuesList.
ToArray() }
383 Result[
"type"] =
"string";
385 if (EnumValuesList is
null)
386 Result[
"enum"] = Enum.GetNames(T);
388 Result[
"oneOf"] = EnumValuesList.
ToArray();
393 switch (Type.GetTypeCode(T))
396 Result[
"type"] =
"null";
399 case TypeCode.Object:
401 Result[
"type"] =
"string";
402 else if (T == typeof(Uri))
404 Result[
"type"] =
"string";
405 Result[
"format"] =
"uri";
409 Result[
"type"] =
"array";
410 Result[
"items"] = GenerateSchema(T.GetElementType()!,
false,
null,
null,
null);
412 else if (T == typeof(Dictionary<string, object>))
415 Result[
"type"] =
"object";
422 Type GenericType = T.GetGenericTypeDefinition();
424 if (GenericType == typeof(Nullable<>) ||
425 GenericType == typeof(Task<>))
427 return GenerateSchema(T.GenericTypeArguments[0],
true, Default,
428 ParameterInfo, EnumValues);
432 Dictionary<string, object> Properties =
new Dictionary<string, object>();
435 Result[
"type"] =
"object";
436 Result[
"properties"] = Properties;
438 foreach (FieldInfo FI
in T.GetFields(BindingFlags.Public | BindingFlags.Instance))
442 IEnumerable<McpEnumValueAttribute>? EnumValues2 = FieldType.IsEnum ?
445 object? FieldDefault = Default is
null ? null : FI.GetValue(Default);
446 Properties[FI.Name] = GenerateSchema(FieldType, !(Default is
null),
447 FieldDefault, FieldInfo, EnumValues2);
450 foreach (PropertyInfo PI
in T.GetProperties(BindingFlags.Public | BindingFlags.Instance))
454 IEnumerable<McpEnumValueAttribute>? EnumValues2 = PropertyType.IsEnum ?
457 object? PropertyDefault = Default is
null ? null : PI.GetValue(Default);
458 Properties[PI.Name] = GenerateSchema(PropertyType, !(Default is
null),
459 PropertyDefault, PropertyInfo, EnumValues2);
464 case TypeCode.DBNull:
465 Result[
"type"] =
"null";
468 case TypeCode.Boolean:
469 Result[
"type"] =
"boolean";
473 Result[
"type"] =
"string";
477 Result[
"type"] =
"integer";
478 Result[
"minimum"] = sbyte.MinValue;
479 Result[
"maximum"] = sbyte.MaxValue;
483 Result[
"type"] =
"integer";
484 Result[
"minimum"] =
byte.MinValue;
485 Result[
"maximum"] =
byte.MaxValue;
489 Result[
"type"] =
"integer";
490 Result[
"minimum"] =
short.MinValue;
491 Result[
"maximum"] =
short.MaxValue;
494 case TypeCode.UInt16:
495 Result[
"type"] =
"integer";
496 Result[
"minimum"] = ushort.MinValue;
497 Result[
"maximum"] = ushort.MaxValue;
501 Result[
"type"] =
"integer";
502 Result[
"minimum"] =
int.MinValue;
503 Result[
"maximum"] =
int.MaxValue;
506 case TypeCode.UInt32:
507 Result[
"type"] =
"integer";
508 Result[
"minimum"] = uint.MinValue;
509 Result[
"maximum"] = uint.MaxValue;
513 Result[
"type"] =
"integer";
514 Result[
"minimum"] =
long.MinValue;
515 Result[
"maximum"] =
long.MaxValue;
518 case TypeCode.UInt64:
519 Result[
"type"] =
"integer";
520 Result[
"minimum"] = ulong.MinValue;
521 Result[
"maximum"] = ulong.MaxValue;
524 case TypeCode.Single:
525 case TypeCode.Double:
526 case TypeCode.Decimal:
527 Result[
"type"] =
"number";
530 case TypeCode.DateTime:
532 Result[
"type"] =
"string";
533 Result[
"format"] =
"date-time";
537 case TypeCode.String:
538 Result[
"type"] =
"string";
544 Result[
"default"] = Default;
565 Dictionary<string, object?>?
MetaData,
566 [NotNullWhen(
false)] out
string? Reason,
567 [NotNullWhen(
true)] out
object?[]?
Arguments)
Represents an HTTP request.
Represets a response of an HTTP client request.
Information about a protected method.
ProtectedMethodArgumentInfo[] Arguments
Arguments
int? RequestArgument
Request argument index
int? IdArgument
ID argument index
MethodInfo Method
Method information.
bool HasReturnValue
If the method has a return value.
int? ResponseArgument
Response argument index
Abstract base class for HTTP-based Model Context Protocol (MCP) server resource, as defined in:
Abstract base class for annotated objects.
Provides a title to an enumeration value.
Enum Value
Enumeration value
Provides meta-data about a parameter.
virtual void Annotate(Dictionary< string, object?> Schema)
Annotates a schema object with information in the attribute.
Abstract base class for an MCP Content Block.
abstract bool IsStructuredContent
If the content block is encoded as structured content.
An optionally-sized icon that can be displayed in a user interface.
Base interface to add icons property.
Icons()
Base interface to add icons property.
bool Empty
If there are icons defined.
Dictionary< string, object >[] ToJson()
Converts object to a generic representation.
Contains information about an MCP Server Resource
Represents a case-insensitive string.
A chunked list is a linked list of chunks of objects of type T .
void Add(T Item)
Adds an item to the collection.
T[] ToArray()
Returns an array containing all elements of the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
static object Instantiate(Type Type, params object[] Arguments)
Returns an instance of the type Type . If one needs to be created, it is. If the constructor requires...
Class managing a script expression.
static bool IsVoid(Type ResultType)
Checks if a result object type is equal to void (i.e. its type equal to System.Threading....
Base class for all nodes in a parsed script tree.
static async Task< object > WaitPossibleTask(object Result)
Waits for any asynchronous process to terminate.
Interface for MCP Content Block.
PropertyType
Type of indexed property.
FieldType
Field Type flags