diff --git a/LinkToolAddin.csproj b/LinkToolAddin.csproj
index 818ba95..299d12b 100644
--- a/LinkToolAddin.csproj
+++ b/LinkToolAddin.csproj
@@ -98,9 +98,11 @@
-
-
-
+
+
+
+
+
diff --git a/LinkToolModule.cs b/LinkToolModule.cs
index 1d4476d..30107d1 100644
--- a/LinkToolModule.cs
+++ b/LinkToolModule.cs
@@ -18,6 +18,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
+using log4net.Config;
namespace LinkToolAddin
{
@@ -42,6 +43,7 @@ namespace LinkToolAddin
}
#endregion Overrides
-
}
+
+
}
diff --git a/client/CallArcGISPro.cs b/client/CallArcGISPro.cs
new file mode 100644
index 0000000..c04c526
--- /dev/null
+++ b/client/CallArcGISPro.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using LinkToolAddin.server;
+using Newtonsoft.Json;
+
+namespace LinkToolAddin.client;
+
+public class CallArcGISPro
+{
+ public static string CallArcGISProTool(Dictionary parameters)
+ {
+ // Call the ArcGIS Pro method and get the result
+ var result = server.CallArcGISPro.CallArcGISProTool(parameters["toolName"], JsonConvert.DeserializeObject>(parameters["toolParams"]));
+
+ // Serialize the result back to a JSON string
+ return JsonConvert.SerializeObject(result);
+ }
+}
\ No newline at end of file
diff --git a/host/CallMcp.cs b/host/CallMcp.cs
new file mode 100644
index 0000000..b27178c
--- /dev/null
+++ b/host/CallMcp.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using LinkToolAddin.server;
+using log4net;
+using Newtonsoft.Json;
+
+namespace LinkToolAddin.host
+{
+ public class CallMcp
+ {
+ private static readonly ILog log = LogManager.GetLogger(typeof(CallMcp));
+ public static string CallInnerMcpTool(string jsonRpcString)
+ {
+ log.Info("通过反射调用内部MCP工具");
+ var jsonRpcEntity = JsonConvert.DeserializeObject(jsonRpcString);
+
+ Type type = Type.GetType("LinkToolAddin.client."+jsonRpcEntity.Method.Split('.')[0]);
+ MethodInfo method = type.GetMethod(jsonRpcEntity.Method.Split('.')[1],BindingFlags.Public | BindingFlags.Static);
+ string result = (string)method.Invoke(null, new object[] { jsonRpcEntity.Params });
+
+ // 将结果序列化为 JSON 字符串
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/resource/DocDb.cs b/resource/DocDb.cs
new file mode 100644
index 0000000..3164327
--- /dev/null
+++ b/resource/DocDb.cs
@@ -0,0 +1,235 @@
+//
+//
+// To parse this JSON data, add NuGet 'System.Text.Json' then do:
+//
+// using QuickType;
+//
+// var welcome = Welcome.FromJson(jsonString);
+#nullable enable
+#pragma warning disable CS8618
+#pragma warning disable CS8601
+#pragma warning disable CS8603
+
+namespace QuickType
+{
+ using System;
+ using System.Collections.Generic;
+
+ using System.Text.Json;
+ using System.Text.Json.Serialization;
+ using System.Globalization;
+
+ public partial class DocDb
+ {
+ [JsonPropertyName("Code")]
+ public string Code { get; set; }
+
+ [JsonPropertyName("Data")]
+ public Data Data { get; set; }
+
+ [JsonPropertyName("Message")]
+ public string Message { get; set; }
+
+ [JsonPropertyName("RequestId")]
+ public string RequestId { get; set; }
+
+ [JsonPropertyName("Status")]
+ public long Status { get; set; }
+
+ [JsonPropertyName("Success")]
+ public bool Success { get; set; }
+ }
+
+ public partial class Data
+ {
+ [JsonPropertyName("Nodes")]
+ public List Nodes { get; set; }
+ }
+
+ public partial class Node
+ {
+ [JsonPropertyName("Metadata")]
+ public Metadata Metadata { get; set; }
+
+ [JsonPropertyName("Score")]
+ public double Score { get; set; }
+
+ [JsonPropertyName("Text")]
+ public string Text { get; set; }
+ }
+
+ public partial class Metadata
+ {
+ [JsonPropertyName("parent")]
+ public string Parent { get; set; }
+
+ [JsonPropertyName("file_path")]
+ public Uri FilePath { get; set; }
+
+ [JsonPropertyName("image_url")]
+ public List ImageUrl { get; set; }
+
+ [JsonPropertyName("nid")]
+ public string Nid { get; set; }
+
+ [JsonPropertyName("title")]
+ public string Title { get; set; }
+
+ [JsonPropertyName("doc_id")]
+ public string DocId { get; set; }
+
+ [JsonPropertyName("content")]
+ public string Content { get; set; }
+
+ [JsonPropertyName("workspace_id")]
+ public string WorkspaceId { get; set; }
+
+ [JsonPropertyName("hier_title")]
+ public string HierTitle { get; set; }
+
+ [JsonPropertyName("doc_name")]
+ public string DocName { get; set; }
+
+ [JsonPropertyName("pipeline_id")]
+ public string PipelineId { get; set; }
+
+ [JsonPropertyName("_id")]
+ public string Id { get; set; }
+ }
+
+ public partial class Welcome
+ {
+ public static Welcome FromJson(string json) => JsonSerializer.Deserialize(json, QuickType.Converter.Settings);
+ }
+
+ public static class Serialize
+ {
+ public static string ToJson(this Welcome self) => JsonSerializer.Serialize(self, QuickType.Converter.Settings);
+ }
+
+ internal static class Converter
+ {
+ public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)
+ {
+ Converters =
+ {
+ new DateOnlyConverter(),
+ new TimeOnlyConverter(),
+ IsoDateTimeOffsetConverter.Singleton
+ },
+ };
+ }
+
+ public class DateOnlyConverter : JsonConverter
+ {
+ private readonly string serializationFormat;
+ public DateOnlyConverter() : this(null) { }
+
+ public DateOnlyConverter(string? serializationFormat)
+ {
+ this.serializationFormat = serializationFormat ?? "yyyy-MM-dd";
+ }
+
+ public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ var value = reader.GetString();
+ return DateOnly.Parse(value!);
+ }
+
+ public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
+ => writer.WriteStringValue(value.ToString(serializationFormat));
+ }
+
+ public class TimeOnlyConverter : JsonConverter
+ {
+ private readonly string serializationFormat;
+
+ public TimeOnlyConverter() : this(null) { }
+
+ public TimeOnlyConverter(string? serializationFormat)
+ {
+ this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff";
+ }
+
+ public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ var value = reader.GetString();
+ return TimeOnly.Parse(value!);
+ }
+
+ public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options)
+ => writer.WriteStringValue(value.ToString(serializationFormat));
+ }
+
+ internal class IsoDateTimeOffsetConverter : JsonConverter
+ {
+ public override bool CanConvert(Type t) => t == typeof(DateTimeOffset);
+
+ private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
+
+ private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
+ private string? _dateTimeFormat;
+ private CultureInfo? _culture;
+
+ public DateTimeStyles DateTimeStyles
+ {
+ get => _dateTimeStyles;
+ set => _dateTimeStyles = value;
+ }
+
+ public string? DateTimeFormat
+ {
+ get => _dateTimeFormat ?? string.Empty;
+ set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value;
+ }
+
+ public CultureInfo Culture
+ {
+ get => _culture ?? CultureInfo.CurrentCulture;
+ set => _culture = value;
+ }
+
+ public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
+ {
+ string text;
+
+
+ if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
+ || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
+ {
+ value = value.ToUniversalTime();
+ }
+
+ text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
+
+ writer.WriteStringValue(text);
+ }
+
+ public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ string? dateText = reader.GetString();
+
+ if (string.IsNullOrEmpty(dateText) == false)
+ {
+ if (!string.IsNullOrEmpty(_dateTimeFormat))
+ {
+ return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
+ }
+ else
+ {
+ return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles);
+ }
+ }
+ else
+ {
+ return default(DateTimeOffset);
+ }
+ }
+
+
+ public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter();
+ }
+}
+#pragma warning restore CS8618
+#pragma warning restore CS8601
+#pragma warning restore CS8603
diff --git a/resource/GpToolDb.cs b/resource/GpToolDb.cs
new file mode 100644
index 0000000..3706c8d
--- /dev/null
+++ b/resource/GpToolDb.cs
@@ -0,0 +1,9 @@
+namespace LinkToolAddin.resource;
+
+public class GpToolDb
+{
+ public string toolName { get; set; }
+ public string toolDescription { get; set; }
+ public string exeName { get; set; }
+ public string toolParma { get; set; }
+}
\ No newline at end of file
diff --git a/resource/PromptDb.cs b/resource/PromptDb.cs
new file mode 100644
index 0000000..6b6e6d3
--- /dev/null
+++ b/resource/PromptDb.cs
@@ -0,0 +1,8 @@
+namespace LinkToolAddin.resource;
+
+public class PromptDb
+{
+ public string promptName { get; set; }
+ public string promptDescription { get; set; }
+ public string promptContent { get; set; }
+}
\ No newline at end of file
diff --git a/server/CallArcGISPro.cs b/server/CallArcGISPro.cs
new file mode 100644
index 0000000..a86ba63
--- /dev/null
+++ b/server/CallArcGISPro.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using ArcGIS.Desktop.Framework.Dialogs;
+
+namespace LinkToolAddin.server;
+
+public class CallArcGISPro
+{
+ private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(CallArcGISPro));
+ public static JsonRpcResultEntity CallArcGISProTool(string methodName, List methodParams)
+ {
+ // Simulate a call to ArcGIS Pro and return a success response
+ var successResponse = new JsonRpcSuccessEntity
+ {
+ Jsonrpc = "2.0",
+ Id = 1,
+ Result = $"ArcGIS Pro {methodName} method called successfully"
+ };
+ log.Info($"ArcGIS Pro {methodName} method called successfully");
+ MessageBox.Show($"ArcGIS Pro {methodName} method called successfully", "Test JsonRpc");
+ return successResponse;
+ }
+}
\ No newline at end of file
diff --git a/server/JsonRpcEntity.cs b/server/JsonRpcEntity.cs
new file mode 100644
index 0000000..01a91e3
--- /dev/null
+++ b/server/JsonRpcEntity.cs
@@ -0,0 +1,25 @@
+using System.Text.Json.Serialization;
+using Newtonsoft.Json;
+
+namespace LinkToolAddin.server
+{
+ using System;
+ using System.Collections.Generic;
+
+ using System.Globalization;
+
+ public partial class JsonRpcEntity
+ {
+ [JsonProperty("jsonrpc")]
+ public string Jsonrpc { get; set; }
+
+ [JsonProperty("method")]
+ public string Method { get; set; }
+
+ [JsonProperty("params")]
+ public Dictionary Params { get; set; }
+
+ [JsonProperty("id")]
+ public long Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/server/JsonRpcErrorEntity.cs b/server/JsonRpcErrorEntity.cs
new file mode 100644
index 0000000..46381de
--- /dev/null
+++ b/server/JsonRpcErrorEntity.cs
@@ -0,0 +1,25 @@
+namespace LinkToolAddin.server
+{
+ using Newtonsoft.Json;
+
+ public partial class JsonRpcErrorEntity
+ {
+ [JsonProperty("jsonrpc")]
+ public string Jsonrpc { get; set; }
+
+ [JsonProperty("error")]
+ public Error Error { get; set; }
+
+ [JsonProperty("id")]
+ public long Id { get; set; }
+ }
+
+ public partial class Error
+ {
+ [JsonProperty("code")]
+ public long Code { get; set; }
+
+ [JsonProperty("message")]
+ public string Message { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/server/JsonRpcResultEntity.cs b/server/JsonRpcResultEntity.cs
new file mode 100644
index 0000000..5d80803
--- /dev/null
+++ b/server/JsonRpcResultEntity.cs
@@ -0,0 +1,15 @@
+using Newtonsoft.Json;
+
+namespace LinkToolAddin.server
+{
+ using Newtonsoft.Json;
+
+ public partial class JsonRpcResultEntity
+ {
+ [JsonProperty("jsonrpc")]
+ public string Jsonrpc { get; set; }
+
+ [JsonProperty("id")]
+ public long Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/server/JsonRpcSuccessEntity.cs b/server/JsonRpcSuccessEntity.cs
new file mode 100644
index 0000000..a37985f
--- /dev/null
+++ b/server/JsonRpcSuccessEntity.cs
@@ -0,0 +1,16 @@
+namespace LinkToolAddin.server
+{
+ using Newtonsoft.Json;
+
+ public partial class JsonRpcSuccessEntity : JsonRpcResultEntity
+ {
+ [JsonProperty("jsonrpc")]
+ public string Jsonrpc { get; set; }
+
+ [JsonProperty("result")]
+ public string Result { get; set; }
+
+ [JsonProperty("id")]
+ public long Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/ui/dockpane/DialogDockpane.xaml b/ui/dockpane/DialogDockpane.xaml
index 3b569d7..84e7de1 100644
--- a/ui/dockpane/DialogDockpane.xaml
+++ b/ui/dockpane/DialogDockpane.xaml
@@ -22,13 +22,7 @@
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/ui/dockpane/DialogDockpane.xaml.cs b/ui/dockpane/DialogDockpane.xaml.cs
index 4a594fd..0196a6c 100644
--- a/ui/dockpane/DialogDockpane.xaml.cs
+++ b/ui/dockpane/DialogDockpane.xaml.cs
@@ -1,18 +1,20 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Net.Http;
+using System.Net.Http.Headers;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using System.Text.Json;
+using System.Threading;
+using log4net;
+using log4net.Appender;
+using log4net.Config;
+using log4net.Layout;
+using ModelContextProtocol.Server;
namespace LinkToolAddin.ui.dockpane
{
@@ -21,9 +23,54 @@ namespace LinkToolAddin.ui.dockpane
///
public partial class DialogDockpaneView : UserControl
{
+ private static ILog log = LogManager.GetLogger(typeof(DialogDockpaneView));
+
public DialogDockpaneView()
{
+ InitLogger();
InitializeComponent();
}
+
+ private async void TestServer_OnClick(object sender, RoutedEventArgs e)
+ {
+ log.Info("TestServer Clicked");
+ string jsonRpcString = @"{""jsonrpc"":""2.0"",""method"":""CallArcGISPro.CallArcGISProTool"",""params"":{""toolName"":""Testbbb"",""toolParams"":""[\""aa\"",\""bbb\""]""},""id"":1}";
+ LinkToolAddin.host.CallMcp.CallInnerMcpTool(jsonRpcString);
+ }
+
+ protected void InitLogger()
+ {
+ // 1. 创建控制台输出器(Appender)
+ var consoleAppender = new ConsoleAppender
+ {
+ Layout = new PatternLayout("%date [%thread] %-5level %logger - %message%newline"),
+ Threshold = log4net.Core.Level.Info // 仅输出 Info 及以上级别
+ };
+ consoleAppender.ActivateOptions(); // 激活配置
+
+ // 2. 创建文件滚动输出器(按大小滚动)
+ var fileAppender = new RollingFileAppender
+ {
+ File = Path.Combine("Logs", "app.log"), // 日志文件路径
+ AppendToFile = true, // 追加模式
+ RollingStyle = RollingFileAppender.RollingMode.Size, // 按文件大小滚动
+ MaxSizeRollBackups = 10, // 保留 10 个历史文件
+ MaximumFileSize = "1MB", // 单个文件最大 1MB
+ StaticLogFileName = true, // 固定文件名(否则自动追加序号)
+ Layout = new PatternLayout("%date [%thread] %-5level %logger - %message%newline"),
+ Threshold = log4net.Core.Level.Info // 仅输出 Info 及以上级别
+ };
+ fileAppender.ActivateOptions(); // 激活配置
+
+ // 3. 直接通过 BasicConfigurator 注册 Appender
+ BasicConfigurator.Configure(consoleAppender, fileAppender);
+
+ log = LogManager.GetLogger(typeof(DialogDockpaneView));
+
+ // 测试日志输出
+ log.Debug("Debug 日志(控制台可见)");
+ log.Info("Info 日志(控制台和文件可见)");
+ log.Error("Error 日志(严重问题)");
+ }
}
}
diff --git a/ui/dockpane/DialogDockpaneViewModel.cs b/ui/dockpane/DialogDockpaneViewModel.cs
index 5871201..1d7a4e5 100644
--- a/ui/dockpane/DialogDockpaneViewModel.cs
+++ b/ui/dockpane/DialogDockpaneViewModel.cs
@@ -17,6 +17,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Console;
namespace LinkToolAddin.ui.dockpane
{
@@ -56,6 +60,7 @@ namespace LinkToolAddin.ui.dockpane
{
protected override void OnClick()
{
+
DialogDockpaneViewModel.Show();
}
}