com.IvanMurzak.ReflectorNet 5.1.1

dotnet add package com.IvanMurzak.ReflectorNet --version 5.1.1
                    
NuGet\Install-Package com.IvanMurzak.ReflectorNet -Version 5.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="com.IvanMurzak.ReflectorNet" Version="5.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="com.IvanMurzak.ReflectorNet" Version="5.1.1" />
                    
Directory.Packages.props
<PackageReference Include="com.IvanMurzak.ReflectorNet" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add com.IvanMurzak.ReflectorNet --version 5.1.1
                    
#r "nuget: com.IvanMurzak.ReflectorNet, 5.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package com.IvanMurzak.ReflectorNet@5.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=com.IvanMurzak.ReflectorNet&version=5.1.1
                    
Install as a Cake Addin
#tool nuget:?package=com.IvanMurzak.ReflectorNet&version=5.1.1
                    
Install as a Cake Tool

ReflectorNet

NuGet netstandard2.1 .NET 8.0 .NET 9.0 Tests

Stars Discord License Stand With Ukraine

ReflectorNet is a sophisticated .NET reflection toolkit designed to bridge the gap between static .NET applications and dynamic, AI-driven environments. It provides robust serialization, intelligent method discovery, and dynamic invocation capabilities that allow AI agents to interact with .NET codebases safely and effectively.

🚀 Why ReflectorNet?

Traditional reflection is brittle and requires exact matches. ReflectorNet is built for flexibility:

  • 🤖 AI-Ready: Designed for scenarios where inputs (from LLMs) might be partial or fuzzy.
  • 🔍 Fuzzy Matching: Discover methods and types even with incomplete names or parameters (configurable match levels 0-6).
  • 📦 Type-Safe Serialization: Preserves full type information, supporting complex nested objects, collections, and custom types.
  • 🔄 In-Place Modification: Update existing object instances from serialized data without breaking references.
  • 🎯 Atomic Path-Based Modification: Navigate directly to any field, array element, or dictionary entry by path and modify only that — without touching anything else.
  • 🩹 JSON Patch: Apply a JSON document to modify multiple fields at different depths in a single call, following JSON Merge Patch (RFC 7396) semantics.
  • 🔎 View & Grep: Read exactly what you need — navigate to a subtree, filter by name pattern or type, or grep the entire live object graph for all fields matching a regex. The read-side counterpart to path-based modification.
  • 📄 JSON Schema Generation: Automatically generate schemas for your types and methods to feed into LLM context windows.

📦 Installation

dotnet add package com.IvanMurzak.ReflectorNet

⚡ Quick Start

1. Setup

The Reflector class is your main entry point.

using com.IvanMurzak.ReflectorNet;

var reflector = new Reflector();

2. Serialization

Convert any .NET object into a SerializedMember intermediate representation. This preserves type metadata that standard JSON serializers might lose.

var myObject = new MyComplexClass { Id = 1, Name = "Test" };

// Serialize to intermediate representation
SerializedMember serialized = reflector.Serialize(myObject);

// Convert to JSON string if needed
string json = reflector.JsonSerializer.Serialize(serialized);

3. Deserialization

Reconstruct objects with full type fidelity.

// Restore to a specific type
MyComplexClass restored = reflector.Deserialize<MyComplexClass>(serialized);

// Or let Reflector resolve the type automatically
object restoredObj = reflector.Deserialize(serialized);

4. In-Place Modification

Update an existing object instance with new data. This is crucial for maintaining object identity in stateful applications (like Unity games or long-running services).

var existingInstance = new MyComplexClass();

// Modify 'existingInstance' with data from 'serialized'
// Returns true if successful
bool success = reflector.TryModify(ref existingInstance, serialized);

5. Atomic Path-Based Modification

Navigate directly to a specific field, array element, or dictionary entry by path and modify only that target — no surrounding data is affected.

Path format:

Segment Meaning
fieldName Field or property by name
[i] Array / list element at index i
[key] Dictionary entry with key key (any key type)

A leading #/ is stripped automatically for compatibility with SerializationContext paths.

var reflector = new Reflector();
object? system = new SolarSystem
{
    globalOrbitSpeedMultiplier = 1f,
    celestialBodies = new[]
    {
        new CelestialBody { orbitRadius = 10f, orbitSpeed = 1f },
        new CelestialBody { orbitRadius = 20f, orbitSpeed = 2f },
    }
};

// Modify a root field
reflector.TryModifyAt<float>(ref system, "globalOrbitSpeedMultiplier", 5f);

// Modify a nested field — only that one field changes
reflector.TryModifyAt<float>(ref system, "celestialBodies/[0]/orbitRadius", 999f);

// Dictionary entry — string or integer keys both work
object? container = new Config { settings = new Dictionary<string, int> { ["timeout"] = 10 } };
reflector.TryModifyAt<int>(ref container, "settings/[timeout]", 60);

For partial updates of a complex object at a path, supply a SerializedMember that lists only the fields to change:

var patch = new SerializedMember { typeName = typeof(CelestialBody).GetTypeId() };
patch.SetFieldValue(reflector, "orbitRadius", 777f); // only orbitRadius changes

var logs = new Logs();
reflector.TryModifyAt(ref system, "celestialBodies/[1]", patch, logs: logs);
// celestialBodies[1].orbitSpeed is untouched

Errors are collected in the Logs object — nothing is thrown:

var logs = new Logs();
bool ok = reflector.TryModifyAt<float>(ref system, "doesNotExist", 5f, logs: logs);
// ok == false; logs contains:
// "Segment 'doesNotExist' not found on type 'SolarSystem'.
//  Available fields: globalOrbitSpeedMultiplier, celestialBodies, ..."

6. JSON Patch

Apply a JSON document to modify multiple fields at different depths in a single call. Follows JSON Merge Patch (RFC 7396) semantics, extended with bracket-notation keys for arrays and dictionaries.

var reflector = new Reflector();
object? system = new SolarSystem { /* ... */ };

// Modify several fields at once — untouched fields are preserved
var logs = new Logs();
bool ok = reflector.TryPatch(ref system, """
{
  "globalOrbitSpeedMultiplier": 5.0,
  "globalSizeMultiplier": 2.0,
  "celestialBodies": {
    "[0]": { "orbitRadius": 42.0 }
  }
}
""", logs: logs);

Patch document rules:

  • A JSON object key navigates into that field ("fieldName") or element ("[i]" / "[key]")
  • A JSON non-object value sets the field directly
  • null sets the field to null
  • "$type" key inside a JSON object specifies a desired subtype — the existing instance is replaced with a fresh instance of the new type before applying the remaining keys
// Replace a base-type field with a derived type and set its fields
reflector.TryPatch(ref system, """
{
  "star": {
    "$type": "MyNamespace.NeutronStar",
    "mass": 2.5
  }
}
""");

A JsonElement overload is also available when you already have a parsed document:

using var doc = JsonDocument.Parse(@"{ ""globalOrbitSpeedMultiplier"": 9.0 }");
reflector.TryPatch(ref system, doc.RootElement, logs: logs);

7. View & Grep — Read-Side Navigation

Read exactly the data you need from a live object — navigate to a specific subtree, filter by name or type, or grep the entire graph for every field matching a pattern. This is the read-side counterpart to Atomic Path-Based Modification.


reflector.View — filtered serialization

Returns a SerializedMember tree with optional path navigation and post-filters applied.

var reflector = new Reflector();
object? system = new SolarSystem
{
    globalOrbitSpeedMultiplier = 1f,
    globalSizeMultiplier       = 2f,
    celestialBodies = new[]
    {
        new CelestialBody { orbitRadius = 10f, orbitSpeed = 1f },
        new CelestialBody { orbitRadius = 20f, orbitSpeed = 2f },
    }
};

// Full view — equivalent to Serialize()
SerializedMember? full = reflector.View(system);

// Navigate to a subtree (same path format as TryModifyAt)
SerializedMember? firstBody = reflector.View(system,
    new ViewQuery { Path = "celestialBodies/[0]" });
// firstBody.typeName contains "CelestialBody"

// Depth-limited — MaxDepth=0 returns root node only (no children)
SerializedMember? shallow = reflector.View(system,
    new ViewQuery { MaxDepth = 1 });

// Pattern filter — keep only branches containing a matching field name
// Accepts any .NET regex; matching is case-insensitive
SerializedMember? orbitFields = reflector.View(system,
    new ViewQuery { NamePattern = "^orbit" });

// Type filter — keep only branches whose resolved type is assignable to float
SerializedMember? floatFields = reflector.View(system,
    new ViewQuery { TypeFilter = typeof(float) });

// Combined — navigate first, then filter
SerializedMember? result = reflector.View(system, new ViewQuery
{
    Path        = "celestialBodies/[0]",
    NamePattern = "^orbit",
    MaxDepth    = 2,
});

When a filter produces no matches the root envelope is still returned with an empty fields collection so that result.typeName always identifies the navigated node's type.

ViewQuery options:

Option Type Default Description
Path string? null Navigate to this path before serializing (same format as TryModifyAt)
MaxDepth int? null Maximum depth of returned tree (0 = root node only, no children)
NamePattern string? null .NET regex matched against field / property names (case-insensitive)
TypeFilter Type? null Keep only branches whose resolved runtime type is assignable to this type

reflector.TryReadAt — single-value path read

Navigate to exactly one value by path and serialize it. Mirrors TryModifyAt but reads instead of writes.

// Scalar leaf
bool ok = reflector.TryReadAt(system, "celestialBodies/[0]/orbitRadius", out SerializedMember? r);
if (ok)
    Console.WriteLine(r!.GetValue<float>(reflector)); // 10f

// Composite node — result has full fields tree for the navigated object
reflector.TryReadAt(system, "celestialBodies/[0]", out var body);
float radius = body!.fields!.First(f => f.name == "orbitRadius").GetValue<float>(reflector);

// Dictionary access — string or any key type
reflector.TryReadAt(container, "config/[timeout]", out var timeout);
int ms = timeout!.GetValue<int>(reflector); // 30

// Invalid paths return false; errors are collected in Logs — nothing is thrown
var logs = new Logs();
bool ok2 = reflector.TryReadAt(system, "doesNotExist", out _, logs: logs);
// ok2 == false
// logs: "Segment 'doesNotExist' not found on type 'SolarSystem'.
//        Available fields: globalOrbitSpeedMultiplier, celestialBodies, ..."

reflector.Grep — grep the live object graph

Walks the entire live object graph and returns a flat list of every field / property whose name matches the given regex pattern — like the grep command, but for in-RAM objects.

// Find every field whose name starts with "orbit"
IReadOnlyList<ViewMatch> hits = reflector.Grep(system, "^orbit");

foreach (var hit in hits)
    Console.WriteLine($"{hit.Path} = {hit.Value.GetValue<float>(reflector)}");
// celestialBodies/[0]/orbitRadius = 10
// celestialBodies/[0]/orbitSpeed  = 1
// celestialBodies/[1]/orbitRadius = 20
// celestialBodies/[1]/orbitSpeed  = 2

// Limit search depth (0 = top-level fields only, no recursion)
IReadOnlyList<ViewMatch> topLevel = reflector.Grep(system, ".*", maxDepth: 0);

// Exact name — anchored regex
IReadOnlyList<ViewMatch> exact = reflector.Grep(system, "^globalOrbitSpeedMultiplier$");
Console.WriteLine(exact[0].Path);  // "globalOrbitSpeedMultiplier"

Each ViewMatch exposes:

  • Path — full slash-delimited path, e.g. "celestialBodies/[0]/orbitRadius"
  • ValueSerializedMember of the matched field, ready for GetValue<T>(reflector)

Grep vs. View + NamePattern: Grep walks the live object graph and can find fields inside array elements. View + NamePattern filters the SerializedMember tree after serialization; array element contents are stored as JSON and are not individually filterable by name. Use Grep when you need to search inside arrays.


8. Dynamic Method Invocation

Allow AI to find and call methods without knowing the exact signature.

using com.IvanMurzak.ReflectorNet.Model;

// 1. Define what we are looking for (can be partial)
var methodRef = new MethodRef
{
    TypeName = "Calculator",
    MethodName = "Add", // Could be "AddValues" or "CalculateAdd" depending on match level
    InputParameters = new List<MethodRef.Parameter>
    {
        new MethodRef.Parameter { Name = "a", Value = "10" },
        new MethodRef.Parameter { Name = "b", Value = "20" }
    }
};

// 2. Call the method
// Note: We pass 'reflector' as the first argument to handle internal deserialization context
string result = reflector.MethodCall(
    reflector,
    methodRef,
    methodNameMatchLevel: 3, // Allow fuzzy matching
    executeInMainThread: false // Set to false for console apps/services (no UI thread)
);

Console.WriteLine(result); // Output: [Success] 30

9. Method Inspection & Schema Generation

Generate JSON schemas for types and methods to help LLMs understand your code structure.

// 1. Get schema for a specific type
var typeSchema = reflector.GetSchema<MyComplexClass>();

// 2. Get schema for method arguments (ideal for LLM function calling definitions)
var methodInfo = typeof(Calculator).GetMethod("Add");
var argsSchema = reflector.GetArgumentsSchema(methodInfo);

// 3. Get schema for method return value
var returnSchema = reflector.GetReturnSchema(methodInfo);

🏗️ Architecture

ReflectorNet is built on a Chain of Responsibility pattern to handle the complexity of .NET types.

Core Components

  • Reflector: The orchestrator. It manages the registry of converters and exposes the high-level API.
  • Registry: Holds a prioritized list of IReflectionConverters. When you serialize or deserialize, the registry finds the best converter for the specific type.
  • SerializedMember: The universal data model. It represents any .NET object (primitive, class, array) in a serializable format that holds both value and type metadata.

Built-in Converters

ReflectorNet comes with a set of standard converters:

  1. PrimitiveReflectionConverter: Handles int, string, bool, DateTime, etc.
  2. ArrayReflectionConverter: Handles arrays (T[]) and generic lists (List<T>).
  3. GenericReflectionConverter<T>: The fallback for custom classes and structs.
  4. TypeReflectionConverter & AssemblyReflectionConverter: Specialized handling for System.Type and System.Reflection.Assembly.

Extensibility

You can create custom converters for your own types by implementing IReflectionConverter or inheriting from GenericReflectionConverter<T> and registering them:

reflector.Converters.Add(new MyCustomConverter());

🛠️ Advanced Features

JSON Schema Generation

Generate schemas to describe your C# types to an LLM.

// Get schema for a type
var typeSchema = reflector.GetSchema<MyClass>();

// Get schema for method arguments (great for function calling)
var methodSchema = reflector.GetArgumentsSchema(myMethodInfo);

🧩 The Converter System (Custom Serialization)

ReflectorNet's power lies in its extensible Converter System. If you have "exotic" data models (e.g., third-party types you can't modify, complex graphs, or types needing special handling like System.Type), you can write a custom converter.

How it Works
  1. Interface: All converters implement IReflectionConverter.
  2. Base Class: Most custom converters should inherit from BaseReflectionConverter<T> or GenericReflectionConverter<T>.
  3. Priority: ReflectorNet asks every registered converter: "Can you handle this type, and how well?" (via SerializationPriority). The one with the highest score wins.
    • Exact match: Highest priority.
    • Inheritance match: Lower priority (based on distance).
    • No match: Zero.
Creating a Custom Converter

Here is an example of a converter for a hypothetical ThirdPartyWidget that should be serialized as a simple string instead of a complex object.

<details> <summary>Click to see the code example</summary>

using com.IvanMurzak.ReflectorNet.Converter;
using com.IvanMurzak.ReflectorNet.Model;

// 1. Inherit from GenericReflectionConverter<T> for the target type
public class WidgetConverter : GenericReflectionConverter<ThirdPartyWidget>
{
    // 2. Override SerializationPriority if you need special matching logic
    // (The default implementation already handles inheritance distance perfectly)

    // 3. Override InternalSerialize to customize output
    protected override SerializedMember InternalSerialize(
        Reflector reflector,
        object? obj,
        Type type,
        string? name = null,
        bool recursive = true,
        BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
        int depth = 0,
        Logs? logs = null,
        ILogger? logger = null,
        SerializationContext? context = null)
    {
        if (obj is ThirdPartyWidget widget)
        {
            // Serialize as a simple string value instead of an object with fields
            return SerializedMember.FromValue(
                reflector,
                type,
                value: $"Widget:{widget.Id}",
                name: name
            );
        }

        return base.InternalSerialize(reflector, obj, type, name, recursive, flags, depth, logs, logger, context);
    }

    // 4. Override CreateInstance if the type has no parameterless constructor
    public override object? CreateInstance(Reflector reflector, Type type)
    {
        return new ThirdPartyWidget("default-id");
    }
}

// 5. Register it
reflector.Converters.Add(new WidgetConverter());

</details>

Lazy Loading & Optional Dependencies

Sometimes you need to handle types that might not be present at runtime (e.g., optional plugins or platform-specific referencing like UnityEngine.Collider which is only available inside Unity). If you reference these types directly in your code, your application might crash if the assembly is missing.

LazyReflectionConverter solves this by resolving the type by its string name at runtime. If the type is found, it works; if not, it gracefully steps aside.

Basic Usage:

// Only active if "Some.Optional.Library.SuperWidget" exists at runtime
var lazyConverter = new LazyReflectionConverter("Some.Optional.Library.SuperWidget");

reflector.Converters.Add(lazyConverter);

Advanced Usage: Delegation & Ignoring Members

You can also use LazyReflectionConverter to wrap your own custom converters. This allows you to apply your custom logic only when the type exists, without taking a hard dependency on it.

// 1. Create your custom converter (assuming it can compile without the hard dependency, e.g. using generics or object)
// Or, if you have a converter that specific to a type but you want to lazy load it:
var myCustomLogic = new MySpecialConverter(); // Implements IReflectionConverter

// 2. Wrap it in LazyReflectionConverter
var lazyDelegate = new LazyReflectionConverter(
    "UnityEngine.Collider",
    backingConverter: myCustomLogic
);

reflector.Converters.Add(lazyDelegate);

You can also simply ignore specific properties or fields without writing a full custom converter:

// Ignore "heavyData" property if the type exists
var simpleLazy = new LazyReflectionConverter(
    "My.Optional.Type",
    ignoredProperties: new[] { "heavyData" }
);

📜 Custom JSON Schema Generation

While ReflectionConverter handles runtime object manipulation, you might also want to control how your types are described in the generated JSON Schema (used by LLMs to understand your data structure).

ReflectorNet allows you to customize this by implementing the IJsonSchemaConverter interface. This is often done by inheriting from JsonSchemaConverter<T>, which combines standard JSON serialization with schema generation.

How it Works
  1. Interface: Implement IJsonSchemaConverter.
  2. Registration: Add the converter to reflector.JsonSerializer.
  3. Generation: When reflector.GetSchema() is called, it checks if a registered converter exists for a type. If that converter implements IJsonSchemaConverter, it delegates schema creation to it.
Example: Custom Schema for a Widget

Suppose you have a ThirdPartyWidget that serializes to a string (e.g., "Widget:123"), and you want the LLM to know this format.

<details> <summary>Click to see the code example</summary>

using System.Text.Json;
using System.Text.Json.Nodes;
using com.IvanMurzak.ReflectorNet.Converter.Json;
using com.IvanMurzak.ReflectorNet.Utils;

// 1. Inherit from JsonSchemaConverter<T>
public class WidgetSchemaConverter : JsonSchemaConverter<ThirdPartyWidget>
{
    // 2. Define the Schema Definition (what the type looks like)
    public override JsonNode GetSchema()
    {
        return new JsonObject
        {
            [JsonSchema.Type] = "string",
            [JsonSchema.Pattern] = "^Widget:\\d+$",
            [JsonSchema.Description] = "A widget identifier in the format 'Widget:{id}'"
        };
    }

    // 3. Define the Schema Reference (how other types refer to it)
    public override JsonNode GetSchemaRef()
    {
        // Standard way to refer to the definition
        return new JsonObject
        {
            [JsonSchema.Ref] = JsonSchema.RefValue + TypeUtils.GetSchemaTypeId<ThirdPartyWidget>()
        };
    }

    // 4. Implement standard System.Text.Json logic (optional if only used for schema, but recommended)
    public override void Write(Utf8JsonWriter writer, ThirdPartyWidget value, JsonSerializerOptions options)
    {
        writer.WriteStringValue($"Widget:{value.Id}");
    }

    public override ThirdPartyWidget Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var str = reader.GetString();
        // Parse "Widget:123" back to object...
        return new ThirdPartyWidget(str.Split(':')[1]);
    }
}

// 5. Register it with the JSON Serializer
reflector.JsonSerializer.AddConverter(new WidgetSchemaConverter());

</details>

Note: You can use ReflectionConverter (for runtime logic) and JsonSchemaConverter (for schema/transport) together for the same type if needed.

Fuzzy Matching Levels

When searching for methods, you can tune the strictness:

  • 6: Exact match
  • 5: Case-insensitive match
  • 4: Starts with (Case-sensitive)
  • 3: Starts with (Case-insensitive)
  • 2: Contains (Case-sensitive)
  • 1: Contains (Case-insensitive)

🤝 Contributing

Contributions are welcome! Please submit Pull Requests to the main branch.

  1. Fork the repository.
  2. Create a feature branch.
  3. Commit your changes.
  4. Push to the branch.
  5. Open a Pull Request.

📄 License

This project is licensed under the Apache-2.0 License. Copyright - Ivan Murzak.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on com.IvanMurzak.ReflectorNet:

Package Downloads
com.IvanMurzak.McpPlugin.Common

McpPlugin common code for McpPlugin and McpPlugin.Server projects. It is .NET Library project for integration MCP server features into any dotnet application. It connects automatically with MCP server and exposes it's API over TCP connection in runtime. When MCP server interacts with AI.

com.IvanMurzak.McpPlugin

McpPlugin is a .NET Library project for integration MCP server features into any dotnet application. It connects automatically with MCP server and exposes it's API over TCP connection in runtime. When MCP server interacts with AI. This library maintains a local application.

com.IvanMurzak.McpPlugin.Server

MCP Server dotnet. Model Context Protocol server that interacts with MCP Plugin integrated into any dotnet application.

com.IvanMurzak.Unity.MCP.Common

Shared code between Unity-MCP-Plugin and Unity-MCP-Server projects.

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on com.IvanMurzak.ReflectorNet:

Repository Stars
IvanMurzak/Unity-MCP
AI Skills, MCP Tools, and CLI for Unity Engine. Full AI develop and test loop. Use cli for quick setup. Efficient token usage, advanced tools. Any C# method may be turned into a tool by a single line. Works with Claude Code, Gemini, Copilot, Cursor and any other absolutely for free.
Version Downloads Last Updated
5.1.1 1,088 4/29/2026
5.1.0 164 4/29/2026
5.0.0 5,659 4/16/2026
4.1.0 792 3/25/2026
4.0.0 2,081 3/3/2026
3.12.1 1,207 2/12/2026
3.12.0 459 1/31/2026
3.11.0 372 1/20/2026
3.10.0 301 1/19/2026
3.9.0 282 1/18/2026
3.8.1 265 1/18/2026
3.8.0 272 1/18/2026
3.7.1 318 1/17/2026
3.7.0 279 1/16/2026
3.6.0 338 1/10/2026
3.5.0 330 1/10/2026
3.4.0 286 1/8/2026
3.3.1 324 1/7/2026
3.3.0 321 1/5/2026
3.2.4 288 1/4/2026
Loading failed