# Creating Custom Tools

You can extend the MCP Server with your own tools by adding a simple attribute to any C# method. No Python changes, no server restart, no tool registration — just recompile in Unity and the AI agent sees your new tool.

## Basic Example

```csharp
using realvirtual.MCP;

public static class MyTools
{
    [McpTool("Get current time")]
    public static string GetTime()
    {
        return $"{{\"time\":\"{System.DateTime.Now}\"}}";
    }

    [McpTool("Add two numbers")]
    public static string Add(
        [McpParam("First number")] float a,
        [McpParam("Second number")] float b)
    {
        return $"{{\"result\":{a + b}}}";
    }
}
```

That's it. After recompilation, `get_time` and `add` are available to any connected AI agent.

## Attributes

### McpTool

Add `[McpTool("description")]` to any public static method that returns a string. The description tells the AI agent what the tool does.

```csharp
[McpTool("Spawn an enemy at position")]
public static string SpawnEnemy(
    [McpParam("Prefab name")] string prefab,
    [McpParam("X position")] float x,
    [McpParam("Z position")] float z)
{
    // Your Unity code here - runs on main thread
    return ToolHelpers.Ok("Enemy spawned");
}
```

### McpParam

Add `[McpParam("description")]` to parameters to give the AI agent context about what values to provide. Optional parameters need default values.

```csharp
[McpTool("Set weather")]
public static string SetWeather(
    [McpParam("Weather type: sunny, rainy, cloudy")] string weather,
    [McpParam("Wind speed in m/s")] float windSpeed = 0f)
{
    // windSpeed is optional, defaults to 0
    return ToolHelpers.Ok($"Weather set to {weather}");
}
```

## Rules

* Method must be `public static` and return `string` (JSON)
* Tool names auto-convert from PascalCase to snake\_case (`SpawnEnemy` → `spawn_enemy`)
* Methods can be in any class, in any assembly — they are found via reflection
* All tool methods run on Unity's main thread
* Return JSON strings — use `ToolHelpers.Ok()` and `ToolHelpers.Error()` for standard responses

## Helper Utilities

The `ToolHelpers` class provides common patterns:

```csharp
// Find a GameObject by hierarchy path
var go = ToolHelpers.FindGameObject("Robot/Arm/Gripper");

// Return success
return ToolHelpers.Ok("Operation completed");

// Return success with data
return ToolHelpers.Ok(new { position = transform.position });

// Return error
return ToolHelpers.Error("GameObject not found");
```

## Example: Custom Sensor Tool

```csharp
using realvirtual.MCP;
using UnityEngine;

public static class FactoryTools
{
    [McpTool("Get temperature from all sensors in the factory")]
    public static string GetTemperatures()
    {
        var sensors = Object.FindObjectsByType<TemperatureSensor>(
            FindObjectsSortMode.None);

        var results = sensors.Select(s => new {
            name = s.gameObject.name,
            temperature = s.CurrentTemperature,
            unit = "celsius"
        }).ToArray();

        return JsonUtility.ToJson(new { sensors = results });
    }
}
```

After recompiling, the AI agent can call `get_temperatures` and receive structured data about all temperature sensors in the scene.
