diff --git a/MCPForUnity/Editor/Clients/Configurators/DroidConfigurator.cs b/MCPForUnity/Editor/Clients/Configurators/DroidConfigurator.cs
new file mode 100644
index 000000000..652ab1aec
--- /dev/null
+++ b/MCPForUnity/Editor/Clients/Configurators/DroidConfigurator.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using MCPForUnity.Editor.Models;
+
+namespace MCPForUnity.Editor.Clients.Configurators
+{
+ ///
+ /// Factory Droid configurator. Droid stores MCP server config in
+ /// ~/.factory/mcp.json using the standard `mcpServers` container, so it
+ /// reuses the shared JSON-file configurator pipeline.
+ ///
+ public class DroidConfigurator : JsonFileMcpConfigurator
+ {
+ public DroidConfigurator() : base(new McpClient
+ {
+ name = "Droid",
+ // ~/.factory/mcp.json on every OS (UserProfile resolves to C:\Users\ on Windows).
+ windowsConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".factory", "mcp.json"),
+ macConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".factory", "mcp.json"),
+ linuxConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".factory", "mcp.json"),
+ })
+ { }
+
+ public override bool SupportsSkills => true;
+
+ public override string GetSkillInstallPath()
+ {
+ var userHome = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
+ return Path.Combine(userHome, ".factory", "skills", "unity-mcp-skill");
+ }
+
+ public override IList GetInstallationSteps() => new List
+ {
+ "Install Factory Droid (https://factory.ai)",
+ "Click Configure to add UnityMCP to ~/.factory/mcp.json\nOR open the config file at the path above",
+ "Merge the manual snippet so it results in mcpServers.unityMCP (do not nest mcpServers twice)",
+ "Save and restart Droid"
+ };
+ }
+}
diff --git a/MCPForUnity/Editor/Clients/Configurators/DroidConfigurator.cs.meta b/MCPForUnity/Editor/Clients/Configurators/DroidConfigurator.cs.meta
new file mode 100644
index 000000000..5f8222661
--- /dev/null
+++ b/MCPForUnity/Editor/Clients/Configurators/DroidConfigurator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a1c8f3b9d5e74a2190f6c1d8e3b7a5f2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Clients/IsInstalledTests.cs b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Clients/IsInstalledTests.cs
index e7d4467cb..4b9e715cd 100644
--- a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Clients/IsInstalledTests.cs
+++ b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Clients/IsInstalledTests.cs
@@ -41,5 +41,14 @@ public void JsonClient_Installed_WhenParentDirExists()
bool expected = parent != null && Directory.Exists(parent);
Assert.AreEqual(expected, claude.IsInstalled);
}
+
+ [Test]
+ public void Droid_Installed_WhenFactoryDirExists()
+ {
+ var droid = new DroidConfigurator();
+ string parent = Path.GetDirectoryName(droid.GetConfigPath());
+ bool expected = parent != null && Directory.Exists(parent);
+ Assert.AreEqual(expected, droid.IsInstalled);
+ }
}
}
diff --git a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Clients/SupportedTransportsTests.cs b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Clients/SupportedTransportsTests.cs
index 865561f0f..f8f9542cf 100644
--- a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Clients/SupportedTransportsTests.cs
+++ b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Clients/SupportedTransportsTests.cs
@@ -32,5 +32,14 @@ public void Cursor_SupportsBothTransports()
CollectionAssert.Contains(list, ConfiguredTransport.Stdio);
CollectionAssert.Contains(list, ConfiguredTransport.Http);
}
+
+ [Test]
+ public void Droid_SupportsBothTransports()
+ {
+ var droid = new DroidConfigurator();
+ var list = droid.SupportedTransports.ToList();
+ CollectionAssert.Contains(list, ConfiguredTransport.Stdio);
+ CollectionAssert.Contains(list, ConfiguredTransport.Http);
+ }
}
}
diff --git a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/ClientConfigFormatTests.cs b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/ClientConfigFormatTests.cs
index ef9301566..fbb19aa81 100644
--- a/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/ClientConfigFormatTests.cs
+++ b/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/ClientConfigFormatTests.cs
@@ -152,5 +152,73 @@ public void BuildManualConfigJson_ForGenericHttpClient_UsesPlainHttpType()
Assert.AreEqual("http", (string)unity["type"],
"Clients without HttpTypeValue should keep the generic type:http");
}
+
+ [Test]
+ public void DroidConfigurator_DeclaresStandardMcpServersFormat()
+ {
+ // Droid stores MCP config in ~/.factory/mcp.json using the standard mcpServers
+ // container, so it must not override ServerContainerKey/HttpTypeValue/StdioTypeValue
+ // (those overrides are for clients with non-standard schemas like Kilo Code).
+ var client = new DroidConfigurator().Client;
+
+ Assert.IsTrue(string.IsNullOrEmpty(client.ServerContainerKey),
+ "Droid must use the default mcpServers container, not a client-specific one");
+ Assert.IsTrue(string.IsNullOrEmpty(client.HttpTypeValue),
+ "Droid must use the generic type:http for HTTP transport");
+ Assert.IsTrue(string.IsNullOrEmpty(client.StdioTypeValue),
+ "Droid must use the generic type:stdio for stdio transport");
+ Assert.IsFalse(client.IsVsCodeLayout,
+ "Droid must not use the VS Code servers/mcp.servers layout");
+ Assert.IsTrue(client.SupportsHttpTransport,
+ "Droid supports both stdio and HTTP transports");
+ }
+
+ [Test]
+ public void BuildManualConfigJson_ForDroid_UsesMcpServersContainerAndPlainHttp()
+ {
+ var client = new DroidConfigurator().Client;
+
+ var root = JObject.Parse(ConfigJsonBuilder.BuildManualConfigJson(uvPath: null, client));
+
+ Assert.IsNull(root["$schema"], "Droid must not write a $schema");
+ Assert.IsNull(root["mcp"], "Droid must not use a client-specific container");
+
+ var unity = (JObject)root.SelectToken("mcpServers.unityMCP");
+ Assert.NotNull(unity, "Expected mcpServers.unityMCP node");
+ Assert.AreEqual("http", (string)unity["type"],
+ "Droid HTTP config must use the generic type:http, not streamableHttp/remote");
+ Assert.IsNotNull(unity["url"], "HTTP transport should set a url");
+ Assert.IsNull(unity["command"], "HTTP transport should not include a command");
+ }
+
+ [Test]
+ public void DroidConfigurator_TargetsFactoryMcpJson_OnAllPlatforms()
+ {
+ var client = new DroidConfigurator().Client;
+ const string expectedFileName = "mcp.json";
+ const string expectedParentDirName = ".factory";
+
+ foreach (var path in new[] { client.windowsConfigPath, client.macConfigPath, client.linuxConfigPath })
+ {
+ Assert.AreEqual(expectedFileName, System.IO.Path.GetFileName(path),
+ "Droid config must target mcp.json");
+ Assert.AreEqual(expectedParentDirName, System.IO.Path.GetFileName(System.IO.Path.GetDirectoryName(path)),
+ "Droid config must live inside ~/.factory/");
+ }
+ }
+
+ [Test]
+ public void DroidConfigurator_SupportsSkills_AndInstallsUnderFactorySkills()
+ {
+ var droid = new DroidConfigurator();
+
+ Assert.IsTrue(droid.SupportsSkills, "Droid should support skill installation");
+ string skillPath = droid.GetSkillInstallPath();
+ Assert.IsNotNull(skillPath, "Skill install path must not be null when SupportsSkills is true");
+ StringAssert.Contains(".factory", skillPath,
+ "Droid skills should install under ~/.factory/skills/");
+ StringAssert.EndsWith("unity-mcp-skill", skillPath,
+ "Droid skill install path should end with the unity-mcp-skill subdirectory");
+ }
}
}
diff --git a/website/docs/getting-started/clients.md b/website/docs/getting-started/clients.md
index 0be1ff516..833b1deb1 100644
--- a/website/docs/getting-started/clients.md
+++ b/website/docs/getting-started/clients.md
@@ -26,6 +26,7 @@ MCP for Unity auto-configures every client the package detects on your machine.
| **Gemini CLI** | HTTP | yes | yes | yes | Auto-connects. |
| **OpenClaw** | HTTP / stdio | yes | yes | yes | Requires `openclaw-mcp-bridge` plugin enabled. Follows MCP for Unity's transport choice. |
| **Antigravity** | HTTP | yes | yes | varies | Requires an MCP toggle in Antigravity settings. |
+| **Droid** | HTTP / stdio | yes | yes | yes | Factory's agent. Config written to `~/.factory/mcp.json`. Follows MCP for Unity's transport choice. |
## How to pick
diff --git a/website/docs/getting-started/install.md b/website/docs/getting-started/install.md
index fa4159468..66acd3813 100644
--- a/website/docs/getting-started/install.md
+++ b/website/docs/getting-started/install.md
@@ -14,7 +14,7 @@ Three install paths are supported. Pick one. **Git URL** is the fastest if you j
- **Unity 2021.3 LTS or newer** — [Download Unity](https://unity.com/download)
- **Python 3.10+** with [`uv`](https://docs.astral.sh/uv/getting-started/installation/) — the setup wizard guides you through both if missing
-- **An MCP client** — [Claude Desktop](https://claude.ai/download), [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Cursor](https://www.cursor.com/), [VS Code Copilot](https://code.visualstudio.com/docs/copilot/overview), [GitHub Copilot CLI](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli), [Windsurf](https://windsurf.com/), [Cline](https://cline.bot/), [OpenClaw](https://openclaw.ai/), and more
+- **An MCP client** — [Claude Desktop](https://claude.ai/download), [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Cursor](https://www.cursor.com/), [VS Code Copilot](https://code.visualstudio.com/docs/copilot/overview), [GitHub Copilot CLI](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli), [Windsurf](https://windsurf.com/), [Cline](https://cline.bot/), [OpenClaw](https://openclaw.ai/), [Factory Droid](https://factory.ai/), and more
## Option 1 — Git URL (fastest)
diff --git a/website/docs/guides/client-configurators.md b/website/docs/guides/client-configurators.md
index 8cbdf101d..5219cdee7 100644
--- a/website/docs/guides/client-configurators.md
+++ b/website/docs/guides/client-configurators.md
@@ -89,6 +89,7 @@ At a high level:
Most MCP clients use a JSON config file that defines one or more MCP servers. Examples:
- **Cursor** – `JsonFileMcpConfigurator` (global `~/.cursor/mcp.json`).
+- **Droid** – `JsonFileMcpConfigurator` (global `~/.factory/mcp.json`, standard `mcpServers` layout; skills install to `~/.factory/skills/unity-mcp-skill`).
- **VSCode GitHub Copilot** – `JsonFileMcpConfigurator` with `IsVsCodeLayout = true`.
- **VSCode Insiders GitHub Copilot** – `JsonFileMcpConfigurator` with `IsVsCodeLayout = true` and Insider-specific `Code - Insiders/User/mcp.json` paths.
- **GitHub Copilot CLI** – `JsonFileMcpConfigurator` with standard HTTP transport.