> For the complete documentation index, see [llms.txt](https://doc.realvirtual.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://doc.realvirtual.io/extensions/mcp-server/creating-custom-tools.md).

# 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.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://doc.realvirtual.io/extensions/mcp-server/creating-custom-tools.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
