Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion UnityMcpBridge/Editor/Tools/ManageScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -557,13 +557,20 @@ private static object ApplyTextEdits(
// If the edit overlaps the method span significantly, treat as replace_method
if (sp.start <= mStart + 2 && sp.end >= mStart + 1)
{
var methodOriginal = original.Substring(mStart, mLen);
int relStart = Math.Max(0, Math.Min(sp.start - mStart, methodOriginal.Length));
int relEnd = Math.Max(relStart, Math.Min(sp.end - mStart, methodOriginal.Length));
string replacementSnippet = methodOriginal
.Remove(relStart, relEnd - relStart)
.Insert(relStart, sp.text ?? string.Empty);

var structEdits = new JArray();
var op = new JObject
{
["mode"] = "replace_method",
["className"] = name,
["methodName"] = methodName,
["replacement"] = original.Remove(sp.start, sp.end - sp.start).Insert(sp.start, sp.text ?? string.Empty).Substring(mStart, (sp.text ?? string.Empty).Length + (sp.start - mStart) + (mLen - (sp.end - mStart)))
["replacement"] = replacementSnippet
};
structEdits.Add(op);
// Reuse structured path
Expand Down
29 changes: 26 additions & 3 deletions UnityMcpBridge/UnityMcpServer~/src/port_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from typing import Optional, List
import glob
import socket
import struct

logger = logging.getLogger("unity-mcp-server")

Expand Down Expand Up @@ -56,14 +57,36 @@ def list_candidate_files() -> List[Path]:
@staticmethod
def _try_probe_unity_mcp(port: int) -> bool:
"""Quickly check if a Unity MCP listener is on this port.
Tries a short TCP connect, sends 'ping', expects a JSON 'pong'.
Performs a short TCP connect and ping/pong exchange. If the
server advertises ``FRAMING=1`` in its greeting, the ping and
pong are sent/received with an 8-byte big-endian length prefix.
"""

def _read_exact(sock: socket.socket, count: int) -> bytes:
buf = bytearray()
while len(buf) < count:
chunk = sock.recv(count - len(buf))
if not chunk:
raise ConnectionError("Connection closed before reading expected bytes")
buf.extend(chunk)
return bytes(buf)

try:
with socket.create_connection(("127.0.0.1", port), PortDiscovery.CONNECT_TIMEOUT) as s:
s.settimeout(PortDiscovery.CONNECT_TIMEOUT)
try:
s.sendall(b"ping")
data = s.recv(512)
greeting = s.recv(256)
text = greeting.decode('ascii', errors='ignore') if greeting else ''
payload = b"ping"
if 'FRAMING=1' in text:
header = struct.pack('>Q', len(payload))
s.sendall(header + payload)
resp_header = _read_exact(s, 8)
resp_len = struct.unpack('>Q', resp_header)[0]
data = _read_exact(s, resp_len)
else:
s.sendall(payload)
data = s.recv(512)
# Minimal validation: look for a success pong response
if data and b'"message":"pong"' in data:
return True
Expand Down