自主实现JSON Schema生成,接入数据查看工具
This commit is contained in:
parent
b6397e5db3
commit
3b1f65b3ba
@ -24,17 +24,47 @@ public class ArcGisPro
|
||||
return result;
|
||||
}
|
||||
|
||||
[McpServerTool, Description("查看指定数据的属性,包括坐标系、范围、数据类型等")]
|
||||
[McpServerTool, Description("查看指定数据的坐标系、范围、几何类型、是否有Z坐标和M坐标,获取字段列表等")]
|
||||
public static async Task<JsonRpcResultEntity> DataProperty(string datasetPath,string dataName)
|
||||
{
|
||||
using Geodatabase gdb = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(datasetPath)));
|
||||
FeatureClass featureClass = gdb.OpenDataset<FeatureClass>(dataName);
|
||||
FeatureClassDefinition featureClassDefinition = featureClass.GetDefinition();
|
||||
JsonRpcResultEntity result = new JsonRpcSuccessEntity()
|
||||
JsonRpcResultEntity result = new JsonRpcResultEntity();
|
||||
await QueuedTask.Run(() =>
|
||||
{
|
||||
Id = 1,
|
||||
Result = JsonConvert.SerializeObject(featureClassDefinition)
|
||||
};
|
||||
try
|
||||
{
|
||||
using Geodatabase gdb = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(datasetPath)));
|
||||
FeatureClass featureClass = gdb.OpenDataset<FeatureClass>(dataName);
|
||||
FeatureClassDefinition featureClassDefinition = featureClass.GetDefinition();
|
||||
SpatialReference spatialReference = featureClassDefinition.GetSpatialReference();
|
||||
GeometryType geometryType = featureClassDefinition.GetShapeType();
|
||||
result = new JsonRpcSuccessEntity()
|
||||
{
|
||||
Id = 1,
|
||||
Result = JsonConvert.SerializeObject(new Dictionary<string, object>()
|
||||
{
|
||||
{"spatialReference", spatialReference.Name+"(WKID:"+spatialReference.Wkid+")"},
|
||||
{"dataName", dataName},
|
||||
{"geometryType", geometryType.ToString()},
|
||||
{"hasZValue", featureClassDefinition.HasZ()},
|
||||
{"hasMValue", featureClassDefinition.HasM()},
|
||||
{"fields",featureClassDefinition.GetFields()}
|
||||
})
|
||||
};
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = new JsonRpcErrorEntity()
|
||||
{
|
||||
Error = new Error()
|
||||
{
|
||||
Message = ex.Message
|
||||
},
|
||||
Id = 1
|
||||
};
|
||||
return result;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
25
client/tool/KnowledgeBase.cs
Normal file
25
client/tool/KnowledgeBase.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using LinkToolAddin.host.llm.entity;
|
||||
using LinkToolAddin.resource;
|
||||
using LinkToolAddin.server;
|
||||
using ModelContextProtocol.Server;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace LinkToolAddin.client.tool;
|
||||
|
||||
public class KnowledgeBase
|
||||
{
|
||||
[McpServerTool, Description("可以查询ArcGIS Pro的帮助文档获取关于地理处理工具使用参数的说明")]
|
||||
public static async Task<JsonRpcResultEntity> QueryArcgisHelpDoc(string query)
|
||||
{
|
||||
DocDb docDb = new DocDb("sk-db177155677e438f832860e7f4da6afc", DocDb.KnowledgeBase.ArcGISProHelpDoc);
|
||||
KnowledgeResult knowledgeResult = await docDb.Retrieve(query);
|
||||
JsonRpcResultEntity result = new JsonRpcSuccessEntity()
|
||||
{
|
||||
Result = JsonConvert.SerializeObject(knowledgeResult.ChunkList),
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
150
common/JsonSchemaGenerator.cs
Normal file
150
common/JsonSchemaGenerator.cs
Normal file
@ -0,0 +1,150 @@
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace LinkToolAddin.common;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
|
||||
public static class JsonSchemaGenerator
|
||||
{
|
||||
public static string GenerateJsonSchema(MethodInfo methodInfo)
|
||||
{
|
||||
var parameters = methodInfo.GetParameters();
|
||||
var properties = new Dictionary<string, object>();
|
||||
var required = new List<string>();
|
||||
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
var paramName = param.Name ?? throw new InvalidOperationException("参数没有名称。");
|
||||
var paramSchema = GenerateSchemaForType(param.ParameterType);
|
||||
properties[paramName] = paramSchema;
|
||||
|
||||
if (!param.IsOptional)
|
||||
{
|
||||
required.Add(paramName);
|
||||
}
|
||||
}
|
||||
|
||||
var schemaRoot = new Dictionary<string, object>
|
||||
{
|
||||
{ "$schema", "http://json-schema.org/draft-07/schema#" },
|
||||
{ "type", "object" },
|
||||
{ "properties", properties }
|
||||
};
|
||||
|
||||
if (required.Count > 0)
|
||||
{
|
||||
schemaRoot["required"] = required;
|
||||
}
|
||||
|
||||
var options = new JsonSerializerOptions { WriteIndented = true };
|
||||
return JsonSerializer.Serialize(schemaRoot, options);
|
||||
}
|
||||
|
||||
private static object GenerateSchemaForType(Type type)
|
||||
{
|
||||
// 处理可空类型
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
var underlyingType = Nullable.GetUnderlyingType(type);
|
||||
return new[] { GenerateSchemaForType(underlyingType), "null" };
|
||||
}
|
||||
|
||||
// 处理集合类型(数组或IEnumerable<T>)
|
||||
if (IsCollectionType(type, out Type elementType))
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
{ "type", "array" },
|
||||
{ "items", GenerateSchemaForType(elementType) }
|
||||
};
|
||||
}
|
||||
|
||||
// 处理基本类型(int, string, bool, etc.)
|
||||
if (IsPrimitiveType(type))
|
||||
{
|
||||
string jsonType = MapClrTypeToJsonType(type);
|
||||
var schema = new Dictionary<string, object> { { "type", jsonType } };
|
||||
|
||||
if (type == typeof(DateTime))
|
||||
schema["format"] = "date-time";
|
||||
else if (type == typeof(Guid))
|
||||
schema["format"] = "uuid";
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
// 处理复杂类型(类、结构体)
|
||||
if (type.IsClass || type.IsValueType)
|
||||
{
|
||||
var props = new Dictionary<string, object>();
|
||||
foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
props[prop.Name] = GenerateSchemaForType(prop.PropertyType);
|
||||
}
|
||||
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
{ "type", "object" },
|
||||
{ "properties", props }
|
||||
};
|
||||
}
|
||||
|
||||
// 默认情况
|
||||
return new Dictionary<string, object> { { "type", "any" } };
|
||||
}
|
||||
|
||||
private static bool IsCollectionType(Type type, out Type elementType)
|
||||
{
|
||||
if (type == typeof(string))
|
||||
{
|
||||
elementType = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type.IsArray)
|
||||
{
|
||||
elementType = type.GetElementType();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genericTypeDef = type.GetGenericTypeDefinition();
|
||||
if (genericTypeDef == typeof(IEnumerable<>) ||
|
||||
genericTypeDef == typeof(List<>) ||
|
||||
genericTypeDef == typeof(Collection<>))
|
||||
{
|
||||
elementType = type.GetGenericArguments()[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
elementType = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsPrimitiveType(Type type)
|
||||
{
|
||||
return type.IsPrimitive || type == typeof(string) || type == typeof(decimal) || type == typeof(DateTime) || type == typeof(Guid);
|
||||
}
|
||||
|
||||
private static string MapClrTypeToJsonType(Type type)
|
||||
{
|
||||
if (type == typeof(int) || type == typeof(short) || type == typeof(long) ||
|
||||
type == typeof(uint) || type == typeof(ushort) || type == typeof(ulong))
|
||||
return "integer";
|
||||
if (type == typeof(float) || type == typeof(double) || type == typeof(decimal))
|
||||
return "number";
|
||||
if (type == typeof(bool))
|
||||
return "boolean";
|
||||
if (type == typeof(string))
|
||||
return "string";
|
||||
if (type == typeof(DateTime) || type == typeof(Guid))
|
||||
return "string";
|
||||
return "any";
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,7 @@ using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Schema;
|
||||
using Newtonsoft.Json.Schema.Generation;
|
||||
using Tool = LinkToolAddin.host.mcp.Tool;
|
||||
using LinkToolAddin.common;
|
||||
|
||||
namespace LinkToolAddin.host;
|
||||
|
||||
@ -471,7 +472,7 @@ public class Gateway
|
||||
{
|
||||
string methodName = method.Name;
|
||||
string methodDescription = method.GetCustomAttribute<DescriptionAttribute>()?.Description;
|
||||
string methodParamSchema = GenerateMethodParamSchema(method);
|
||||
string methodParamSchema = LinkToolAddin.common.JsonSchemaGenerator.GenerateJsonSchema(method);
|
||||
McpToolDefinition toolDefinition = new McpToolDefinition
|
||||
{
|
||||
Tool = new Tool
|
||||
|
||||
Loading…
Reference in New Issue
Block a user